@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
@@ -7,8 +7,7 @@ import { twMerge } from 'tailwind-merge';
7
7
  import { cva } from 'class-variance-authority';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
  import { Img } from '@page-speed/img';
10
- import { TextInput, TextArea, Select, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput, RichTextEditor } from '@page-speed/forms/inputs';
11
- import * as LabelPrimitive from '@radix-ui/react-label';
10
+ import { TextInput, TextArea, Select, MultiSelect, Radio, Checkbox, CheckboxGroup, DatePicker, DateRangePicker, TimePicker, FileInput, RichTextEditor } from '@page-speed/forms/inputs';
12
11
  import { serializeForRails, deserializeErrors } from '@page-speed/forms/integration';
13
12
 
14
13
  // components/blocks/contact/contact-photography.tsx
@@ -388,6 +387,7 @@ var Pressable = React.forwardRef(
388
387
  rel,
389
388
  linkType,
390
389
  isInternal,
390
+ isExternal,
391
391
  handleClick
392
392
  } = navigation;
393
393
  const shouldRenderLink = normalizedHref && linkType !== "none";
@@ -463,22 +463,6 @@ var Pressable = React.forwardRef(
463
463
  }
464
464
  );
465
465
  Pressable.displayName = "Pressable";
466
- function Label({
467
- className,
468
- ...props
469
- }) {
470
- return /* @__PURE__ */ jsx(
471
- LabelPrimitive.Root,
472
- {
473
- "data-slot": "label",
474
- className: cn(
475
- "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",
476
- className
477
- ),
478
- ...props
479
- }
480
- );
481
- }
482
466
  function DynamicFormField({
483
467
  field,
484
468
  className,
@@ -487,190 +471,199 @@ function DynamicFormField({
487
471
  onFileRemove,
488
472
  isUploading = false
489
473
  }) {
490
- const fieldId = `field-${field.name}`;
491
- return /* @__PURE__ */ jsx(Field, { name: field.name, children: ({ field: formField, meta }) => /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", className), children: [
492
- field.type !== "checkbox" && /* @__PURE__ */ jsxs(Label, { htmlFor: fieldId, children: [
493
- field.label,
494
- field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
495
- ] }),
496
- (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsx(
497
- TextInput,
498
- {
499
- ...formField,
500
- id: fieldId,
501
- type: field.type,
502
- placeholder: field.placeholder,
503
- error: meta.touched && !!meta.error,
504
- disabled: field.disabled,
505
- "aria-label": field.label
506
- }
507
- ),
508
- field.type === "number" && /* @__PURE__ */ jsx(
509
- TextInput,
510
- {
511
- ...formField,
512
- id: fieldId,
513
- type: "text",
514
- placeholder: field.placeholder,
515
- error: meta.touched && !!meta.error,
516
- disabled: field.disabled,
517
- "aria-label": field.label
518
- }
519
- ),
520
- field.type === "textarea" && /* @__PURE__ */ jsx(
521
- TextArea,
522
- {
523
- ...formField,
524
- id: fieldId,
525
- placeholder: field.placeholder,
526
- rows: field.rows || 4,
527
- error: meta.touched && !!meta.error,
528
- disabled: field.disabled,
529
- "aria-label": field.label
530
- }
531
- ),
532
- field.type === "select" && field.options && /* @__PURE__ */ jsx(
533
- Select,
534
- {
535
- ...formField,
536
- id: fieldId,
537
- options: field.options,
538
- placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
539
- error: meta.touched && !!meta.error,
540
- disabled: field.disabled,
541
- "aria-label": field.label
542
- }
543
- ),
544
- field.type === "multi-select" && field.options && /* @__PURE__ */ jsx(
545
- Select,
546
- {
547
- ...formField,
548
- id: fieldId,
549
- options: field.options,
550
- placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
551
- error: meta.touched && !!meta.error,
552
- disabled: field.disabled,
553
- "aria-label": field.label,
554
- multiple: true
555
- }
556
- ),
557
- field.type === "radio" && field.options && /* @__PURE__ */ jsx(
558
- Radio,
559
- {
560
- ...formField,
561
- id: fieldId,
562
- options: field.options,
563
- disabled: field.disabled,
564
- layout: field.layout || "stacked",
565
- error: meta.touched && !!meta.error,
566
- "aria-label": field.label
567
- }
568
- ),
569
- field.type === "checkbox" && /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-2", children: [
570
- /* @__PURE__ */ jsx(
571
- Checkbox,
572
- {
573
- ...formField,
574
- id: fieldId,
575
- value: formField.value === true || formField.value === "true",
576
- onChange: (checked) => formField.onChange(checked),
577
- disabled: field.disabled,
578
- error: meta.touched && !!meta.error,
579
- "aria-label": field.label
580
- }
581
- ),
582
- /* @__PURE__ */ jsxs(
583
- Label,
584
- {
585
- htmlFor: fieldId,
586
- className: "font-normal cursor-pointer leading-relaxed",
587
- children: [
588
- field.label,
589
- field.required && /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" })
590
- ]
591
- }
592
- )
593
- ] }),
594
- field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsx(
595
- CheckboxGroup,
596
- {
597
- ...formField,
598
- id: fieldId,
599
- options: field.options,
600
- disabled: field.disabled,
601
- layout: field.layout || "stacked",
602
- error: meta.touched && !!meta.error,
603
- "aria-label": field.label
604
- }
605
- ),
606
- (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsx(
607
- DatePicker,
608
- {
609
- ...formField,
610
- id: fieldId,
611
- placeholder: field.placeholder,
612
- error: meta.touched && !!meta.error,
613
- disabled: field.disabled,
614
- "aria-label": field.label
615
- }
616
- ),
617
- field.type === "date-range" && /* @__PURE__ */ jsx(
618
- DateRangePicker,
619
- {
620
- ...formField,
621
- id: fieldId,
622
- error: meta.touched && !!meta.error,
623
- disabled: field.disabled,
624
- "aria-label": field.label
625
- }
626
- ),
627
- field.type === "time" && /* @__PURE__ */ jsx(
628
- TimePicker,
629
- {
630
- ...formField,
631
- id: fieldId,
632
- placeholder: field.placeholder,
633
- error: meta.touched && !!meta.error,
634
- disabled: field.disabled,
635
- "aria-label": field.label
636
- }
637
- ),
638
- field.type === "file" && /* @__PURE__ */ jsx(
639
- FileInput,
640
- {
641
- ...formField,
642
- id: fieldId,
643
- accept: field.accept,
644
- maxSize: field.maxSize || 5 * 1024 * 1024,
645
- maxFiles: field.maxFiles || 1,
646
- multiple: field.multiple || false,
647
- placeholder: field.placeholder || "Choose file(s)...",
648
- error: meta.touched && !!meta.error,
649
- disabled: field.disabled || isUploading,
650
- showProgress: true,
651
- uploadProgress,
652
- onChange: (files) => {
653
- formField.onChange(files);
654
- if (files.length > 0 && onFileUpload) {
655
- onFileUpload(files);
474
+ const fieldId = field.name;
475
+ const usesGroupLegend = field.type === "radio" || field.type === "checkbox-group";
476
+ const usesInlineCheckboxLabel = field.type === "checkbox";
477
+ const shouldRenderFieldLabel = !usesGroupLegend && !usesInlineCheckboxLabel;
478
+ const checkboxLabel = /* @__PURE__ */ jsxs(Fragment, { children: [
479
+ field.label,
480
+ field.required ? /* @__PURE__ */ jsx("span", { className: "text-destructive ml-1", children: "*" }) : null
481
+ ] });
482
+ return /* @__PURE__ */ jsx(
483
+ Field,
484
+ {
485
+ name: field.name,
486
+ label: shouldRenderFieldLabel ? field.label : void 0,
487
+ description: shouldRenderFieldLabel ? field.description : void 0,
488
+ required: field.required,
489
+ className: cn("space-y-2", className),
490
+ children: ({ field: formField, meta }) => /* @__PURE__ */ jsxs("div", { children: [
491
+ (field.type === "text" || field.type === "email" || field.type === "tel" || field.type === "search" || field.type === "password" || field.type === "url") && /* @__PURE__ */ jsx(
492
+ TextInput,
493
+ {
494
+ ...formField,
495
+ id: fieldId,
496
+ type: field.type,
497
+ placeholder: field.placeholder,
498
+ error: meta.touched && !!meta.error,
499
+ disabled: field.disabled,
500
+ "aria-label": field.label
656
501
  }
657
- },
658
- onFileRemove,
659
- "aria-label": field.label
660
- }
661
- ),
662
- field.type === "rich-text" && /* @__PURE__ */ jsx(
663
- RichTextEditor,
664
- {
665
- ...formField,
666
- id: fieldId,
667
- placeholder: field.placeholder,
668
- error: meta.touched && !!meta.error,
669
- disabled: field.disabled,
670
- "aria-label": field.label
671
- }
672
- )
673
- ] }) });
502
+ ),
503
+ field.type === "number" && /* @__PURE__ */ jsx(
504
+ TextInput,
505
+ {
506
+ ...formField,
507
+ id: fieldId,
508
+ type: "text",
509
+ placeholder: field.placeholder,
510
+ error: meta.touched && !!meta.error,
511
+ disabled: field.disabled,
512
+ "aria-label": field.label
513
+ }
514
+ ),
515
+ field.type === "textarea" && /* @__PURE__ */ jsx(
516
+ TextArea,
517
+ {
518
+ ...formField,
519
+ id: fieldId,
520
+ placeholder: field.placeholder,
521
+ rows: field.rows || 4,
522
+ error: meta.touched && !!meta.error,
523
+ disabled: field.disabled,
524
+ "aria-label": field.label
525
+ }
526
+ ),
527
+ field.type === "select" && field.options && /* @__PURE__ */ jsx(
528
+ Select,
529
+ {
530
+ ...formField,
531
+ id: fieldId,
532
+ options: field.options,
533
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
534
+ error: meta.touched && !!meta.error,
535
+ disabled: field.disabled,
536
+ "aria-label": field.label
537
+ }
538
+ ),
539
+ field.type === "multi-select" && field.options && /* @__PURE__ */ jsx(
540
+ MultiSelect,
541
+ {
542
+ ...formField,
543
+ id: fieldId,
544
+ options: field.options,
545
+ placeholder: field.placeholder || `Select ${field.label.toLowerCase()}`,
546
+ error: meta.touched && !!meta.error,
547
+ disabled: field.disabled,
548
+ "aria-label": field.label
549
+ }
550
+ ),
551
+ field.type === "radio" && field.options && /* @__PURE__ */ jsx(
552
+ Radio,
553
+ {
554
+ ...formField,
555
+ id: fieldId,
556
+ options: field.options,
557
+ label: field.label,
558
+ description: field.description,
559
+ required: field.required,
560
+ disabled: field.disabled,
561
+ layout: field.layout || "stacked",
562
+ error: meta.touched && !!meta.error,
563
+ "aria-label": field.label
564
+ }
565
+ ),
566
+ field.type === "checkbox" && /* @__PURE__ */ jsx(
567
+ Checkbox,
568
+ {
569
+ ...formField,
570
+ id: fieldId,
571
+ value: formField.value === true || formField.value === "true",
572
+ onChange: (checked) => formField.onChange(checked),
573
+ label: checkboxLabel,
574
+ description: field.description,
575
+ disabled: field.disabled,
576
+ required: field.required,
577
+ error: meta.touched && !!meta.error,
578
+ "aria-label": field.label
579
+ }
580
+ ),
581
+ field.type === "checkbox-group" && field.options && /* @__PURE__ */ jsx(
582
+ CheckboxGroup,
583
+ {
584
+ ...formField,
585
+ id: fieldId,
586
+ options: field.options,
587
+ label: field.label,
588
+ description: field.description,
589
+ required: field.required,
590
+ disabled: field.disabled,
591
+ layout: field.layout || "stacked",
592
+ error: meta.touched && !!meta.error,
593
+ "aria-label": field.label
594
+ }
595
+ ),
596
+ (field.type === "date-picker" || field.type === "date") && /* @__PURE__ */ jsx(
597
+ DatePicker,
598
+ {
599
+ ...formField,
600
+ id: fieldId,
601
+ placeholder: field.placeholder,
602
+ error: meta.touched && !!meta.error,
603
+ disabled: field.disabled,
604
+ "aria-label": field.label
605
+ }
606
+ ),
607
+ field.type === "date-range" && /* @__PURE__ */ jsx(
608
+ DateRangePicker,
609
+ {
610
+ ...formField,
611
+ id: fieldId,
612
+ placeholder: field.placeholder,
613
+ error: meta.touched && !!meta.error,
614
+ disabled: field.disabled,
615
+ "aria-label": field.label
616
+ }
617
+ ),
618
+ field.type === "time" && /* @__PURE__ */ jsx(
619
+ TimePicker,
620
+ {
621
+ ...formField,
622
+ id: fieldId,
623
+ placeholder: field.placeholder,
624
+ error: meta.touched && !!meta.error,
625
+ disabled: field.disabled,
626
+ "aria-label": field.label
627
+ }
628
+ ),
629
+ field.type === "file" && /* @__PURE__ */ jsx(
630
+ FileInput,
631
+ {
632
+ ...formField,
633
+ id: fieldId,
634
+ accept: field.accept,
635
+ maxSize: field.maxSize || 5 * 1024 * 1024,
636
+ maxFiles: field.maxFiles || 1,
637
+ multiple: field.multiple || false,
638
+ placeholder: field.placeholder || "Choose file(s)...",
639
+ error: meta.touched && !!meta.error,
640
+ disabled: field.disabled || isUploading,
641
+ showProgress: true,
642
+ uploadProgress,
643
+ onChange: (files) => {
644
+ formField.onChange(files);
645
+ if (files.length > 0 && onFileUpload) {
646
+ onFileUpload(files);
647
+ }
648
+ },
649
+ onFileRemove,
650
+ "aria-label": field.label
651
+ }
652
+ ),
653
+ field.type === "rich-text" && /* @__PURE__ */ jsx(
654
+ RichTextEditor,
655
+ {
656
+ ...formField,
657
+ id: fieldId,
658
+ placeholder: field.placeholder,
659
+ error: meta.touched && !!meta.error,
660
+ disabled: field.disabled,
661
+ "aria-label": field.label
662
+ }
663
+ )
664
+ ] })
665
+ }
666
+ );
674
667
  }
675
668
 
676
669
  // lib/form-field-types.ts
@@ -802,8 +795,36 @@ function useContactForm(options) {
802
795
  resetOnSuccess = true,
803
796
  uploadTokens = []
804
797
  } = options;
805
- const [isSubmitted, setIsSubmitted] = useState(false);
806
798
  const [submissionError, setSubmissionError] = useState(null);
799
+ const submissionConfig = formConfig?.submissionConfig;
800
+ const redirectUrl = submissionConfig?.redirectUrl;
801
+ const redirectNavigation = useNavigation({ href: redirectUrl });
802
+ const resetSubmissionState = useCallback(() => {
803
+ setSubmissionError(null);
804
+ }, []);
805
+ const performRedirect = useCallback(() => {
806
+ if (!redirectUrl || typeof window === "undefined") {
807
+ return;
808
+ }
809
+ const navigate = () => {
810
+ if (redirectNavigation.shouldUseRouter && redirectNavigation.normalizedHref) {
811
+ const handler = window.__opensiteNavigationHandler;
812
+ if (typeof handler === "function") {
813
+ try {
814
+ const handled = handler(redirectNavigation.normalizedHref, void 0);
815
+ if (handled !== false) {
816
+ return;
817
+ }
818
+ } catch (error) {
819
+ console.error("Internal redirect handler failed:", error);
820
+ }
821
+ }
822
+ }
823
+ const destination = redirectNavigation.normalizedHref || redirectUrl;
824
+ window.location.assign(destination);
825
+ };
826
+ window.setTimeout(navigate, 150);
827
+ }, [redirectNavigation, redirectUrl]);
807
828
  const form = useForm({
808
829
  initialValues: useMemo(
809
830
  () => generateInitialValues(formFields),
@@ -814,7 +835,7 @@ function useContactForm(options) {
814
835
  [formFields]
815
836
  ),
816
837
  onSubmit: async (values, helpers) => {
817
- setSubmissionError(null);
838
+ resetSubmissionState();
818
839
  const shouldAutoSubmit = Boolean(formConfig?.endpoint);
819
840
  if (!shouldAutoSubmit && !onSubmit) {
820
841
  return;
@@ -834,12 +855,21 @@ function useContactForm(options) {
834
855
  await onSubmit(submissionValues);
835
856
  }
836
857
  if (shouldAutoSubmit || onSubmit) {
837
- setIsSubmitted(true);
858
+ try {
859
+ await submissionConfig?.handleFormSubmission?.({
860
+ formData: submissionValues,
861
+ responseData: result
862
+ });
863
+ } catch (callbackError) {
864
+ console.error("handleFormSubmission callback failed:", callbackError);
865
+ }
838
866
  if (resetOnSuccess) {
839
867
  helpers.resetForm();
840
868
  }
841
869
  onSuccess?.(result);
842
- setTimeout(() => setIsSubmitted(false), 1e4);
870
+ if (submissionConfig?.behavior === "redirect" && submissionConfig.redirectUrl) {
871
+ performRedirect();
872
+ }
843
873
  }
844
874
  } catch (error) {
845
875
  if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
@@ -854,9 +884,10 @@ function useContactForm(options) {
854
884
  const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
855
885
  return {
856
886
  form,
857
- isSubmitted,
887
+ isSubmitted: form.status === "success",
858
888
  submissionError,
859
- formMethod
889
+ formMethod,
890
+ resetSubmissionState
860
891
  };
861
892
  }
862
893
 
@@ -1242,38 +1273,6 @@ function PatternBackground({
1242
1273
  }
1243
1274
  );
1244
1275
  }
1245
- var FormFeedback = ({
1246
- isSubmitted,
1247
- successMessageClassName,
1248
- successMessage,
1249
- submissionError,
1250
- errorMessageClassName
1251
- }) => {
1252
- if (!isSubmitted && !submissionError) return null;
1253
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1254
- isSubmitted && !submissionError && /* @__PURE__ */ jsx(
1255
- "div",
1256
- {
1257
- className: cn(
1258
- "mb-6 p-4 bg-primary/10 border border-primary rounded-md",
1259
- successMessageClassName
1260
- ),
1261
- children: typeof successMessage === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-primary-foreground/90 text-center", children: successMessage }) : successMessage
1262
- }
1263
- ),
1264
- submissionError && /* @__PURE__ */ jsx(
1265
- "div",
1266
- {
1267
- className: cn(
1268
- "mb-6 p-4 bg-destructive/10 border border-destructive rounded-md",
1269
- errorMessageClassName
1270
- ),
1271
- children: typeof submissionError === "string" ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive text-center", children: submissionError }) : submissionError
1272
- }
1273
- )
1274
- ] });
1275
- };
1276
- var form_feedback_default = FormFeedback;
1277
1276
  var DEFAULT_FORM_FIELDS = [
1278
1277
  {
1279
1278
  name: "first_name",
@@ -1355,7 +1354,7 @@ function ContactPhotography({
1355
1354
  removeFile,
1356
1355
  resetUpload
1357
1356
  } = useFileUpload({ onError });
1358
- const { form, isSubmitted, submissionError, formMethod } = useContactForm({
1357
+ const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
1359
1358
  formFields,
1360
1359
  formConfig,
1361
1360
  onSubmit,
@@ -1445,22 +1444,21 @@ function ContactPhotography({
1445
1444
  children: description
1446
1445
  }
1447
1446
  ) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description })),
1448
- /* @__PURE__ */ jsx(
1449
- form_feedback_default,
1450
- {
1451
- isSubmitted,
1452
- successMessageClassName,
1453
- successMessage,
1454
- submissionError,
1455
- errorMessageClassName
1456
- }
1457
- ),
1458
1447
  /* @__PURE__ */ jsxs(
1459
1448
  Form,
1460
1449
  {
1461
1450
  form,
1462
1451
  action: formConfig?.endpoint,
1463
1452
  method: formMethod,
1453
+ submissionError,
1454
+ successMessage,
1455
+ successMessageClassName,
1456
+ errorMessageClassName,
1457
+ submissionConfig: formConfig?.submissionConfig,
1458
+ onNewSubmission: () => {
1459
+ resetUpload();
1460
+ resetSubmissionState();
1461
+ },
1464
1462
  className: cn("space-y-4", formClassName),
1465
1463
  children: [
1466
1464
  /* @__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';