@opensite/ui 1.8.2 → 1.8.4

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 (171) hide show
  1. package/dist/about-story-gallery.cjs +3 -30
  2. package/dist/about-story-gallery.d.cts +1 -1
  3. package/dist/about-story-gallery.d.ts +1 -1
  4. package/dist/about-story-gallery.js +3 -30
  5. package/dist/components.d.cts +1 -1
  6. package/dist/components.d.ts +1 -1
  7. package/dist/contact-callback.cjs +526 -273
  8. package/dist/contact-callback.d.cts +39 -59
  9. package/dist/contact-callback.d.ts +39 -59
  10. package/dist/contact-callback.js +528 -274
  11. package/dist/contact-card.cjs +459 -183
  12. package/dist/contact-card.d.cts +26 -49
  13. package/dist/contact-card.d.ts +26 -49
  14. package/dist/contact-card.js +461 -183
  15. package/dist/contact-careers.cjs +614 -510
  16. package/dist/contact-careers.d.cts +32 -55
  17. package/dist/contact-careers.d.ts +32 -55
  18. package/dist/contact-careers.js +616 -510
  19. package/dist/contact-catering.cjs +507 -501
  20. package/dist/contact-catering.d.cts +27 -61
  21. package/dist/contact-catering.d.ts +27 -61
  22. package/dist/contact-catering.js +509 -500
  23. package/dist/contact-consultation.cjs +484 -253
  24. package/dist/contact-consultation.d.cts +29 -56
  25. package/dist/contact-consultation.d.ts +29 -56
  26. package/dist/contact-consultation.js +486 -253
  27. package/dist/contact-dark.cjs +296 -296
  28. package/dist/contact-dark.d.cts +1 -1
  29. package/dist/contact-dark.d.ts +1 -1
  30. package/dist/contact-dark.js +297 -296
  31. package/dist/contact-demo.d.cts +1 -1
  32. package/dist/contact-demo.d.ts +1 -1
  33. package/dist/contact-emergency.d.cts +1 -1
  34. package/dist/contact-emergency.d.ts +1 -1
  35. package/dist/contact-event.d.cts +1 -1
  36. package/dist/contact-event.d.ts +1 -1
  37. package/dist/contact-faq.cjs +247 -250
  38. package/dist/contact-faq.d.cts +1 -1
  39. package/dist/contact-faq.d.ts +1 -1
  40. package/dist/contact-faq.js +248 -250
  41. package/dist/contact-feedback.d.cts +1 -1
  42. package/dist/contact-feedback.d.ts +1 -1
  43. package/dist/contact-fitness.d.cts +1 -1
  44. package/dist/contact-fitness.d.ts +1 -1
  45. package/dist/contact-guest.d.cts +1 -1
  46. package/dist/contact-guest.d.ts +1 -1
  47. package/dist/contact-image.d.cts +1 -1
  48. package/dist/contact-image.d.ts +1 -1
  49. package/dist/contact-insurance.d.cts +1 -1
  50. package/dist/contact-insurance.d.ts +1 -1
  51. package/dist/contact-interview.d.cts +1 -1
  52. package/dist/contact-interview.d.ts +1 -1
  53. package/dist/contact-locations.d.cts +1 -1
  54. package/dist/contact-locations.d.ts +1 -1
  55. package/dist/contact-maintenance.d.cts +1 -1
  56. package/dist/contact-maintenance.d.ts +1 -1
  57. package/dist/contact-map.d.cts +1 -1
  58. package/dist/contact-map.d.ts +1 -1
  59. package/dist/contact-minimal.d.cts +1 -1
  60. package/dist/contact-minimal.d.ts +1 -1
  61. package/dist/contact-moving.d.cts +1 -1
  62. package/dist/contact-moving.d.ts +1 -1
  63. package/dist/contact-multistep.d.cts +1 -1
  64. package/dist/contact-multistep.d.ts +1 -1
  65. package/dist/contact-partnership.d.cts +1 -1
  66. package/dist/contact-partnership.d.ts +1 -1
  67. package/dist/contact-photography.cjs +247 -250
  68. package/dist/contact-photography.d.cts +1 -1
  69. package/dist/contact-photography.d.ts +1 -1
  70. package/dist/contact-photography.js +248 -250
  71. package/dist/contact-press.d.cts +1 -1
  72. package/dist/contact-press.d.ts +1 -1
  73. package/dist/contact-quote.d.cts +1 -1
  74. package/dist/contact-quote.d.ts +1 -1
  75. package/dist/contact-referral.d.cts +1 -1
  76. package/dist/contact-referral.d.ts +1 -1
  77. package/dist/contact-report.d.cts +1 -1
  78. package/dist/contact-report.d.ts +1 -1
  79. package/dist/contact-reservation.d.cts +1 -1
  80. package/dist/contact-reservation.d.ts +1 -1
  81. package/dist/contact-retreat.d.cts +1 -1
  82. package/dist/contact-retreat.d.ts +1 -1
  83. package/dist/contact-rsvp.d.cts +1 -1
  84. package/dist/contact-rsvp.d.ts +1 -1
  85. package/dist/contact-sales.d.cts +1 -1
  86. package/dist/contact-sales.d.ts +1 -1
  87. package/dist/contact-schedule.d.cts +1 -1
  88. package/dist/contact-schedule.d.ts +1 -1
  89. package/dist/contact-sponsorship.d.cts +1 -1
  90. package/dist/contact-sponsorship.d.ts +1 -1
  91. package/dist/contact-support.d.cts +1 -1
  92. package/dist/contact-support.d.ts +1 -1
  93. package/dist/contact-tenant.d.cts +1 -1
  94. package/dist/contact-tenant.d.ts +1 -1
  95. package/dist/contact-vendor.d.cts +1 -1
  96. package/dist/contact-vendor.d.ts +1 -1
  97. package/dist/contact-volunteer.d.cts +1 -1
  98. package/dist/contact-volunteer.d.ts +1 -1
  99. package/dist/contact-warranty.d.cts +1 -1
  100. package/dist/contact-warranty.d.ts +1 -1
  101. package/dist/contact-wedding.d.cts +1 -1
  102. package/dist/contact-wedding.d.ts +1 -1
  103. package/dist/cta-app-download-newsletter.d.cts +1 -1
  104. package/dist/cta-app-download-newsletter.d.ts +1 -1
  105. package/dist/cta-newsletter-features.d.cts +1 -1
  106. package/dist/cta-newsletter-features.d.ts +1 -1
  107. package/dist/footer-accordion-social.d.cts +1 -1
  108. package/dist/footer-accordion-social.d.ts +1 -1
  109. package/dist/footer-newsletter-contact.d.cts +1 -1
  110. package/dist/footer-newsletter-contact.d.ts +1 -1
  111. package/dist/footer-newsletter-minimal.d.cts +1 -1
  112. package/dist/footer-newsletter-minimal.d.ts +1 -1
  113. package/dist/footer-split-image-accordion.d.cts +1 -1
  114. package/dist/footer-split-image-accordion.d.ts +1 -1
  115. package/dist/{forms-nGgHUTBw.d.cts → forms-CStlFhnh.d.cts} +41 -0
  116. package/dist/{forms-nGgHUTBw.d.ts → forms-CStlFhnh.d.ts} +41 -0
  117. package/dist/hero-conversation-intelligence.cjs +1 -2
  118. package/dist/hero-conversation-intelligence.d.cts +1 -5
  119. package/dist/hero-conversation-intelligence.d.ts +1 -5
  120. package/dist/hero-conversation-intelligence.js +1 -2
  121. package/dist/hero-conversion-video-play.cjs +2 -2
  122. package/dist/hero-conversion-video-play.js +2 -2
  123. package/dist/hero-design-system-3d.cjs +162 -82
  124. package/dist/hero-design-system-3d.js +162 -82
  125. package/dist/hero-ecommerce-product-showcase.cjs +103 -81
  126. package/dist/hero-ecommerce-product-showcase.d.cts +5 -1
  127. package/dist/hero-ecommerce-product-showcase.d.ts +5 -1
  128. package/dist/hero-ecommerce-product-showcase.js +103 -81
  129. package/dist/hero-floating-images.cjs +1 -1
  130. package/dist/hero-floating-images.js +1 -1
  131. package/dist/hero-hiring-animated-text.cjs +4 -4
  132. package/dist/hero-hiring-animated-text.js +4 -4
  133. package/dist/hero-minimal-centered-dark.cjs +111 -82
  134. package/dist/hero-minimal-centered-dark.d.cts +1 -1
  135. package/dist/hero-minimal-centered-dark.d.ts +1 -1
  136. package/dist/hero-minimal-centered-dark.js +111 -82
  137. package/dist/hero-mobile-app-download.cjs +1 -1
  138. package/dist/hero-mobile-app-download.js +1 -1
  139. package/dist/hero-overlay-cta-grid.cjs +1 -1
  140. package/dist/hero-overlay-cta-grid.js +1 -1
  141. package/dist/hero-spiral-pattern-cards.cjs +1 -1
  142. package/dist/hero-spiral-pattern-cards.js +1 -1
  143. package/dist/hero-startup-launch-cta.cjs +1 -1
  144. package/dist/hero-startup-launch-cta.js +1 -1
  145. package/dist/hero-stats-social-proof.cjs +106 -90
  146. package/dist/hero-stats-social-proof.js +106 -90
  147. package/dist/hero-testimonial-image-grid.cjs +1 -1
  148. package/dist/hero-testimonial-image-grid.js +1 -1
  149. package/dist/hero-therapy-testimonial-grid.cjs +1 -1
  150. package/dist/hero-therapy-testimonial-grid.js +1 -1
  151. package/dist/hero-ui-library-showcase.cjs +63 -15
  152. package/dist/hero-ui-library-showcase.d.cts +5 -1
  153. package/dist/hero-ui-library-showcase.d.ts +5 -1
  154. package/dist/hero-ui-library-showcase.js +63 -15
  155. package/dist/index.cjs +44 -6
  156. package/dist/index.d.cts +3 -2
  157. package/dist/index.d.ts +3 -2
  158. package/dist/index.js +44 -6
  159. package/dist/link-page-newsletter-social.d.cts +1 -1
  160. package/dist/link-page-newsletter-social.d.ts +1 -1
  161. package/dist/offer-modal-membership-image.d.cts +1 -1
  162. package/dist/offer-modal-membership-image.d.ts +1 -1
  163. package/dist/offer-modal-newsletter-discount.d.cts +1 -1
  164. package/dist/offer-modal-newsletter-discount.d.ts +1 -1
  165. package/dist/offer-modal-sheet-newsletter.d.cts +1 -1
  166. package/dist/offer-modal-sheet-newsletter.d.ts +1 -1
  167. package/dist/registry.cjs +14465 -14767
  168. package/dist/registry.js +12664 -12966
  169. package/dist/resource-list-hero-filter.d.cts +1 -1
  170. package/dist/resource-list-hero-filter.d.ts +1 -1
  171. package/package.json +3 -3
@@ -3,12 +3,11 @@
3
3
 
4
4
  var React = require('react');
5
5
  var forms = require('@page-speed/forms');
6
- var inputs = require('@page-speed/forms/inputs');
7
6
  var clsx = require('clsx');
8
7
  var tailwindMerge = require('tailwind-merge');
9
8
  var classVarianceAuthority = require('class-variance-authority');
10
9
  var jsxRuntime = require('react/jsx-runtime');
11
- var LabelPrimitive = require('@radix-ui/react-label');
10
+ var inputs = require('@page-speed/forms/inputs');
12
11
  var integration = require('@page-speed/forms/integration');
13
12
 
14
13
  function _interopNamespace(e) {
@@ -30,11 +29,8 @@ function _interopNamespace(e) {
30
29
  }
31
30
 
32
31
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
- var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
34
32
 
35
33
  // components/blocks/contact/contact-callback.tsx
36
- var TextInput = inputs.TextInput;
37
- var TextArea = inputs.TextArea;
38
34
  function cn(...inputs) {
39
35
  return tailwindMerge.twMerge(clsx.clsx(inputs));
40
36
  }
@@ -381,6 +377,7 @@ var Pressable = React__namespace.forwardRef(
381
377
  rel,
382
378
  linkType,
383
379
  isInternal,
380
+ isExternal,
384
381
  handleClick
385
382
  } = navigation;
386
383
  const shouldRenderLink = normalizedHref && linkType !== "none";
@@ -584,22 +581,371 @@ function CardContent({ className, ...props }) {
584
581
  }
585
582
  );
586
583
  }
587
- function Label({
584
+ function DynamicFormField({
585
+ field,
588
586
  className,
589
- ...props
587
+ uploadProgress = {},
588
+ onFileUpload,
589
+ onFileRemove,
590
+ isUploading = false
590
591
  }) {
592
+ const fieldId = field.name;
593
+ const usesGroupLegend = field.type === "radio" || field.type === "checkbox-group";
594
+ const usesInlineCheckboxLabel = field.type === "checkbox";
595
+ const shouldRenderFieldLabel = !usesGroupLegend && !usesInlineCheckboxLabel;
596
+ const checkboxLabel = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
597
+ field.label,
598
+ field.required ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive ml-1", children: "*" }) : null
599
+ ] });
591
600
  return /* @__PURE__ */ jsxRuntime.jsx(
592
- LabelPrimitive__namespace.Root,
601
+ forms.Field,
593
602
  {
594
- "data-slot": "label",
595
- className: cn(
596
- "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",
597
- className
598
- ),
599
- ...props
603
+ name: field.name,
604
+ label: shouldRenderFieldLabel ? field.label : void 0,
605
+ description: shouldRenderFieldLabel ? field.description : void 0,
606
+ required: field.required,
607
+ className: cn("space-y-2", className),
608
+ children: ({ field: formField, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
609
+ (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsxRuntime.jsx(
610
+ inputs.TextInput,
611
+ {
612
+ ...formField,
613
+ id: fieldId,
614
+ type: field.type,
615
+ placeholder: field.placeholder,
616
+ error: meta.touched && !!meta.error,
617
+ disabled: field.disabled,
618
+ "aria-label": field.label
619
+ }
620
+ ),
621
+ field.type === "number" && /* @__PURE__ */ jsxRuntime.jsx(
622
+ inputs.TextInput,
623
+ {
624
+ ...formField,
625
+ id: fieldId,
626
+ type: "text",
627
+ placeholder: field.placeholder,
628
+ error: meta.touched && !!meta.error,
629
+ disabled: field.disabled,
630
+ "aria-label": field.label
631
+ }
632
+ ),
633
+ field.type === "textarea" && /* @__PURE__ */ jsxRuntime.jsx(
634
+ inputs.TextArea,
635
+ {
636
+ ...formField,
637
+ id: fieldId,
638
+ placeholder: field.placeholder,
639
+ rows: field.rows || 4,
640
+ error: meta.touched && !!meta.error,
641
+ disabled: field.disabled,
642
+ "aria-label": field.label
643
+ }
644
+ ),
645
+ field.type === "select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
646
+ inputs.Select,
647
+ {
648
+ ...formField,
649
+ id: fieldId,
650
+ options: field.options,
651
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
652
+ error: meta.touched && !!meta.error,
653
+ disabled: field.disabled,
654
+ "aria-label": field.label
655
+ }
656
+ ),
657
+ field.type === "multi-select" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
658
+ inputs.MultiSelect,
659
+ {
660
+ ...formField,
661
+ id: fieldId,
662
+ options: field.options,
663
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
664
+ error: meta.touched && !!meta.error,
665
+ disabled: field.disabled,
666
+ "aria-label": field.label
667
+ }
668
+ ),
669
+ field.type === "radio" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
670
+ inputs.Radio,
671
+ {
672
+ ...formField,
673
+ id: fieldId,
674
+ options: field.options,
675
+ label: field.label,
676
+ description: field.description,
677
+ required: field.required,
678
+ disabled: field.disabled,
679
+ layout: field.layout || "stacked",
680
+ error: meta.touched && !!meta.error,
681
+ "aria-label": field.label
682
+ }
683
+ ),
684
+ field.type === "checkbox" && /* @__PURE__ */ jsxRuntime.jsx(
685
+ inputs.Checkbox,
686
+ {
687
+ ...formField,
688
+ id: fieldId,
689
+ value: formField.value === true || formField.value === "true",
690
+ onChange: (checked) => formField.onChange(checked),
691
+ label: checkboxLabel,
692
+ description: field.description,
693
+ disabled: field.disabled,
694
+ required: field.required,
695
+ error: meta.touched && !!meta.error,
696
+ "aria-label": field.label
697
+ }
698
+ ),
699
+ field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsxRuntime.jsx(
700
+ inputs.CheckboxGroup,
701
+ {
702
+ ...formField,
703
+ id: fieldId,
704
+ options: field.options,
705
+ label: field.label,
706
+ description: field.description,
707
+ required: field.required,
708
+ disabled: field.disabled,
709
+ layout: field.layout || "stacked",
710
+ error: meta.touched && !!meta.error,
711
+ "aria-label": field.label
712
+ }
713
+ ),
714
+ (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsxRuntime.jsx(
715
+ inputs.DatePicker,
716
+ {
717
+ ...formField,
718
+ id: fieldId,
719
+ placeholder: field.placeholder,
720
+ error: meta.touched && !!meta.error,
721
+ disabled: field.disabled,
722
+ "aria-label": field.label
723
+ }
724
+ ),
725
+ field.type === "date-range" && /* @__PURE__ */ jsxRuntime.jsx(
726
+ inputs.DateRangePicker,
727
+ {
728
+ ...formField,
729
+ id: fieldId,
730
+ placeholder: field.placeholder,
731
+ error: meta.touched && !!meta.error,
732
+ disabled: field.disabled,
733
+ "aria-label": field.label
734
+ }
735
+ ),
736
+ field.type === "time" && /* @__PURE__ */ jsxRuntime.jsx(
737
+ inputs.TimePicker,
738
+ {
739
+ ...formField,
740
+ id: fieldId,
741
+ placeholder: field.placeholder,
742
+ error: meta.touched && !!meta.error,
743
+ disabled: field.disabled,
744
+ "aria-label": field.label
745
+ }
746
+ ),
747
+ field.type === "file" && /* @__PURE__ */ jsxRuntime.jsx(
748
+ inputs.FileInput,
749
+ {
750
+ ...formField,
751
+ id: fieldId,
752
+ accept: field.accept,
753
+ maxSize: field.maxSize || 5 * 1024 * 1024,
754
+ maxFiles: field.maxFiles || 1,
755
+ multiple: field.multiple || false,
756
+ placeholder: field.placeholder || "Choose file(s)...",
757
+ error: meta.touched && !!meta.error,
758
+ disabled: field.disabled || isUploading,
759
+ showProgress: true,
760
+ uploadProgress,
761
+ onChange: (files) => {
762
+ formField.onChange(files);
763
+ if (files.length > 0 && onFileUpload) {
764
+ onFileUpload(files);
765
+ }
766
+ },
767
+ onFileRemove,
768
+ "aria-label": field.label
769
+ }
770
+ ),
771
+ field.type === "rich-text" && /* @__PURE__ */ jsxRuntime.jsx(
772
+ inputs.RichTextEditor,
773
+ {
774
+ ...formField,
775
+ id: fieldId,
776
+ placeholder: field.placeholder,
777
+ error: meta.touched && !!meta.error,
778
+ disabled: field.disabled,
779
+ "aria-label": field.label
780
+ }
781
+ )
782
+ ] })
600
783
  }
601
784
  );
602
785
  }
786
+
787
+ // lib/form-field-types.ts
788
+ function generateInitialValues(fields) {
789
+ return fields.reduce(
790
+ (acc, field) => {
791
+ if (field.type === "checkbox") {
792
+ acc[field.name] = false;
793
+ } else if (field.type === "checkbox-group" || field.type === "multi-select") {
794
+ acc[field.name] = [];
795
+ } else if (field.type === "file") {
796
+ acc[field.name] = [];
797
+ } else if (field.type === "date-range") {
798
+ acc[field.name] = { start: null, end: null };
799
+ } else {
800
+ acc[field.name] = "";
801
+ }
802
+ return acc;
803
+ },
804
+ {}
805
+ );
806
+ }
807
+ function generateValidationSchema(fields) {
808
+ return fields.reduce(
809
+ (acc, field) => {
810
+ acc[field.name] = (value, allValues) => {
811
+ if (field.required) {
812
+ if (!value || typeof value === "string" && !value.trim()) {
813
+ return `${field.label} is required`;
814
+ }
815
+ }
816
+ if (field.type === "email" && value) {
817
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
818
+ return "Please enter a valid email address";
819
+ }
820
+ }
821
+ if (field.type === "url" && value) {
822
+ try {
823
+ new URL(value);
824
+ } catch {
825
+ return "Please enter a valid URL";
826
+ }
827
+ }
828
+ if (field.validator) {
829
+ return field.validator(value, allValues);
830
+ }
831
+ return void 0;
832
+ };
833
+ return acc;
834
+ },
835
+ {}
836
+ );
837
+ }
838
+ function getColumnSpanClass(span) {
839
+ if (!span || span === 12) return "col-span-12";
840
+ return `col-span-12 sm:col-span-${Math.min(span, 12)}`;
841
+ }
842
+ function useContactForm(options) {
843
+ const {
844
+ formFields,
845
+ formConfig,
846
+ onSubmit,
847
+ onSuccess,
848
+ onError,
849
+ resetOnSuccess = true,
850
+ uploadTokens = []
851
+ } = options;
852
+ const [submissionError, setSubmissionError] = React.useState(null);
853
+ const submissionConfig = formConfig?.submissionConfig;
854
+ const redirectUrl = submissionConfig?.redirectUrl;
855
+ const redirectNavigation = useNavigation({ href: redirectUrl });
856
+ const resetSubmissionState = React.useCallback(() => {
857
+ setSubmissionError(null);
858
+ }, []);
859
+ const performRedirect = React.useCallback(() => {
860
+ if (!redirectUrl || typeof window === "undefined") {
861
+ return;
862
+ }
863
+ const navigate = () => {
864
+ if (redirectNavigation.shouldUseRouter && redirectNavigation.normalizedHref) {
865
+ const handler = window.__opensiteNavigationHandler;
866
+ if (typeof handler === "function") {
867
+ try {
868
+ const handled = handler(redirectNavigation.normalizedHref, void 0);
869
+ if (handled !== false) {
870
+ return;
871
+ }
872
+ } catch (error) {
873
+ console.error("Internal redirect handler failed:", error);
874
+ }
875
+ }
876
+ }
877
+ const destination = redirectNavigation.normalizedHref || redirectUrl;
878
+ window.location.assign(destination);
879
+ };
880
+ window.setTimeout(navigate, 150);
881
+ }, [redirectNavigation, redirectUrl]);
882
+ const form = forms.useForm({
883
+ initialValues: React.useMemo(
884
+ () => generateInitialValues(formFields),
885
+ [formFields]
886
+ ),
887
+ validationSchema: React.useMemo(
888
+ () => generateValidationSchema(formFields),
889
+ [formFields]
890
+ ),
891
+ onSubmit: async (values, helpers) => {
892
+ resetSubmissionState();
893
+ const shouldAutoSubmit = Boolean(formConfig?.endpoint);
894
+ if (!shouldAutoSubmit && !onSubmit) {
895
+ return;
896
+ }
897
+ try {
898
+ let result;
899
+ const submissionValues = {
900
+ ...values,
901
+ ...uploadTokens.length > 0 && {
902
+ contact_form_upload_tokens: uploadTokens
903
+ }
904
+ };
905
+ if (shouldAutoSubmit) {
906
+ result = await submitPageSpeedForm(submissionValues, formConfig);
907
+ }
908
+ if (onSubmit) {
909
+ await onSubmit(submissionValues);
910
+ }
911
+ if (shouldAutoSubmit || onSubmit) {
912
+ try {
913
+ await submissionConfig?.handleFormSubmission?.({
914
+ formData: submissionValues,
915
+ responseData: result
916
+ });
917
+ } catch (callbackError) {
918
+ console.error("handleFormSubmission callback failed:", callbackError);
919
+ }
920
+ if (resetOnSuccess) {
921
+ helpers.resetForm();
922
+ }
923
+ onSuccess?.(result);
924
+ if (submissionConfig?.behavior === "redirect" && submissionConfig.redirectUrl) {
925
+ performRedirect();
926
+ }
927
+ }
928
+ } catch (error) {
929
+ if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
930
+ helpers.setErrors(error.formErrors);
931
+ }
932
+ const errorMessage = error instanceof Error ? error.message : "Form submission failed";
933
+ setSubmissionError(errorMessage);
934
+ onError?.(error);
935
+ }
936
+ }
937
+ });
938
+ const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
939
+ return {
940
+ form,
941
+ isSubmitted: form.status === "success",
942
+ submissionError,
943
+ formMethod,
944
+ resetSubmissionState
945
+ };
946
+ }
947
+
948
+ // lib/forms.ts
603
949
  var PageSpeedFormSubmissionError = class extends Error {
604
950
  constructor(message, options = {}) {
605
951
  super(message);
@@ -1090,41 +1436,121 @@ var Section = React__namespace.default.forwardRef(
1090
1436
  }
1091
1437
  );
1092
1438
  Section.displayName = "Section";
1093
- var TIME_SLOTS = [
1094
- "9:00 AM",
1095
- "10:00 AM",
1096
- "11:00 AM",
1097
- "12:00 PM",
1098
- "1:00 PM",
1099
- "2:00 PM",
1100
- "3:00 PM",
1101
- "4:00 PM",
1102
- "5:00 PM"
1103
- ];
1104
- var TOPICS = [
1105
- "Product Demo",
1106
- "Sales Inquiry",
1107
- "Technical Support",
1108
- "Partnership",
1109
- "General Question"
1110
- ];
1111
- var TIMEZONES = [
1112
- { value: "est", label: "Eastern Time (EST)" },
1113
- { value: "cst", label: "Central Time (CST)" },
1114
- { value: "mst", label: "Mountain Time (MST)" },
1115
- { value: "pst", label: "Pacific Time (PST)" }
1439
+ var DEFAULT_FORM_FIELDS = [
1440
+ {
1441
+ name: "name",
1442
+ type: "text",
1443
+ label: "Full Name",
1444
+ placeholder: "John Doe",
1445
+ required: true,
1446
+ columnSpan: 6
1447
+ },
1448
+ {
1449
+ name: "company",
1450
+ type: "text",
1451
+ label: "Company",
1452
+ placeholder: "Acme Inc.",
1453
+ required: false,
1454
+ columnSpan: 6
1455
+ },
1456
+ {
1457
+ name: "email",
1458
+ type: "email",
1459
+ label: "Email Address",
1460
+ placeholder: "john@example.com",
1461
+ required: true,
1462
+ columnSpan: 6
1463
+ },
1464
+ {
1465
+ name: "phone",
1466
+ type: "tel",
1467
+ label: "Phone Number",
1468
+ placeholder: "+1 (555) 000-0000",
1469
+ required: true,
1470
+ columnSpan: 6
1471
+ },
1472
+ {
1473
+ name: "date",
1474
+ type: "date",
1475
+ label: "Preferred Date",
1476
+ placeholder: "",
1477
+ required: true,
1478
+ columnSpan: 6
1479
+ },
1480
+ {
1481
+ name: "time",
1482
+ type: "select",
1483
+ label: "Preferred Time",
1484
+ placeholder: "Select a time",
1485
+ required: true,
1486
+ columnSpan: 6,
1487
+ options: [
1488
+ { value: "9:00 AM", label: "9:00 AM" },
1489
+ { value: "10:00 AM", label: "10:00 AM" },
1490
+ { value: "11:00 AM", label: "11:00 AM" },
1491
+ { value: "12:00 PM", label: "12:00 PM" },
1492
+ { value: "1:00 PM", label: "1:00 PM" },
1493
+ { value: "2:00 PM", label: "2:00 PM" },
1494
+ { value: "3:00 PM", label: "3:00 PM" },
1495
+ { value: "4:00 PM", label: "4:00 PM" },
1496
+ { value: "5:00 PM", label: "5:00 PM" }
1497
+ ]
1498
+ },
1499
+ {
1500
+ name: "timezone",
1501
+ type: "select",
1502
+ label: "Timezone",
1503
+ placeholder: "",
1504
+ required: true,
1505
+ columnSpan: 12,
1506
+ options: [
1507
+ { value: "est", label: "Eastern Time (EST)" },
1508
+ { value: "cst", label: "Central Time (CST)" },
1509
+ { value: "mst", label: "Mountain Time (MST)" },
1510
+ { value: "pst", label: "Pacific Time (PST)" }
1511
+ ]
1512
+ },
1513
+ {
1514
+ name: "topic",
1515
+ type: "select",
1516
+ label: "Topic",
1517
+ placeholder: "Select a topic",
1518
+ required: true,
1519
+ columnSpan: 12,
1520
+ options: [
1521
+ { value: "product-demo", label: "Product Demo" },
1522
+ { value: "sales-inquiry", label: "Sales Inquiry" },
1523
+ { value: "technical-support", label: "Technical Support" },
1524
+ { value: "partnership", label: "Partnership" },
1525
+ { value: "general-question", label: "General Question" }
1526
+ ]
1527
+ },
1528
+ {
1529
+ name: "details",
1530
+ type: "textarea",
1531
+ label: "Additional Details (Optional)",
1532
+ placeholder: "Help us prepare for the call by sharing any specific questions or topics you'd like to cover...",
1533
+ required: false,
1534
+ rows: 4,
1535
+ columnSpan: 12
1536
+ }
1116
1537
  ];
1117
1538
  function ContactCallback({
1118
1539
  heading,
1119
1540
  description,
1120
- buttonText,
1541
+ buttonText = "Schedule Callback",
1121
1542
  buttonIcon = /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/phone", size: 16 }),
1122
1543
  actions,
1123
1544
  actionsSlot,
1124
- footer,
1125
- footerSlot,
1545
+ formFields,
1546
+ successMessage = "Thank you! Your callback request has been received.",
1547
+ infoSectionLabel,
1548
+ scheduleSectionLabel,
1549
+ topicSectionLabel,
1550
+ callbackProcessLabel,
1551
+ callbackProcessDescription,
1126
1552
  className,
1127
- containerClassName,
1553
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
1128
1554
  headerClassName,
1129
1555
  headingClassName,
1130
1556
  descriptionClassName,
@@ -1132,75 +1558,40 @@ function ContactCallback({
1132
1558
  cardContentClassName,
1133
1559
  formClassName,
1134
1560
  submitClassName,
1135
- footerClassName,
1136
- background = "white",
1137
- spacing = "xl",
1561
+ successMessageClassName,
1562
+ errorMessageClassName,
1563
+ background,
1564
+ spacing = "py-8 md:py-32",
1138
1565
  pattern,
1139
- patternOpacity = 0.1,
1566
+ patternOpacity,
1140
1567
  formConfig,
1141
1568
  onSubmit,
1142
1569
  onSuccess,
1143
1570
  onError
1144
1571
  }) {
1145
- const form = forms.useForm({
1146
- initialValues: {
1147
- name: "",
1148
- company: "",
1149
- email: "",
1150
- phone: "",
1151
- date: "",
1152
- time: "",
1153
- timezone: "est",
1154
- topic: "",
1155
- details: ""
1156
- },
1157
- validationSchema: {
1158
- name: (value) => !value ? "Name is required" : void 0,
1159
- email: (value) => {
1160
- if (!value) return "Email is required";
1161
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
1162
- return "Please enter a valid email address";
1163
- return void 0;
1164
- },
1165
- phone: (value) => !value ? "Phone number is required" : void 0,
1166
- date: (value) => !value ? "Date is required" : void 0,
1167
- time: (value) => !value ? "Time is required" : void 0,
1168
- topic: (value) => !value ? "Topic is required" : void 0
1169
- },
1170
- onSubmit: async (values, helpers) => {
1171
- const shouldAutoSubmit = Boolean(formConfig?.endpoint);
1172
- if (!shouldAutoSubmit && !onSubmit) {
1173
- return;
1174
- }
1175
- try {
1176
- let result;
1177
- if (shouldAutoSubmit) {
1178
- result = await submitPageSpeedForm(values, formConfig);
1179
- }
1180
- if (onSubmit) {
1181
- await onSubmit(values);
1182
- }
1183
- if (shouldAutoSubmit || onSubmit) {
1184
- if (formConfig?.resetOnSuccess !== false) {
1185
- helpers.resetForm();
1186
- }
1187
- onSuccess?.(result);
1188
- }
1189
- } catch (error) {
1190
- if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
1191
- helpers.setErrors(error.formErrors);
1192
- }
1193
- onError?.(error);
1194
- throw error;
1195
- }
1196
- }
1572
+ const fields = React.useMemo(
1573
+ () => formFields || DEFAULT_FORM_FIELDS,
1574
+ [formFields]
1575
+ );
1576
+ const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
1577
+ formFields: fields,
1578
+ formConfig,
1579
+ onSubmit,
1580
+ onSuccess,
1581
+ onError
1197
1582
  });
1198
- const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
1199
- const actionsContent = React__namespace.useMemo(() => {
1583
+ const actionsContent = React.useMemo(() => {
1200
1584
  if (actionsSlot) return actionsSlot;
1201
1585
  if (actions && actions.length > 0) {
1202
1586
  return actions.map((action, index) => {
1203
- const { label, icon, iconAfter, children, className: actionClassName, ...pressableProps } = action;
1587
+ const {
1588
+ label,
1589
+ icon,
1590
+ iconAfter,
1591
+ children,
1592
+ className: actionClassName,
1593
+ ...pressableProps
1594
+ } = action;
1204
1595
  return /* @__PURE__ */ jsxRuntime.jsx(
1205
1596
  Pressable,
1206
1597
  {
@@ -1219,13 +1610,6 @@ function ContactCallback({
1219
1610
  }
1220
1611
  return null;
1221
1612
  }, [actionsSlot, actions]);
1222
- const footerContent = React__namespace.useMemo(() => {
1223
- if (footerSlot) return footerSlot;
1224
- if (footer) {
1225
- return typeof footer === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-6 text-center text-sm text-muted-foreground", footerClassName), children: footer }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("mt-6 text-center text-sm text-muted-foreground", footerClassName), children: footer });
1226
- }
1227
- return null;
1228
- }, [footerSlot, footer, footerClassName]);
1229
1613
  return /* @__PURE__ */ jsxRuntime.jsx(
1230
1614
  Section,
1231
1615
  {
@@ -1233,11 +1617,21 @@ function ContactCallback({
1233
1617
  spacing,
1234
1618
  pattern,
1235
1619
  patternOpacity,
1236
- className: cn("pb-12", className),
1237
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mx-auto max-w-4xl px-4", containerClassName), children: [
1238
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
1239
- heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h2", { className: cn("mb-3 text-3xl font-bold tracking-tight", headingClassName), children: heading }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
1240
- description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("leading-relaxed text-muted-foreground", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description }))
1620
+ className,
1621
+ containerClassName,
1622
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1623
+ (heading || description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
1624
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
1625
+ "h2",
1626
+ {
1627
+ className: cn(
1628
+ "mb-3 text-3xl font-bold tracking-tight",
1629
+ headingClassName
1630
+ ),
1631
+ children: heading
1632
+ }
1633
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
1634
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("leading-relaxed", descriptionClassName), children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description }))
1241
1635
  ] }),
1242
1636
  /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cardClassName, children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: cn("p-6 lg:p-8", cardContentClassName), children: /* @__PURE__ */ jsxRuntime.jsxs(
1243
1637
  forms.Form,
@@ -1245,174 +1639,34 @@ function ContactCallback({
1245
1639
  form,
1246
1640
  action: formConfig?.endpoint,
1247
1641
  method: formMethod,
1642
+ submissionError,
1643
+ successMessage,
1644
+ successMessageClassName,
1645
+ errorMessageClassName,
1646
+ submissionConfig: formConfig?.submissionConfig,
1647
+ onNewSubmission: resetSubmissionState,
1248
1648
  className: cn("space-y-6", formClassName),
1249
1649
  children: [
1250
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1251
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-semibold", children: "Your Information" }),
1252
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2", children: [
1253
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "name", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1254
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "name", children: "Full Name" }),
1255
- /* @__PURE__ */ jsxRuntime.jsx(
1256
- TextInput,
1257
- {
1258
- ...field,
1259
- id: "name",
1260
- placeholder: "John Doe",
1261
- error: meta.touched && !!meta.error,
1262
- "aria-label": "Full Name"
1263
- }
1264
- )
1265
- ] }) }),
1266
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "company", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1267
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "company", children: "Company" }),
1268
- /* @__PURE__ */ jsxRuntime.jsx(
1269
- TextInput,
1270
- {
1271
- ...field,
1272
- id: "company",
1273
- placeholder: "Acme Inc.",
1274
- error: meta.touched && !!meta.error,
1275
- "aria-label": "Company"
1276
- }
1277
- )
1278
- ] }) })
1279
- ] })
1280
- ] }),
1281
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2", children: [
1282
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1283
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email Address" }),
1284
- /* @__PURE__ */ jsxRuntime.jsx(
1285
- TextInput,
1286
- {
1287
- ...field,
1288
- id: "email",
1289
- type: "email",
1290
- placeholder: "john@example.com",
1291
- error: meta.touched && !!meta.error,
1292
- "aria-label": "Email Address"
1293
- }
1294
- )
1295
- ] }) }),
1296
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "phone", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1297
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "phone", children: "Phone Number" }),
1298
- /* @__PURE__ */ jsxRuntime.jsx(
1299
- TextInput,
1300
- {
1301
- ...field,
1302
- id: "phone",
1303
- type: "tel",
1304
- placeholder: "+1 (555) 000-0000",
1305
- error: meta.touched && !!meta.error,
1306
- "aria-label": "Phone Number"
1307
- }
1308
- )
1309
- ] }) })
1310
- ] }),
1311
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-6", children: [
1312
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-semibold", children: "Preferred Callback Time" }),
1313
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-6 sm:grid-cols-2", children: [
1314
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "date", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1315
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "date", children: "Preferred Date" }),
1316
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1317
- /* @__PURE__ */ jsxRuntime.jsx(
1318
- TextInput,
1319
- {
1320
- ...field,
1321
- id: "date",
1322
- type: "date",
1323
- className: "pl-10",
1324
- error: meta.touched && !!meta.error,
1325
- "aria-label": "Preferred Date"
1326
- }
1327
- ),
1328
- /* @__PURE__ */ jsxRuntime.jsx(
1329
- DynamicIcon,
1330
- {
1331
- name: "lucide/calendar",
1332
- size: 20,
1333
- className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"
1334
- }
1335
- )
1336
- ] })
1337
- ] }) }),
1338
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "time", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1339
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "time", children: "Preferred Time" }),
1340
- /* @__PURE__ */ jsxRuntime.jsxs(
1341
- inputs.Select,
1342
- {
1343
- ...field,
1344
- id: "time",
1345
- error: meta.touched && !!meta.error,
1346
- "aria-label": "Preferred Time",
1347
- children: [
1348
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select a time" }),
1349
- TIME_SLOTS.map((slot) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: slot, children: slot }, slot))
1350
- ]
1351
- }
1352
- )
1353
- ] }) })
1354
- ] }),
1355
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "timezone", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1356
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "timezone", children: "Timezone" }),
1357
- /* @__PURE__ */ jsxRuntime.jsx(
1358
- inputs.Select,
1359
- {
1360
- ...field,
1361
- id: "timezone",
1362
- error: meta.touched && !!meta.error,
1363
- "aria-label": "Timezone",
1364
- children: TIMEZONES.map((tz) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: tz.value, children: tz.label }, tz.value))
1365
- }
1366
- )
1367
- ] }) }) })
1368
- ] }),
1369
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-6", children: [
1370
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mb-4 text-lg font-semibold", children: "What would you like to discuss?" }),
1371
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
1372
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "topic", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1373
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "topic", children: "Topic" }),
1374
- /* @__PURE__ */ jsxRuntime.jsxs(
1375
- inputs.Select,
1376
- {
1377
- ...field,
1378
- id: "topic",
1379
- error: meta.touched && !!meta.error,
1380
- "aria-label": "Topic",
1381
- children: [
1382
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select a topic" }),
1383
- TOPICS.map((topic) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: topic.toLowerCase(), children: topic }, topic))
1384
- ]
1385
- }
1386
- )
1387
- ] }) }),
1388
- /* @__PURE__ */ jsxRuntime.jsx(forms.Field, { name: "details", children: ({ field, meta }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1389
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "details", children: "Additional Details (Optional)" }),
1390
- /* @__PURE__ */ jsxRuntime.jsx(
1391
- TextArea,
1392
- {
1393
- ...field,
1394
- id: "details",
1395
- placeholder: "Help us prepare for the call by sharing any specific questions or topics you'd like to cover...",
1396
- rows: 4,
1397
- error: meta.touched && !!meta.error,
1398
- "aria-label": "Additional Details"
1399
- }
1400
- )
1401
- ] }) })
1402
- ] })
1403
- ] }),
1404
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
1650
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-12 gap-6", children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1651
+ "div",
1652
+ {
1653
+ className: getColumnSpanClass(field.columnSpan),
1654
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicFormField, { field })
1655
+ },
1656
+ field.name
1657
+ )) }),
1658
+ (callbackProcessLabel || callbackProcessDescription) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
1405
1659
  /* @__PURE__ */ jsxRuntime.jsx(
1406
1660
  DynamicIcon,
1407
1661
  {
1408
1662
  name: "lucide/clock",
1409
1663
  size: 20,
1410
- className: "mt-1 shrink-0 text-primary"
1664
+ className: "mt-1 shrink-0"
1411
1665
  }
1412
1666
  ),
1413
1667
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
1414
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: "Callback Process" }),
1415
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 leading-relaxed text-muted-foreground", children: "We'll call you at the scheduled time at the phone number you provided. Please ensure you're available to answer. If you miss the call, we'll send you a follow-up email." })
1668
+ callbackProcessLabel && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: callbackProcessLabel }),
1669
+ callbackProcessDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 leading-relaxed", children: callbackProcessDescription })
1416
1670
  ] })
1417
1671
  ] }) }),
1418
1672
  actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1426,14 +1680,13 @@ function ContactCallback({
1426
1680
  disabled: form.isSubmitting,
1427
1681
  children: [
1428
1682
  buttonIcon,
1429
- buttonText
1683
+ buttonText || "Schedule Callback"
1430
1684
  ]
1431
1685
  }
1432
1686
  )
1433
1687
  ]
1434
1688
  }
1435
- ) }) }),
1436
- footerContent
1689
+ ) }) })
1437
1690
  ] })
1438
1691
  }
1439
1692
  );