@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
@@ -6,8 +6,7 @@ import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
- import { TextInput, TextArea, Select, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput, RichTextEditor } from '@page-speed/forms/inputs';
10
- import * as LabelPrimitive from '@radix-ui/react-label';
9
+ import { TextInput, TextArea, Select, MultiSelect, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput, RichTextEditor } from '@page-speed/forms/inputs';
11
10
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
12
11
  import { serializeForRails, deserializeErrors } from '@page-speed/forms/integration';
13
12
 
@@ -358,6 +357,7 @@ var Pressable = React.forwardRef(
358
357
  rel,
359
358
  linkType,
360
359
  isInternal,
360
+ isExternal,
361
361
  handleClick
362
362
  } = navigation;
363
363
  const shouldRenderLink = normalizedHref && linkType !== "none";
@@ -456,22 +456,6 @@ function CardContent({ className, ...props }) {
456
456
  }
457
457
  );
458
458
  }
459
- function Label({
460
- className,
461
- ...props
462
- }) {
463
- return /* @__PURE__ */ jsx(
464
- LabelPrimitive.Root,
465
- {
466
- "data-slot": "label",
467
- className: cn(
468
- "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",
469
- className
470
- ),
471
- ...props
472
- }
473
- );
474
- }
475
459
  function DynamicFormField({
476
460
  field,
477
461
  className,
@@ -480,190 +464,199 @@ function DynamicFormField({
480
464
  onFileRemove,
481
465
  isUploading = false
482
466
  }) {
483
- const fieldId = `field-${field.name}`;
484
- return /* @__PURE__ */ jsx(Field, { name: field.name, children: ({ field: formField, meta }) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
485
- field.type !== "checkbox" && /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
486
- field.label,
487
- field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
488
- ] }),
489
- (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsx(
490
- TextInput,
491
- {
492
- ...formField,
493
- id: fieldId,
494
- type: field.type,
495
- placeholder: field.placeholder,
496
- error: meta.touched && !!meta.error,
497
- disabled: field.disabled,
498
- "aria-label": field.label
499
- }
500
- ),
501
- field.type === "number" && /* @__PURE__ */ jsx(
502
- TextInput,
503
- {
504
- ...formField,
505
- id: fieldId,
506
- type: "text",
507
- placeholder: field.placeholder,
508
- error: meta.touched && !!meta.error,
509
- disabled: field.disabled,
510
- "aria-label": field.label
511
- }
512
- ),
513
- field.type === "textarea" && /* @__PURE__ */ jsx(
514
- TextArea,
515
- {
516
- ...formField,
517
- id: fieldId,
518
- placeholder: field.placeholder,
519
- rows: field.rows || 4,
520
- error: meta.touched && !!meta.error,
521
- disabled: field.disabled,
522
- "aria-label": field.label
523
- }
524
- ),
525
- field.type === "select" && field.options && /* @__PURE__ */ jsx(
526
- Select,
527
- {
528
- ...formField,
529
- id: fieldId,
530
- options: field.options,
531
- placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
532
- error: meta.touched && !!meta.error,
533
- disabled: field.disabled,
534
- "aria-label": field.label
535
- }
536
- ),
537
- field.type === "multi-select" && field.options && /* @__PURE__ */ jsx(
538
- Select,
539
- {
540
- ...formField,
541
- id: fieldId,
542
- options: field.options,
543
- placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
544
- error: meta.touched && !!meta.error,
545
- disabled: field.disabled,
546
- "aria-label": field.label,
547
- multiple: true
548
- }
549
- ),
550
- field.type === "radio" && field.options && /* @__PURE__ */ jsx(
551
- Radio,
552
- {
553
- ...formField,
554
- id: fieldId,
555
- options: field.options,
556
- disabled: field.disabled,
557
- layout: field.layout || "stacked",
558
- error: meta.touched && !!meta.error,
559
- "aria-label": field.label
560
- }
561
- ),
562
- field.type === "checkbox" && /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-2", children: [
563
- /* @__PURE__ */ jsx(
564
- Checkbox,
565
- {
566
- ...formField,
567
- id: fieldId,
568
- value: formField.value === true || formField.value === "true",
569
- onChange: (checked) => formField.onChange(checked),
570
- disabled: field.disabled,
571
- error: meta.touched && !!meta.error,
572
- "aria-label": field.label
573
- }
574
- ),
575
- /* @__PURE__ */ jsxs(
576
- Label,
577
- {
578
- htmlFor: fieldId,
579
- className: "font-normal cursor-pointer leading-relaxed",
580
- children: [
581
- field.label,
582
- field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
583
- ]
584
- }
585
- )
586
- ] }),
587
- field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsx(
588
- CheckboxGroup,
589
- {
590
- ...formField,
591
- id: fieldId,
592
- options: field.options,
593
- disabled: field.disabled,
594
- layout: field.layout || "stacked",
595
- error: meta.touched && !!meta.error,
596
- "aria-label": field.label
597
- }
598
- ),
599
- (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsx(
600
- DatePicker,
601
- {
602
- ...formField,
603
- id: fieldId,
604
- placeholder: field.placeholder,
605
- error: meta.touched && !!meta.error,
606
- disabled: field.disabled,
607
- "aria-label": field.label
608
- }
609
- ),
610
- field.type === "date-range" && /* @__PURE__ */ jsx(
611
- DateRangePicker,
612
- {
613
- ...formField,
614
- id: fieldId,
615
- error: meta.touched && !!meta.error,
616
- disabled: field.disabled,
617
- "aria-label": field.label
618
- }
619
- ),
620
- field.type === "time" && /* @__PURE__ */ jsx(
621
- TimePicker,
622
- {
623
- ...formField,
624
- id: fieldId,
625
- placeholder: field.placeholder,
626
- error: meta.touched && !!meta.error,
627
- disabled: field.disabled,
628
- "aria-label": field.label
629
- }
630
- ),
631
- field.type === "file" && /* @__PURE__ */ jsx(
632
- FileInput,
633
- {
634
- ...formField,
635
- id: fieldId,
636
- accept: field.accept,
637
- maxSize: field.maxSize || 5 * 1024 * 1024,
638
- maxFiles: field.maxFiles || 1,
639
- multiple: field.multiple || false,
640
- placeholder: field.placeholder || "Choose file(s)...",
641
- error: meta.touched && !!meta.error,
642
- disabled: field.disabled || isUploading,
643
- showProgress: true,
644
- uploadProgress,
645
- onChange: (files) => {
646
- formField.onChange(files);
647
- if (files.length > 0 && onFileUpload) {
648
- onFileUpload(files);
467
+ const fieldId = field.name;
468
+ const usesGroupLegend = field.type === "radio" || field.type === "checkbox-group";
469
+ const usesInlineCheckboxLabel = field.type === "checkbox";
470
+ const shouldRenderFieldLabel = !usesGroupLegend && !usesInlineCheckboxLabel;
471
+ const checkboxLabel = /* @__PURE__ */ jsxs(Fragment, { children: [
472
+ field.label,
473
+ field.required ? /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" }) : null
474
+ ] });
475
+ return /* @__PURE__ */ jsx(
476
+ Field,
477
+ {
478
+ name: field.name,
479
+ label: shouldRenderFieldLabel ? field.label : void 0,
480
+ description: shouldRenderFieldLabel ? field.description : void 0,
481
+ required: field.required,
482
+ className: cn("space-y-2", className),
483
+ children: ({ field: formField, meta }) => /* @__PURE__ */ jsxs("div", { children: [
484
+ (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsx(
485
+ TextInput,
486
+ {
487
+ ...formField,
488
+ id: fieldId,
489
+ type: field.type,
490
+ placeholder: field.placeholder,
491
+ error: meta.touched && !!meta.error,
492
+ disabled: field.disabled,
493
+ "aria-label": field.label
649
494
  }
650
- },
651
- onFileRemove,
652
- "aria-label": field.label
653
- }
654
- ),
655
- field.type === "rich-text" && /* @__PURE__ */ jsx(
656
- RichTextEditor,
657
- {
658
- ...formField,
659
- id: fieldId,
660
- placeholder: field.placeholder,
661
- error: meta.touched && !!meta.error,
662
- disabled: field.disabled,
663
- "aria-label": field.label
664
- }
665
- )
666
- ] }) });
495
+ ),
496
+ field.type === "number" && /* @__PURE__ */ jsx(
497
+ TextInput,
498
+ {
499
+ ...formField,
500
+ id: fieldId,
501
+ type: "text",
502
+ placeholder: field.placeholder,
503
+ error: meta.touched && !!meta.error,
504
+ disabled: field.disabled,
505
+ "aria-label": field.label
506
+ }
507
+ ),
508
+ field.type === "textarea" && /* @__PURE__ */ jsx(
509
+ TextArea,
510
+ {
511
+ ...formField,
512
+ id: fieldId,
513
+ placeholder: field.placeholder,
514
+ rows: field.rows || 4,
515
+ error: meta.touched && !!meta.error,
516
+ disabled: field.disabled,
517
+ "aria-label": field.label
518
+ }
519
+ ),
520
+ field.type === "select" && field.options && /* @__PURE__ */ jsx(
521
+ Select,
522
+ {
523
+ ...formField,
524
+ id: fieldId,
525
+ options: field.options,
526
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
527
+ error: meta.touched && !!meta.error,
528
+ disabled: field.disabled,
529
+ "aria-label": field.label
530
+ }
531
+ ),
532
+ field.type === "multi-select" && field.options && /* @__PURE__ */ jsx(
533
+ MultiSelect,
534
+ {
535
+ ...formField,
536
+ id: fieldId,
537
+ options: field.options,
538
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
539
+ error: meta.touched && !!meta.error,
540
+ disabled: field.disabled,
541
+ "aria-label": field.label
542
+ }
543
+ ),
544
+ field.type === "radio" && field.options && /* @__PURE__ */ jsx(
545
+ Radio,
546
+ {
547
+ ...formField,
548
+ id: fieldId,
549
+ options: field.options,
550
+ label: field.label,
551
+ description: field.description,
552
+ required: field.required,
553
+ disabled: field.disabled,
554
+ layout: field.layout || "stacked",
555
+ error: meta.touched && !!meta.error,
556
+ "aria-label": field.label
557
+ }
558
+ ),
559
+ field.type === "checkbox" && /* @__PURE__ */ jsx(
560
+ Checkbox,
561
+ {
562
+ ...formField,
563
+ id: fieldId,
564
+ value: formField.value === true || formField.value === "true",
565
+ onChange: (checked) => formField.onChange(checked),
566
+ label: checkboxLabel,
567
+ description: field.description,
568
+ disabled: field.disabled,
569
+ required: field.required,
570
+ error: meta.touched && !!meta.error,
571
+ "aria-label": field.label
572
+ }
573
+ ),
574
+ field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsx(
575
+ CheckboxGroup,
576
+ {
577
+ ...formField,
578
+ id: fieldId,
579
+ options: field.options,
580
+ label: field.label,
581
+ description: field.description,
582
+ required: field.required,
583
+ disabled: field.disabled,
584
+ layout: field.layout || "stacked",
585
+ error: meta.touched && !!meta.error,
586
+ "aria-label": field.label
587
+ }
588
+ ),
589
+ (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsx(
590
+ DatePicker,
591
+ {
592
+ ...formField,
593
+ id: fieldId,
594
+ placeholder: field.placeholder,
595
+ error: meta.touched && !!meta.error,
596
+ disabled: field.disabled,
597
+ "aria-label": field.label
598
+ }
599
+ ),
600
+ field.type === "date-range" && /* @__PURE__ */ jsx(
601
+ DateRangePicker,
602
+ {
603
+ ...formField,
604
+ id: fieldId,
605
+ placeholder: field.placeholder,
606
+ error: meta.touched && !!meta.error,
607
+ disabled: field.disabled,
608
+ "aria-label": field.label
609
+ }
610
+ ),
611
+ field.type === "time" && /* @__PURE__ */ jsx(
612
+ TimePicker,
613
+ {
614
+ ...formField,
615
+ id: fieldId,
616
+ placeholder: field.placeholder,
617
+ error: meta.touched && !!meta.error,
618
+ disabled: field.disabled,
619
+ "aria-label": field.label
620
+ }
621
+ ),
622
+ field.type === "file" && /* @__PURE__ */ jsx(
623
+ FileInput,
624
+ {
625
+ ...formField,
626
+ id: fieldId,
627
+ accept: field.accept,
628
+ maxSize: field.maxSize || 5 * 1024 * 1024,
629
+ maxFiles: field.maxFiles || 1,
630
+ multiple: field.multiple || false,
631
+ placeholder: field.placeholder || "Choose file(s)...",
632
+ error: meta.touched && !!meta.error,
633
+ disabled: field.disabled || isUploading,
634
+ showProgress: true,
635
+ uploadProgress,
636
+ onChange: (files) => {
637
+ formField.onChange(files);
638
+ if (files.length > 0 && onFileUpload) {
639
+ onFileUpload(files);
640
+ }
641
+ },
642
+ onFileRemove,
643
+ "aria-label": field.label
644
+ }
645
+ ),
646
+ field.type === "rich-text" && /* @__PURE__ */ jsx(
647
+ RichTextEditor,
648
+ {
649
+ ...formField,
650
+ id: fieldId,
651
+ placeholder: field.placeholder,
652
+ error: meta.touched && !!meta.error,
653
+ disabled: field.disabled,
654
+ "aria-label": field.label
655
+ }
656
+ )
657
+ ] })
658
+ }
659
+ );
667
660
  }
668
661
  var svgCache = /* @__PURE__ */ new Map();
669
662
  function DynamicIcon({
@@ -962,8 +955,36 @@ function useContactForm(options) {
962
955
  resetOnSuccess = true,
963
956
  uploadTokens = []
964
957
  } = options;
965
- const [isSubmitted, setIsSubmitted] = useState(false);
966
958
  const [submissionError, setSubmissionError] = useState(null);
959
+ const submissionConfig = formConfig?.submissionConfig;
960
+ const redirectUrl = submissionConfig?.redirectUrl;
961
+ const redirectNavigation = useNavigation({ href: redirectUrl });
962
+ const resetSubmissionState = useCallback(() => {
963
+ setSubmissionError(null);
964
+ }, []);
965
+ const performRedirect = useCallback(() => {
966
+ if (!redirectUrl || typeof window === "undefined") {
967
+ return;
968
+ }
969
+ const navigate = () => {
970
+ if (redirectNavigation.shouldUseRouter && redirectNavigation.normalizedHref) {
971
+ const handler = window.__opensiteNavigationHandler;
972
+ if (typeof handler === "function") {
973
+ try {
974
+ const handled = handler(redirectNavigation.normalizedHref, void 0);
975
+ if (handled !== false) {
976
+ return;
977
+ }
978
+ } catch (error) {
979
+ console.error("Internal redirect handler failed:", error);
980
+ }
981
+ }
982
+ }
983
+ const destination = redirectNavigation.normalizedHref || redirectUrl;
984
+ window.location.assign(destination);
985
+ };
986
+ window.setTimeout(navigate, 150);
987
+ }, [redirectNavigation, redirectUrl]);
967
988
  const form = useForm({
968
989
  initialValues: useMemo(
969
990
  () => generateInitialValues(formFields),
@@ -974,7 +995,7 @@ function useContactForm(options) {
974
995
  [formFields]
975
996
  ),
976
997
  onSubmit: async (values, helpers) => {
977
- setSubmissionError(null);
998
+ resetSubmissionState();
978
999
  const shouldAutoSubmit = Boolean(formConfig?.endpoint);
979
1000
  if (!shouldAutoSubmit && !onSubmit) {
980
1001
  return;
@@ -994,12 +1015,21 @@ function useContactForm(options) {
994
1015
  await onSubmit(submissionValues);
995
1016
  }
996
1017
  if (shouldAutoSubmit || onSubmit) {
997
- setIsSubmitted(true);
1018
+ try {
1019
+ await submissionConfig?.handleFormSubmission?.({
1020
+ formData: submissionValues,
1021
+ responseData: result
1022
+ });
1023
+ } catch (callbackError) {
1024
+ console.error("handleFormSubmission callback failed:", callbackError);
1025
+ }
998
1026
  if (resetOnSuccess) {
999
1027
  helpers.resetForm();
1000
1028
  }
1001
1029
  onSuccess?.(result);
1002
- setTimeout(() => setIsSubmitted(false), 1e4);
1030
+ if (submissionConfig?.behavior === "redirect" && submissionConfig.redirectUrl) {
1031
+ performRedirect();
1032
+ }
1003
1033
  }
1004
1034
  } catch (error) {
1005
1035
  if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
@@ -1014,9 +1044,10 @@ function useContactForm(options) {
1014
1044
  const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
1015
1045
  return {
1016
1046
  form,
1017
- isSubmitted,
1047
+ isSubmitted: form.status === "success",
1018
1048
  submissionError,
1019
- formMethod
1049
+ formMethod,
1050
+ resetSubmissionState
1020
1051
  };
1021
1052
  }
1022
1053
 
@@ -1511,38 +1542,6 @@ var Section = React__default.forwardRef(
1511
1542
  }
1512
1543
  );
1513
1544
  Section.displayName = "Section";
1514
- var FormFeedback = ({
1515
- isSubmitted,
1516
- successMessageClassName,
1517
- successMessage,
1518
- submissionError,
1519
- errorMessageClassName
1520
- }) => {
1521
- if (!isSubmitted && !submissionError) return null;
1522
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1523
- isSubmitted && !submissionError && /* @__PURE__ */ jsx(
1524
- "div",
1525
- {
1526
- className: cn(
1527
- "mb-6 p-4 bg-primary/10 border border-primary rounded-md",
1528
- successMessageClassName
1529
- ),
1530
- children: typeof successMessage === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-primary-foreground/90 text-center", children: successMessage }) : successMessage
1531
- }
1532
- ),
1533
- submissionError && /* @__PURE__ */ jsx(
1534
- "div",
1535
- {
1536
- className: cn(
1537
- "mb-6 p-4 bg-destructive/10 border border-destructive rounded-md",
1538
- errorMessageClassName
1539
- ),
1540
- children: typeof submissionError === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive text-center", children: submissionError }) : submissionError
1541
- }
1542
- )
1543
- ] });
1544
- };
1545
- var form_feedback_default = FormFeedback;
1546
1545
  var DEFAULT_FORM_FIELDS = [
1547
1546
  {
1548
1547
  name: "name",
@@ -1627,7 +1626,7 @@ function ContactFaq({
1627
1626
  removeFile,
1628
1627
  resetUpload
1629
1628
  } = useFileUpload({ onError });
1630
- const { form, isSubmitted, submissionError, formMethod } = useContactForm({
1629
+ const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
1631
1630
  formFields,
1632
1631
  formConfig,
1633
1632
  onSubmit,
@@ -1763,22 +1762,21 @@ function ContactFaq({
1763
1762
  children: formHeading
1764
1763
  }
1765
1764
  ) : /* @__PURE__ */ jsx("div", { className: formHeadingClassName, children: formHeading })),
1766
- /* @__PURE__ */ jsx(
1767
- form_feedback_default,
1768
- {
1769
- isSubmitted,
1770
- successMessageClassName,
1771
- successMessage,
1772
- submissionError,
1773
- errorMessageClassName
1774
- }
1775
- ),
1776
1765
  /* @__PURE__ */ jsxs(
1777
1766
  Form,
1778
1767
  {
1779
1768
  form,
1780
1769
  action: formConfig?.endpoint,
1781
1770
  method: formMethod,
1771
+ submissionError,
1772
+ successMessage,
1773
+ successMessageClassName,
1774
+ errorMessageClassName,
1775
+ submissionConfig: formConfig?.submissionConfig,
1776
+ onNewSubmission: () => {
1777
+ resetUpload();
1778
+ resetSubmissionState();
1779
+ },
1782
1780
  className: cn("space-y-4", formClassName),
1783
1781
  children: [
1784
1782
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-12 gap-6", children: formFields.map((field) => /* @__PURE__ */ jsx(
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.js';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.js';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-AwBlQu1a.js';
4
4
  import { A as ActionConfig } from './blocks-ClXAGlHQ.js';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.js';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.js';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-AwBlQu1a.js';
4
4
  import { A as ActionConfig } from './blocks-ClXAGlHQ.js';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.js';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.js';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-AwBlQu1a.js';
4
4
  import { A as ActionConfig } from './blocks-ClXAGlHQ.js';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.js';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.js';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-AwBlQu1a.js';
4
4
  import { A as ActionConfig } from './blocks-ClXAGlHQ.js';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.js';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.js';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-AwBlQu1a.js';
4
4
  import { A as ActionConfig } from './blocks-ClXAGlHQ.js';
5
5
  import '@page-speed/forms/integration';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import { P as PageSpeedFormConfig } from './forms-nGgHUTBw.cjs';
2
+ import { P as PageSpeedFormConfig } from './forms-CStlFhnh.cjs';
3
3
  import { f as SectionBackground, g as SectionSpacing, s as PatternName } from './community-initiatives-k1_FqqBQ.cjs';
4
4
  import { A as ActionConfig } from './blocks-rgCERYOC.cjs';
5
5
  import '@page-speed/forms/integration';