@opensite/ui 1.9.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/contact-demo.cjs +106 -406
  2. package/dist/contact-demo.d.cts +36 -111
  3. package/dist/contact-demo.d.ts +36 -111
  4. package/dist/contact-demo.js +108 -405
  5. package/dist/contact-emergency.cjs +129 -158
  6. package/dist/contact-emergency.d.cts +23 -12
  7. package/dist/contact-emergency.d.ts +23 -12
  8. package/dist/contact-emergency.js +131 -159
  9. package/dist/contact-event.cjs +106 -147
  10. package/dist/contact-event.d.cts +36 -66
  11. package/dist/contact-event.d.ts +36 -66
  12. package/dist/contact-event.js +108 -148
  13. package/dist/contact-feedback.cjs +109 -102
  14. package/dist/contact-feedback.d.cts +36 -63
  15. package/dist/contact-feedback.d.ts +36 -63
  16. package/dist/contact-feedback.js +111 -103
  17. package/dist/contact-fitness.cjs +107 -148
  18. package/dist/contact-fitness.d.cts +36 -66
  19. package/dist/contact-fitness.d.ts +36 -66
  20. package/dist/contact-fitness.js +109 -149
  21. package/dist/contact-guest.cjs +107 -148
  22. package/dist/contact-guest.d.cts +35 -65
  23. package/dist/contact-guest.d.ts +35 -65
  24. package/dist/contact-guest.js +109 -149
  25. package/dist/contact-image.cjs +108 -149
  26. package/dist/contact-image.d.cts +35 -65
  27. package/dist/contact-image.d.ts +35 -65
  28. package/dist/contact-image.js +110 -150
  29. package/dist/contact-insurance.cjs +107 -148
  30. package/dist/contact-insurance.d.cts +36 -66
  31. package/dist/contact-insurance.d.ts +36 -66
  32. package/dist/contact-insurance.js +109 -149
  33. package/dist/contact-interview.cjs +106 -147
  34. package/dist/contact-interview.d.cts +20 -12
  35. package/dist/contact-interview.d.ts +20 -12
  36. package/dist/contact-interview.js +108 -148
  37. package/dist/contact-locations.cjs +106 -147
  38. package/dist/contact-locations.d.cts +21 -13
  39. package/dist/contact-locations.d.ts +21 -13
  40. package/dist/contact-locations.js +108 -148
  41. package/dist/contact-maintenance.cjs +103 -143
  42. package/dist/contact-maintenance.d.cts +21 -13
  43. package/dist/contact-maintenance.d.ts +21 -13
  44. package/dist/contact-maintenance.js +105 -144
  45. package/dist/contact-map.cjs +103 -143
  46. package/dist/contact-map.d.cts +20 -12
  47. package/dist/contact-map.d.ts +20 -12
  48. package/dist/contact-map.js +105 -144
  49. package/dist/contact-minimal.cjs +126 -242
  50. package/dist/contact-minimal.d.cts +36 -70
  51. package/dist/contact-minimal.d.ts +36 -70
  52. package/dist/contact-minimal.js +128 -243
  53. package/dist/contact-moving.cjs +103 -143
  54. package/dist/contact-moving.d.cts +20 -12
  55. package/dist/contact-moving.d.ts +20 -12
  56. package/dist/contact-moving.js +105 -144
  57. package/dist/contact-multistep.cjs +104 -144
  58. package/dist/contact-multistep.d.cts +21 -13
  59. package/dist/contact-multistep.d.ts +21 -13
  60. package/dist/contact-multistep.js +106 -145
  61. package/dist/contact-partnership.cjs +103 -143
  62. package/dist/contact-partnership.d.cts +19 -11
  63. package/dist/contact-partnership.d.ts +19 -11
  64. package/dist/contact-partnership.js +105 -144
  65. package/dist/contact-press.cjs +144 -150
  66. package/dist/contact-press.d.cts +21 -13
  67. package/dist/contact-press.d.ts +21 -13
  68. package/dist/contact-press.js +146 -151
  69. package/dist/contact-quote.cjs +144 -150
  70. package/dist/contact-quote.d.cts +19 -11
  71. package/dist/contact-quote.d.ts +19 -11
  72. package/dist/contact-quote.js +146 -151
  73. package/dist/contact-referral.cjs +144 -150
  74. package/dist/contact-referral.d.cts +20 -12
  75. package/dist/contact-referral.d.ts +20 -12
  76. package/dist/contact-referral.js +146 -151
  77. package/dist/contact-report.cjs +144 -150
  78. package/dist/contact-report.d.cts +21 -13
  79. package/dist/contact-report.d.ts +21 -13
  80. package/dist/contact-report.js +146 -151
  81. package/dist/contact-reservation.cjs +144 -150
  82. package/dist/contact-reservation.d.cts +20 -12
  83. package/dist/contact-reservation.d.ts +20 -12
  84. package/dist/contact-reservation.js +146 -151
  85. package/dist/contact-retreat.cjs +144 -150
  86. package/dist/contact-retreat.d.cts +21 -13
  87. package/dist/contact-retreat.d.ts +21 -13
  88. package/dist/contact-retreat.js +146 -151
  89. package/dist/contact-rsvp.cjs +144 -150
  90. package/dist/contact-rsvp.d.cts +20 -12
  91. package/dist/contact-rsvp.d.ts +20 -12
  92. package/dist/contact-rsvp.js +146 -151
  93. package/dist/contact-sales.cjs +131 -146
  94. package/dist/contact-sales.d.cts +34 -65
  95. package/dist/contact-sales.d.ts +34 -65
  96. package/dist/contact-sales.js +133 -147
  97. package/dist/contact-schedule.cjs +144 -150
  98. package/dist/contact-schedule.d.cts +20 -12
  99. package/dist/contact-schedule.d.ts +20 -12
  100. package/dist/contact-schedule.js +146 -151
  101. package/dist/contact-sponsorship.cjs +144 -150
  102. package/dist/contact-sponsorship.d.cts +21 -13
  103. package/dist/contact-sponsorship.d.ts +21 -13
  104. package/dist/contact-sponsorship.js +146 -151
  105. package/dist/contact-support.cjs +147 -120
  106. package/dist/contact-support.d.cts +21 -12
  107. package/dist/contact-support.d.ts +21 -12
  108. package/dist/contact-support.js +149 -121
  109. package/dist/contact-tenant.cjs +144 -150
  110. package/dist/contact-tenant.d.cts +20 -12
  111. package/dist/contact-tenant.d.ts +20 -12
  112. package/dist/contact-tenant.js +146 -151
  113. package/dist/contact-vendor.cjs +144 -150
  114. package/dist/contact-vendor.d.cts +20 -12
  115. package/dist/contact-vendor.d.ts +20 -12
  116. package/dist/contact-vendor.js +146 -151
  117. package/dist/contact-volunteer.cjs +144 -150
  118. package/dist/contact-volunteer.d.cts +20 -12
  119. package/dist/contact-volunteer.d.ts +20 -12
  120. package/dist/contact-volunteer.js +146 -151
  121. package/dist/contact-warranty.cjs +144 -150
  122. package/dist/contact-warranty.d.cts +20 -12
  123. package/dist/contact-warranty.d.ts +20 -12
  124. package/dist/contact-warranty.js +146 -151
  125. package/dist/contact-wedding.cjs +144 -150
  126. package/dist/contact-wedding.d.cts +20 -12
  127. package/dist/contact-wedding.d.ts +20 -12
  128. package/dist/contact-wedding.js +146 -151
  129. package/dist/registry.cjs +5791 -5883
  130. package/dist/registry.js +4527 -4619
  131. package/package.json +2 -2
@@ -1,19 +1,14 @@
1
1
  "use client";
2
2
  import * as React from 'react';
3
- import React__default from 'react';
4
- import { useForm, Form, Field } from '@page-speed/forms';
5
- import { Select, TextInput as TextInput$1 } from '@page-speed/forms/inputs';
3
+ import React__default, { useMemo } from 'react';
4
+ import { Form } from '@page-speed/forms';
5
+ import { useFileUpload, useContactForm, getColumnSpanClass, DynamicFormField } from '@page-speed/forms/integration';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import { cva } from 'class-variance-authority';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
- import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
11
- import * as LabelPrimitive from '@radix-ui/react-label';
12
- import * as SeparatorPrimitive from '@radix-ui/react-separator';
13
- import { submitPageSpeedForm, PageSpeedFormSubmissionError } from '@page-speed/forms/integration';
14
10
 
15
11
  // components/blocks/contact/contact-demo.tsx
16
- var TextInput = TextInput$1;
17
12
  function cn(...inputs) {
18
13
  return twMerge(clsx(inputs));
19
14
  }
@@ -435,111 +430,6 @@ var Pressable = React.forwardRef(
435
430
  }
436
431
  );
437
432
  Pressable.displayName = "Pressable";
438
- var svgCache = /* @__PURE__ */ new Map();
439
- function DynamicIcon({
440
- name,
441
- size = 28,
442
- color,
443
- className,
444
- alt
445
- }) {
446
- const [svgContent, setSvgContent] = React.useState(null);
447
- const [isLoading, setIsLoading] = React.useState(true);
448
- const [error, setError] = React.useState(null);
449
- const { url, iconName } = React.useMemo(() => {
450
- const separator = name.includes("/") ? "/" : ":";
451
- const [prefix, iconName2] = name.split(separator);
452
- const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}&key=au382bi7fsh96w9h9xlrnat2jglx`;
453
- return {
454
- url: baseUrl,
455
- iconName: iconName2
456
- };
457
- }, [name, size]);
458
- React.useEffect(() => {
459
- let isMounted = true;
460
- const fetchSvg = async () => {
461
- const cached = svgCache.get(url);
462
- if (cached) {
463
- if (isMounted) {
464
- setSvgContent(cached);
465
- setIsLoading(false);
466
- }
467
- return;
468
- }
469
- try {
470
- setIsLoading(true);
471
- setError(null);
472
- const response = await fetch(url);
473
- if (!response.ok) {
474
- throw new Error(`Failed to fetch icon: ${response.status}`);
475
- }
476
- let svg = await response.text();
477
- svg = processSvgForCurrentColor(svg);
478
- svgCache.set(url, svg);
479
- if (isMounted) {
480
- setSvgContent(svg);
481
- setIsLoading(false);
482
- }
483
- } catch (err) {
484
- if (isMounted) {
485
- setError(err instanceof Error ? err.message : "Failed to load icon");
486
- setIsLoading(false);
487
- }
488
- }
489
- };
490
- fetchSvg();
491
- return () => {
492
- isMounted = false;
493
- };
494
- }, [url]);
495
- if (isLoading) {
496
- return /* @__PURE__ */ jsx(
497
- "span",
498
- {
499
- className: cn("inline-block", className),
500
- style: { width: size, height: size },
501
- "aria-hidden": "true"
502
- }
503
- );
504
- }
505
- if (error || !svgContent) {
506
- return /* @__PURE__ */ jsx(
507
- "span",
508
- {
509
- className: cn("inline-block", className),
510
- style: { width: size, height: size },
511
- role: "img",
512
- "aria-label": alt || iconName
513
- }
514
- );
515
- }
516
- return /* @__PURE__ */ jsx(
517
- "span",
518
- {
519
- className: cn("inline-flex items-center justify-center", className),
520
- style: {
521
- width: size,
522
- height: size,
523
- color: color || "inherit"
524
- },
525
- role: "img",
526
- "aria-label": alt || iconName,
527
- dangerouslySetInnerHTML: { __html: svgContent }
528
- }
529
- );
530
- }
531
- function processSvgForCurrentColor(svg) {
532
- let processed = svg;
533
- processed = processed.replace(
534
- /stroke=["'](#000000|#000|black)["']/gi,
535
- 'stroke="currentColor"'
536
- );
537
- processed = processed.replace(
538
- /fill=["'](#000000|#000|black)["']/gi,
539
- 'fill="currentColor"'
540
- );
541
- return processed;
542
- }
543
433
  function Card({ className, ...props }) {
544
434
  return /* @__PURE__ */ jsx(
545
435
  "div",
@@ -563,66 +453,6 @@ function CardContent({ className, ...props }) {
563
453
  }
564
454
  );
565
455
  }
566
- function Checkbox({
567
- className,
568
- ...props
569
- }) {
570
- return /* @__PURE__ */ jsx(
571
- CheckboxPrimitive.Root,
572
- {
573
- "data-slot": "checkbox",
574
- className: cn(
575
- "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
576
- className
577
- ),
578
- ...props,
579
- children: /* @__PURE__ */ jsx(
580
- CheckboxPrimitive.Indicator,
581
- {
582
- "data-slot": "checkbox-indicator",
583
- className: "grid place-content-center text-current transition-none",
584
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/check", size: 14 })
585
- }
586
- )
587
- }
588
- );
589
- }
590
- function Label({
591
- className,
592
- ...props
593
- }) {
594
- return /* @__PURE__ */ jsx(
595
- LabelPrimitive.Root,
596
- {
597
- "data-slot": "label",
598
- className: cn(
599
- "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",
600
- className
601
- ),
602
- ...props
603
- }
604
- );
605
- }
606
- function Separator({
607
- className,
608
- orientation = "horizontal",
609
- decorative = true,
610
- ...props
611
- }) {
612
- return /* @__PURE__ */ jsx(
613
- SeparatorPrimitive.Root,
614
- {
615
- "data-slot": "separator",
616
- decorative,
617
- orientation,
618
- className: cn(
619
- "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
620
- className
621
- ),
622
- ...props
623
- }
624
- );
625
- }
626
456
  var maxWidthStyles = {
627
457
  sm: "max-w-screen-sm",
628
458
  md: "max-w-screen-md",
@@ -998,36 +828,60 @@ var Section = React__default.forwardRef(
998
828
  }
999
829
  );
1000
830
  Section.displayName = "Section";
1001
- var USE_CASES = [
1002
- { value: "automation", label: "Workflow Automation", icon: "lucide/zap" },
831
+ var DEFAULT_FORM_FIELDS = [
1003
832
  {
1004
- value: "analytics",
1005
- label: "Analytics & Reporting",
1006
- icon: "lucide/bar-chart-3"
833
+ name: "first_name",
834
+ type: "text",
835
+ label: "First Name",
836
+ placeholder: "John",
837
+ required: true,
838
+ columnSpan: 6
1007
839
  },
1008
- { value: "collaboration", label: "Team Collaboration", icon: "lucide/users" }
1009
- ];
1010
- var TEAM_SIZES = [
1011
- { value: "1-10", label: "1-10" },
1012
- { value: "11-50", label: "11-50" },
1013
- { value: "51-200", label: "51-200" },
1014
- { value: "201-500", label: "201-500" },
1015
- { value: "500+", label: "500+" }
1016
- ];
1017
- var TIMELINES = [
1018
- { value: "asap", label: "As soon as possible" },
1019
- { value: "this-week", label: "This week" },
1020
- { value: "this-month", label: "This month" },
1021
- { value: "exploring", label: "Just exploring" }
840
+ {
841
+ name: "last_name",
842
+ type: "text",
843
+ label: "Last Name",
844
+ placeholder: "Doe",
845
+ required: true,
846
+ columnSpan: 6
847
+ },
848
+ {
849
+ name: "email",
850
+ type: "email",
851
+ label: "Email",
852
+ placeholder: "john@example.com",
853
+ required: true,
854
+ columnSpan: 12
855
+ },
856
+ {
857
+ name: "phone",
858
+ type: "tel",
859
+ label: "Phone",
860
+ placeholder: "+1 (555) 000-0000",
861
+ required: true,
862
+ columnSpan: 12
863
+ },
864
+ {
865
+ name: "message",
866
+ type: "textarea",
867
+ label: "Message",
868
+ placeholder: "Your message...",
869
+ required: true,
870
+ rows: 4,
871
+ columnSpan: 12
872
+ }
1022
873
  ];
1023
874
  function ContactDemo({
1024
875
  heading,
1025
876
  description,
1026
- buttonText,
877
+ buttonText = "Submit",
1027
878
  buttonIcon,
1028
879
  actions,
1029
880
  actionsSlot,
881
+ formFields = DEFAULT_FORM_FIELDS,
882
+ successMessage = "Thank you! Your message has been sent successfully.",
1030
883
  className,
884
+ containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
1031
885
  headerClassName,
1032
886
  headingClassName,
1033
887
  descriptionClassName,
@@ -1035,72 +889,38 @@ function ContactDemo({
1035
889
  cardContentClassName,
1036
890
  formClassName,
1037
891
  submitClassName,
1038
- spacing = "py-8 md:py-32",
1039
- containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
1040
- background,
892
+ successMessageClassName,
893
+ errorMessageClassName,
894
+ background = "white",
895
+ spacing = "xl",
1041
896
  pattern,
1042
- patternOpacity,
897
+ patternOpacity = 0.1,
1043
898
  formConfig,
1044
899
  onSubmit,
1045
900
  onSuccess,
1046
901
  onError
1047
902
  }) {
1048
- const form = useForm({
1049
- initialValues: {
1050
- useCase: "",
1051
- teamSize: "",
1052
- timeline: "",
1053
- firstName: "",
1054
- lastName: "",
1055
- email: "",
1056
- company: "",
1057
- jobTitle: "",
1058
- updates: false
903
+ const {
904
+ uploadTokens,
905
+ uploadProgress,
906
+ isUploading,
907
+ uploadFiles,
908
+ removeFile,
909
+ resetUpload
910
+ } = useFileUpload({ onError });
911
+ const { form, submissionError, formMethod, resetSubmissionState } = useContactForm({
912
+ formFields,
913
+ formConfig,
914
+ onSubmit,
915
+ onSuccess: (data) => {
916
+ resetUpload();
917
+ onSuccess?.(data);
1059
918
  },
1060
- validationSchema: {
1061
- useCase: (value) => !value ? "Please select a use case" : void 0,
1062
- teamSize: (value) => !value ? "Please select team size" : void 0,
1063
- timeline: (value) => !value ? "Please select a timeline" : void 0,
1064
- firstName: (value) => !value ? "First name is required" : void 0,
1065
- lastName: (value) => !value ? "Last name is required" : void 0,
1066
- email: (value) => {
1067
- if (!value) return "Email is required";
1068
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value))
1069
- return "Please enter a valid email address";
1070
- return void 0;
1071
- },
1072
- company: (value) => !value ? "Company is required" : void 0
1073
- },
1074
- onSubmit: async (values, helpers) => {
1075
- const shouldAutoSubmit = Boolean(formConfig?.endpoint);
1076
- if (!shouldAutoSubmit && !onSubmit) {
1077
- return;
1078
- }
1079
- try {
1080
- let result;
1081
- if (shouldAutoSubmit) {
1082
- result = await submitPageSpeedForm(values, formConfig);
1083
- }
1084
- if (onSubmit) {
1085
- await onSubmit(values);
1086
- }
1087
- if (shouldAutoSubmit || onSubmit) {
1088
- if (formConfig?.resetOnSuccess !== false) {
1089
- helpers.resetForm();
1090
- }
1091
- onSuccess?.(result);
1092
- }
1093
- } catch (error) {
1094
- if (error instanceof PageSpeedFormSubmissionError && error.formErrors) {
1095
- helpers.setErrors(error.formErrors);
1096
- }
1097
- onError?.(error);
1098
- throw error;
1099
- }
1100
- }
919
+ onError,
920
+ resetOnSuccess: formConfig?.resetOnSuccess !== false,
921
+ uploadTokens
1101
922
  });
1102
- const formMethod = formConfig?.method?.toLowerCase() === "get" ? "get" : "post";
1103
- const actionsContent = React.useMemo(() => {
923
+ const actionsContent = useMemo(() => {
1104
924
  if (actionsSlot) return actionsSlot;
1105
925
  if (actions && actions.length > 0) {
1106
926
  return actions.map((action, index) => {
@@ -1137,9 +957,9 @@ function ContactDemo({
1137
957
  spacing,
1138
958
  pattern,
1139
959
  patternOpacity,
1140
- className,
960
+ className: cn("py-12", className),
1141
961
  containerClassName,
1142
- children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
962
+ children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-4xl", children: [
1143
963
  /* @__PURE__ */ jsxs("div", { className: cn("mb-10 text-center", headerClassName), children: [
1144
964
  heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
1145
965
  "h2",
@@ -1162,174 +982,57 @@ function ContactDemo({
1162
982
  }
1163
983
  ) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description }))
1164
984
  ] }),
1165
- /* @__PURE__ */ jsx(Card, { className: cardClassName, children: /* @__PURE__ */ jsx(CardContent, { className: cn("p-6 lg:p-8", cardContentClassName), children: /* @__PURE__ */ jsxs(
985
+ /* @__PURE__ */ jsx(Card, { className: cn("mx-auto max-w-xl", cardClassName), children: /* @__PURE__ */ jsx(CardContent, { className: cn("p-6 lg:p-8", cardContentClassName), children: /* @__PURE__ */ jsxs(
1166
986
  Form,
1167
987
  {
1168
988
  form,
1169
- action: formConfig?.endpoint,
1170
- method: formMethod,
1171
- className: cn("space-y-8", formClassName),
989
+ notificationConfig: {
990
+ submissionError,
991
+ successMessage
992
+ },
993
+ styleConfig: {
994
+ formClassName: cn("space-y-4", formClassName),
995
+ successMessageClassName,
996
+ errorMessageClassName
997
+ },
998
+ formConfig: {
999
+ endpoint: formConfig?.endpoint,
1000
+ method: formMethod,
1001
+ submissionConfig: formConfig?.submissionConfig
1002
+ },
1003
+ onNewSubmission: () => {
1004
+ resetUpload();
1005
+ resetSubmissionState();
1006
+ },
1172
1007
  children: [
1173
- /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1174
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "What's your primary use case?" }),
1175
- /* @__PURE__ */ jsx(Field, { name: "useCase", children: ({ field, meta }) => /* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs(
1176
- Select,
1177
- {
1178
- ...field,
1179
- id: "use-case",
1180
- error: meta.touched && !!meta.error,
1181
- "aria-label": "Use Case",
1182
- children: [
1183
- /* @__PURE__ */ jsx("option", { value: "", children: "Select a use case" }),
1184
- USE_CASES.map((useCase) => /* @__PURE__ */ jsx("option", { value: useCase.value, children: useCase.label }, useCase.value))
1185
- ]
1186
- }
1187
- ) }) })
1188
- ] }),
1189
- /* @__PURE__ */ jsx(Separator, {}),
1190
- /* @__PURE__ */ jsxs("div", { className: "grid gap-6 sm:grid-cols-2", children: [
1191
- /* @__PURE__ */ jsx(Field, { name: "teamSize", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1192
- /* @__PURE__ */ jsx(Label, { htmlFor: "team-size", children: "Team Size" }),
1193
- /* @__PURE__ */ jsxs(
1194
- Select,
1195
- {
1196
- ...field,
1197
- id: "team-size",
1198
- error: meta.touched && !!meta.error,
1199
- "aria-label": "Team Size",
1200
- children: [
1201
- /* @__PURE__ */ jsx("option", { value: "", children: "Select team size" }),
1202
- TEAM_SIZES.map((size) => /* @__PURE__ */ jsx("option", { value: size.value, children: size.label }, size.value))
1203
- ]
1204
- }
1205
- )
1206
- ] }) }),
1207
- /* @__PURE__ */ jsx(Field, { name: "timeline", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1208
- /* @__PURE__ */ jsx(Label, { htmlFor: "timeline", children: "When do you need this?" }),
1209
- /* @__PURE__ */ jsxs(
1210
- Select,
1211
- {
1212
- ...field,
1213
- id: "timeline",
1214
- error: meta.touched && !!meta.error,
1215
- "aria-label": "Timeline",
1216
- children: [
1217
- /* @__PURE__ */ jsx("option", { value: "", children: "Select timeline" }),
1218
- TIMELINES.map((time) => /* @__PURE__ */ jsx("option", { value: time.value, children: time.label }, time.value))
1219
- ]
1220
- }
1221
- )
1222
- ] }) })
1223
- ] }),
1224
- /* @__PURE__ */ jsx(Separator, {}),
1225
- /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
1226
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "Your Information" }),
1227
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
1228
- /* @__PURE__ */ jsx(Field, { name: "firstName", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1229
- /* @__PURE__ */ jsx(Label, { htmlFor: "first-name", children: "First Name" }),
1230
- /* @__PURE__ */ jsx(
1231
- TextInput,
1232
- {
1233
- ...field,
1234
- id: "first-name",
1235
- placeholder: "John",
1236
- error: meta.touched && !!meta.error,
1237
- "aria-label": "First Name"
1238
- }
1239
- )
1240
- ] }) }),
1241
- /* @__PURE__ */ jsx(Field, { name: "lastName", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1242
- /* @__PURE__ */ jsx(Label, { htmlFor: "last-name", children: "Last Name" }),
1243
- /* @__PURE__ */ jsx(
1244
- TextInput,
1245
- {
1246
- ...field,
1247
- id: "last-name",
1248
- placeholder: "Doe",
1249
- error: meta.touched && !!meta.error,
1250
- "aria-label": "Last Name"
1251
- }
1252
- )
1253
- ] }) })
1254
- ] }),
1255
- /* @__PURE__ */ jsx(Field, { name: "email", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1256
- /* @__PURE__ */ jsx(Label, { htmlFor: "email", children: "Work Email" }),
1257
- /* @__PURE__ */ jsx(
1258
- TextInput,
1259
- {
1260
- ...field,
1261
- id: "email",
1262
- type: "email",
1263
- placeholder: "john@company.com",
1264
- error: meta.touched && !!meta.error,
1265
- "aria-label": "Work Email"
1266
- }
1267
- )
1268
- ] }) }),
1269
- /* @__PURE__ */ jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [
1270
- /* @__PURE__ */ jsx(Field, { name: "company", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1271
- /* @__PURE__ */ jsx(Label, { htmlFor: "company", children: "Company" }),
1272
- /* @__PURE__ */ jsx(
1273
- TextInput,
1274
- {
1275
- ...field,
1276
- id: "company",
1277
- placeholder: "Acme Inc.",
1278
- error: meta.touched && !!meta.error,
1279
- "aria-label": "Company"
1280
- }
1281
- )
1282
- ] }) }),
1283
- /* @__PURE__ */ jsx(Field, { name: "jobTitle", children: ({ field, meta }) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1284
- /* @__PURE__ */ jsx(Label, { htmlFor: "job-title", children: "Job Title (Optional)" }),
1285
- /* @__PURE__ */ jsx(
1286
- TextInput,
1287
- {
1288
- ...field,
1289
- id: "job-title",
1290
- placeholder: "Product Manager",
1291
- error: meta.touched && !!meta.error,
1292
- "aria-label": "Job Title"
1293
- }
1294
- )
1295
- ] }) })
1296
- ] }),
1297
- /* @__PURE__ */ jsx(Field, { name: "updates", children: ({ field }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1298
- /* @__PURE__ */ jsx(
1299
- Checkbox,
1300
- {
1301
- id: "updates",
1302
- checked: field.value,
1303
- onCheckedChange: (checked) => field.onChange(checked === true)
1304
- }
1305
- ),
1306
- /* @__PURE__ */ jsx(
1307
- Label,
1008
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-12 gap-6", children: formFields.map((field) => /* @__PURE__ */ jsx(
1009
+ "div",
1010
+ {
1011
+ className: getColumnSpanClass(field.columnSpan),
1012
+ children: /* @__PURE__ */ jsx(
1013
+ DynamicFormField,
1308
1014
  {
1309
- htmlFor: "updates",
1310
- className: "cursor-pointer text-sm font-normal",
1311
- children: "Send me product updates and announcements"
1015
+ field,
1016
+ uploadProgress,
1017
+ onFileUpload: uploadFiles,
1018
+ onFileRemove: removeFile,
1019
+ isUploading
1312
1020
  }
1313
1021
  )
1314
- ] }) })
1315
- ] }),
1022
+ },
1023
+ field.name
1024
+ )) }),
1316
1025
  actionsSlot || actions && actions.length > 0 ? actionsContent : /* @__PURE__ */ jsxs(
1317
1026
  Pressable,
1318
1027
  {
1319
1028
  componentType: "button",
1320
1029
  type: "submit",
1321
1030
  className: cn("w-full", submitClassName),
1031
+ size: "lg",
1322
1032
  asButton: true,
1323
1033
  disabled: form.isSubmitting,
1324
1034
  children: [
1325
- buttonIcon ?? /* @__PURE__ */ jsx(
1326
- DynamicIcon,
1327
- {
1328
- name: "lucide/calendar",
1329
- size: 16,
1330
- className: "mr-2"
1331
- }
1332
- ),
1035
+ buttonIcon,
1333
1036
  buttonText
1334
1037
  ]
1335
1038
  }