@forms.expert/sdk 0.1.3 → 0.1.5

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.
@@ -517,9 +517,9 @@ function useForm(options) {
517
517
  submit,
518
518
  reset,
519
519
  clearErrors,
520
- requiresCaptcha: config?.settings?.captcha?.enabled ?? false,
521
- captchaProvider: config?.settings?.captcha?.provider,
522
- captchaSiteKey: config?.settings?.captcha?.siteKey,
520
+ requiresCaptcha: config?.captcha?.enabled ?? config?.settings?.captcha?.enabled ?? false,
521
+ captchaProvider: config?.captcha?.provider ?? config?.settings?.captcha?.provider,
522
+ captchaSiteKey: config?.captcha?.siteKey ?? config?.settings?.captcha?.siteKey,
523
523
  honeypotEnabled: config?.settings?.honeypot ?? false,
524
524
  allowsAttachments,
525
525
  maxAttachments,
@@ -554,6 +554,22 @@ function getBorderRadius(radius) {
554
554
  return "0.375rem";
555
555
  }
556
556
  }
557
+ function getButtonRadius(radius) {
558
+ switch (radius) {
559
+ case "none":
560
+ return "0";
561
+ case "small":
562
+ return "4px";
563
+ case "medium":
564
+ return "8px";
565
+ case "large":
566
+ return "12px";
567
+ case "full":
568
+ return "9999px";
569
+ default:
570
+ return "8px";
571
+ }
572
+ }
557
573
  function getFontSize(size) {
558
574
  switch (size) {
559
575
  case "sm":
@@ -566,6 +582,94 @@ function getFontSize(size) {
566
582
  return "1rem";
567
583
  }
568
584
  }
585
+ function getPlaceholderFontSize(size) {
586
+ switch (size) {
587
+ case "small":
588
+ return "0.75rem";
589
+ case "large":
590
+ return "1rem";
591
+ default:
592
+ return "0.875rem";
593
+ }
594
+ }
595
+ function getFieldSpacing(spacing) {
596
+ switch (spacing) {
597
+ case "compact":
598
+ return "0.5rem";
599
+ case "relaxed":
600
+ return "1.5rem";
601
+ case "spacious":
602
+ return "2rem";
603
+ default:
604
+ return "1rem";
605
+ }
606
+ }
607
+ function getFormPadding(padding) {
608
+ switch (padding) {
609
+ case "compact":
610
+ return "1rem";
611
+ case "relaxed":
612
+ return "2.5rem";
613
+ case "spacious":
614
+ return "3.5rem";
615
+ default:
616
+ return "1.5rem";
617
+ }
618
+ }
619
+ function getLabelSpacing(spacing) {
620
+ switch (spacing) {
621
+ case "compact":
622
+ return "0.125rem";
623
+ case "relaxed":
624
+ return "0.75rem";
625
+ default:
626
+ return "0.25rem";
627
+ }
628
+ }
629
+ function getFormMaxWidth(width) {
630
+ switch (width) {
631
+ case "narrow":
632
+ return "28rem";
633
+ case "wide":
634
+ return "48rem";
635
+ case "full":
636
+ return "100%";
637
+ default:
638
+ return "36rem";
639
+ }
640
+ }
641
+ function getButtonAlign(align) {
642
+ switch (align) {
643
+ case "left":
644
+ return "flex-start";
645
+ case "right":
646
+ return "flex-end";
647
+ default:
648
+ return "center";
649
+ }
650
+ }
651
+ function getHeadingSize(size) {
652
+ switch (size) {
653
+ case "small":
654
+ return "1.125rem";
655
+ case "large":
656
+ return "1.875rem";
657
+ case "extra-large":
658
+ return "2.25rem";
659
+ default:
660
+ return "1.5rem";
661
+ }
662
+ }
663
+ function getParagraphSize(size) {
664
+ switch (size) {
665
+ case "small":
666
+ return "0.875rem";
667
+ case "large":
668
+ return "1.125rem";
669
+ default:
670
+ return "1rem";
671
+ }
672
+ }
569
673
  function FormsExpertForm({
570
674
  config,
571
675
  slug,
@@ -669,9 +773,19 @@ function FormsExpertForm({
669
773
  }
670
774
  }
671
775
  };
672
- const styling = form.config?.schema?.styling || defaultStyling;
776
+ const styling = { ...defaultStyling, ...form.config?.schema?.styling, ...form.config?.styling };
673
777
  const radius = getBorderRadius(styling.borderRadius);
778
+ const btnRadius = getButtonRadius(styling.buttonRadius);
674
779
  const fontSize = getFontSize(styling.fontSize);
780
+ const phFontSize = getPlaceholderFontSize(styling.placeholderFontSize);
781
+ const fieldSpacing = getFieldSpacing(styling.fieldSpacing);
782
+ const formPadding = getFormPadding(styling.formPadding);
783
+ const labelSpacing = getLabelSpacing(styling.labelSpacing);
784
+ const formMaxWidth = getFormMaxWidth(styling.formWidth);
785
+ const btnColor = styling.buttonColor || styling.primaryColor;
786
+ const fontFamily = styling.fontFamily || "system-ui, -apple-system, sans-serif";
787
+ const btnAlign = getButtonAlign(styling.buttonAlign);
788
+ const resolvedButtonText = styling.buttonText || submitText;
675
789
  const handleSubmit = async (e) => {
676
790
  e.preventDefault();
677
791
  const result = await form.submit(captchaToken || void 0);
@@ -720,19 +834,26 @@ function FormsExpertForm({
720
834
  );
721
835
  }
722
836
  if (form.isSubmitted) {
723
- return /* @__PURE__ */ jsxs(
837
+ return /* @__PURE__ */ jsx2(
724
838
  "div",
725
839
  {
726
840
  className,
727
841
  style: {
728
- padding: "2rem",
842
+ display: "flex",
843
+ alignItems: "center",
844
+ justifyContent: "center",
845
+ minHeight: "100%",
846
+ padding: formPadding,
729
847
  textAlign: "center",
730
- backgroundColor: styling.backgroundColor,
848
+ backgroundColor: styling.transparentBackground ? "transparent" : styling.backgroundColor,
731
849
  color: styling.textColor,
732
850
  borderRadius: radius,
851
+ maxWidth: formMaxWidth,
852
+ margin: "0 auto",
853
+ fontFamily,
733
854
  ...style
734
855
  },
735
- children: [
856
+ children: /* @__PURE__ */ jsxs("div", { children: [
736
857
  /* @__PURE__ */ jsx2(
737
858
  "svg",
738
859
  {
@@ -740,7 +861,7 @@ function FormsExpertForm({
740
861
  width: "3rem",
741
862
  height: "3rem",
742
863
  margin: "0 auto 1rem",
743
- color: "#22c55e"
864
+ color: styling.successColor || "#22c55e"
744
865
  },
745
866
  fill: "none",
746
867
  stroke: "currentColor",
@@ -764,39 +885,69 @@ function FormsExpertForm({
764
885
  onClick: form.reset,
765
886
  style: {
766
887
  marginTop: "1rem",
767
- padding: "0.5rem 1rem",
768
- backgroundColor: "transparent",
888
+ background: "none",
889
+ border: "none",
769
890
  color: styling.primaryColor,
770
- border: `1px solid ${styling.primaryColor}`,
771
- borderRadius: radius,
772
- cursor: "pointer"
891
+ textDecoration: "underline",
892
+ cursor: "pointer",
893
+ fontSize: "0.875rem"
773
894
  },
774
- children: "Submit another response"
895
+ children: "Submit again"
775
896
  }
776
897
  )
777
- ]
898
+ ] })
778
899
  }
779
900
  );
780
901
  }
781
902
  const fields = form.config.schema?.fields || [];
782
903
  const showBranding = form.config.branding?.enabled !== false;
783
- const brandingText = form.config.branding?.text || "Powered by Mira";
784
- const brandingUrl = form.config.branding?.url || "https://mira.io";
785
- return /* @__PURE__ */ jsxs(
904
+ const brandingText = form.config.branding?.text || "Powered by forms.expert";
905
+ const brandingUrl = form.config.branding?.url || "https://forms.expert";
906
+ const wrapperStyle = {
907
+ ...styling.backgroundImageUrl ? {
908
+ backgroundImage: `url(${styling.backgroundImageUrl})`,
909
+ backgroundSize: "cover",
910
+ backgroundPosition: "center"
911
+ } : {},
912
+ position: "relative"
913
+ };
914
+ const formEl = /* @__PURE__ */ jsxs(
786
915
  "form",
787
916
  {
788
917
  onSubmit: handleSubmit,
789
918
  className,
790
919
  style: {
791
- fontFamily: "system-ui, -apple-system, sans-serif",
920
+ fontFamily,
792
921
  fontSize,
793
- backgroundColor: styling.backgroundColor,
922
+ backgroundColor: styling.transparentBackground ? "transparent" : styling.backgroundColor,
794
923
  color: styling.textColor,
795
- padding: "1.5rem",
924
+ padding: formPadding,
796
925
  borderRadius: radius,
926
+ maxWidth: formMaxWidth,
927
+ width: "100%",
928
+ margin: "0 auto",
929
+ position: "relative",
797
930
  ...style
798
931
  },
799
932
  children: [
933
+ styling.logoUrl && /* @__PURE__ */ jsx2("div", { style: {
934
+ textAlign: styling.logoPosition === "top-left" ? "left" : styling.logoPosition === "top-right" ? "right" : "center",
935
+ marginBottom: "1rem"
936
+ }, children: /* @__PURE__ */ jsx2("img", { src: styling.logoUrl, alt: "", style: { maxHeight: "48px" } }) }),
937
+ styling.coverImageUrl && /* @__PURE__ */ jsx2(
938
+ "img",
939
+ {
940
+ src: styling.coverImageUrl,
941
+ alt: "",
942
+ style: {
943
+ width: "100%",
944
+ maxHeight: "200px",
945
+ objectFit: "cover",
946
+ borderRadius: `${radius} ${radius} 0 0`,
947
+ marginBottom: "1rem"
948
+ }
949
+ }
950
+ ),
800
951
  fields.map((field) => /* @__PURE__ */ jsx2(
801
952
  FormFieldInput,
802
953
  {
@@ -804,34 +955,37 @@ function FormsExpertForm({
804
955
  value: form.values[field.name],
805
956
  error: form.errors[field.name],
806
957
  onChange: handleChange,
807
- styling
958
+ onValueChange: (name, val) => form.setValue(name, val),
959
+ styling,
960
+ fieldSpacing,
961
+ labelSpacing,
962
+ phFontSize
808
963
  },
809
964
  field.name
810
965
  )),
811
966
  form.honeypotEnabled && /* @__PURE__ */ jsx2("div", { style: { position: "absolute", left: "-9999px", opacity: 0, height: 0, overflow: "hidden" }, "aria-hidden": "true", children: /* @__PURE__ */ jsx2("input", { type: "text", name: "_hp", tabIndex: -1, autoComplete: "off" }) }),
812
967
  form.requiresCaptcha && form.captchaProvider !== "recaptcha" && /* @__PURE__ */ jsx2("div", { ref: captchaContainerRef, style: { marginTop: "1rem" } }),
813
- /* @__PURE__ */ jsx2(
968
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", justifyContent: btnAlign, marginTop: "1rem" }, children: /* @__PURE__ */ jsx2(
814
969
  "button",
815
970
  {
816
971
  type: "submit",
817
972
  disabled: form.isLoading,
818
973
  style: {
819
- width: "100%",
974
+ ...styling.buttonAlign ? {} : { width: "100%" },
820
975
  padding: "0.625rem 1.25rem",
821
- marginTop: "1rem",
822
976
  fontWeight: 500,
823
977
  fontSize,
824
978
  fontFamily: "inherit",
825
- borderRadius: radius,
979
+ borderRadius: btnRadius,
826
980
  cursor: form.isLoading ? "not-allowed" : "pointer",
827
981
  opacity: form.isLoading ? 0.5 : 1,
828
- backgroundColor: styling.buttonStyle === "filled" ? styling.primaryColor : "transparent",
829
- color: styling.buttonStyle === "filled" ? "white" : styling.primaryColor,
830
- border: styling.buttonStyle === "filled" ? "none" : `2px solid ${styling.primaryColor}`
982
+ backgroundColor: styling.buttonStyle === "filled" ? btnColor : "transparent",
983
+ color: styling.buttonStyle === "filled" ? "white" : btnColor,
984
+ border: styling.buttonStyle === "filled" ? "none" : `2px solid ${btnColor}`
831
985
  },
832
- children: form.isLoading ? "Submitting..." : submitText
986
+ children: form.isLoading ? "Submitting..." : resolvedButtonText
833
987
  }
834
- ),
988
+ ) }),
835
989
  showBranding && /* @__PURE__ */ jsx2(
836
990
  "div",
837
991
  {
@@ -860,16 +1014,33 @@ function FormsExpertForm({
860
1014
  ]
861
1015
  }
862
1016
  );
1017
+ if (styling.backgroundImageUrl) {
1018
+ return /* @__PURE__ */ jsxs("div", { style: wrapperStyle, children: [
1019
+ styling.backgroundOverlay ? /* @__PURE__ */ jsx2("div", { style: {
1020
+ position: "absolute",
1021
+ inset: 0,
1022
+ backgroundColor: `rgba(0,0,0,${styling.backgroundOverlay})`,
1023
+ pointerEvents: "none"
1024
+ } }) : null,
1025
+ formEl
1026
+ ] });
1027
+ }
1028
+ return formEl;
863
1029
  }
864
1030
  function FormFieldInput({
865
1031
  field,
866
1032
  value,
867
1033
  error,
868
1034
  onChange,
869
- styling
1035
+ onValueChange,
1036
+ styling,
1037
+ fieldSpacing,
1038
+ labelSpacing,
1039
+ phFontSize
870
1040
  }) {
871
1041
  const radius = getBorderRadius(styling.borderRadius);
872
1042
  const fontSize = getFontSize(styling.fontSize);
1043
+ const isInline = styling.labelPosition === "left" || styling.fieldLayout === "inline";
873
1044
  const inputStyle = {
874
1045
  width: "100%",
875
1046
  padding: "0.5rem 0.75rem",
@@ -880,8 +1051,37 @@ function FormFieldInput({
880
1051
  backgroundColor: styling.theme === "dark" ? "#374151" : "#ffffff",
881
1052
  color: styling.textColor
882
1053
  };
883
- if (field.type === "checkbox") {
884
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "1rem" }, children: [
1054
+ const getOpts = () => {
1055
+ if (!field.options) return [];
1056
+ return field.options.map((o) => typeof o === "string" ? { value: o, label: o } : o);
1057
+ };
1058
+ if (field.type === "heading") {
1059
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: fieldSpacing }, children: [
1060
+ /* @__PURE__ */ jsx2("h2", { style: { fontSize: getHeadingSize(styling.headingSize), fontWeight: 600 }, children: field.label }),
1061
+ field.content && /* @__PURE__ */ jsx2("p", { style: { fontSize: "0.875rem", color: styling.theme === "dark" ? "#9ca3af" : "#6b7280", marginTop: "0.25rem" }, children: field.content })
1062
+ ] });
1063
+ }
1064
+ if (field.type === "divider") {
1065
+ return /* @__PURE__ */ jsx2("hr", { style: { marginBottom: fieldSpacing, border: "none", borderTop: `1px solid ${styling.theme === "dark" ? "#4b5563" : "#d1d5db"}` } });
1066
+ }
1067
+ if (field.type === "paragraph") {
1068
+ const pSize = field.paragraphFontSize ? `${field.paragraphFontSize}px` : getParagraphSize(styling.paragraphSize);
1069
+ return /* @__PURE__ */ jsxs("div", { style: { marginBottom: fieldSpacing }, children: [
1070
+ field.label && /* @__PURE__ */ jsx2("p", { style: { fontWeight: 500, fontSize: pSize, marginBottom: "0.25rem" }, children: field.label }),
1071
+ field.content && /* @__PURE__ */ jsx2(
1072
+ "div",
1073
+ {
1074
+ style: { fontSize: pSize, color: styling.theme === "dark" ? "#9ca3af" : "#6b7280" },
1075
+ dangerouslySetInnerHTML: { __html: field.content }
1076
+ }
1077
+ )
1078
+ ] });
1079
+ }
1080
+ if (field.type === "hidden") {
1081
+ return /* @__PURE__ */ jsx2("input", { type: "hidden", name: field.name, value: String(value || field.defaultValue || "") });
1082
+ }
1083
+ if (field.type === "checkbox" || field.type === "toggle" || field.type === "consent") {
1084
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: fieldSpacing }, children: [
885
1085
  /* @__PURE__ */ jsx2(
886
1086
  "input",
887
1087
  {
@@ -895,91 +1095,312 @@ function FormFieldInput({
895
1095
  }
896
1096
  ),
897
1097
  /* @__PURE__ */ jsxs("label", { htmlFor: field.name, children: [
898
- field.label || field.name,
899
- field.required && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
1098
+ field.type === "consent" && field.consentText ? field.consentUrl ? /* @__PURE__ */ jsxs("span", { children: [
1099
+ field.consentText,
1100
+ " ",
1101
+ /* @__PURE__ */ jsx2("a", { href: field.consentUrl, target: "_blank", rel: "noopener noreferrer", style: { color: styling.primaryColor }, children: "(link)" })
1102
+ ] }) : field.consentText : field.label || field.name,
1103
+ field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
900
1104
  ] }),
901
- error && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", fontSize: "0.875rem", marginLeft: "0.5rem" }, children: error })
1105
+ error && /* @__PURE__ */ jsx2("span", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginLeft: "0.5rem" }, children: error })
1106
+ ] });
1107
+ }
1108
+ const labelEl = /* @__PURE__ */ jsxs(
1109
+ "label",
1110
+ {
1111
+ htmlFor: field.name,
1112
+ style: {
1113
+ display: "block",
1114
+ fontWeight: 500,
1115
+ ...isInline ? { width: "33%", flexShrink: 0, paddingTop: "0.5rem", marginBottom: 0 } : { marginBottom: labelSpacing }
1116
+ },
1117
+ children: [
1118
+ field.label || field.name,
1119
+ field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
1120
+ ]
1121
+ }
1122
+ );
1123
+ const errorEl = error ? /* @__PURE__ */ jsx2("div", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginTop: "0.25rem" }, children: error }) : null;
1124
+ let fieldEl;
1125
+ if (field.type === "textarea" || field.type === "richText") {
1126
+ fieldEl = /* @__PURE__ */ jsx2(
1127
+ "textarea",
1128
+ {
1129
+ id: field.name,
1130
+ name: field.name,
1131
+ value: String(value || ""),
1132
+ onChange,
1133
+ placeholder: field.placeholder,
1134
+ required: field.required,
1135
+ style: { ...inputStyle, minHeight: "100px", resize: "vertical" }
1136
+ }
1137
+ );
1138
+ } else if (field.type === "select" || field.type === "dropdown") {
1139
+ fieldEl = /* @__PURE__ */ jsxs("select", { id: field.name, name: field.name, value: String(value || ""), onChange, required: field.required, style: inputStyle, children: [
1140
+ /* @__PURE__ */ jsx2("option", { value: "", children: "Select an option..." }),
1141
+ getOpts().map((opt) => /* @__PURE__ */ jsx2("option", { value: opt.value, children: opt.label }, opt.value))
902
1142
  ] });
1143
+ } else if (field.type === "radio") {
1144
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: getOpts().map((opt) => /* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: "0.5rem", cursor: "pointer" }, children: [
1145
+ /* @__PURE__ */ jsx2(
1146
+ "input",
1147
+ {
1148
+ type: "radio",
1149
+ name: field.name,
1150
+ value: opt.value,
1151
+ checked: value === opt.value,
1152
+ onChange: () => onValueChange(field.name, opt.value),
1153
+ style: { accentColor: styling.primaryColor }
1154
+ }
1155
+ ),
1156
+ opt.label
1157
+ ] }, opt.value)) });
1158
+ } else if (field.type === "multiselect") {
1159
+ const selected = Array.isArray(value) ? value : [];
1160
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: getOpts().map((opt) => /* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: "0.5rem", cursor: "pointer" }, children: [
1161
+ /* @__PURE__ */ jsx2(
1162
+ "input",
1163
+ {
1164
+ type: "checkbox",
1165
+ checked: selected.includes(opt.value),
1166
+ onChange: () => {
1167
+ const next = selected.includes(opt.value) ? selected.filter((v) => v !== opt.value) : [...selected, opt.value];
1168
+ onValueChange(field.name, next);
1169
+ },
1170
+ style: { accentColor: styling.primaryColor }
1171
+ }
1172
+ ),
1173
+ opt.label
1174
+ ] }, opt.value)) });
1175
+ } else if (field.type === "rating") {
1176
+ const max = field.ratingMax || 5;
1177
+ const current = Number(value) || 0;
1178
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "0.25rem" }, children: Array.from({ length: max }, (_, i) => i + 1).map((n) => /* @__PURE__ */ jsx2(
1179
+ "button",
1180
+ {
1181
+ type: "button",
1182
+ onClick: () => onValueChange(field.name, n),
1183
+ style: {
1184
+ width: "2rem",
1185
+ height: "2rem",
1186
+ cursor: "pointer",
1187
+ border: "none",
1188
+ background: "none",
1189
+ padding: 0,
1190
+ fontSize: "1.5rem",
1191
+ color: n <= current ? "#f59e0b" : styling.theme === "dark" ? "#4b5563" : "#d1d5db",
1192
+ transition: "color 0.15s"
1193
+ },
1194
+ children: "\u2605"
1195
+ },
1196
+ n
1197
+ )) });
1198
+ } else if (field.type === "scale" || field.type === "opinionScale") {
1199
+ const min = field.min ?? 1;
1200
+ const max = field.max ?? 10;
1201
+ const current = value;
1202
+ fieldEl = /* @__PURE__ */ jsxs("div", { children: [
1203
+ /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "0.25rem", flexWrap: "wrap" }, children: Array.from({ length: max - min + 1 }, (_, i) => min + i).map((n) => /* @__PURE__ */ jsx2(
1204
+ "button",
1205
+ {
1206
+ type: "button",
1207
+ onClick: () => onValueChange(field.name, n),
1208
+ style: {
1209
+ minWidth: "2.25rem",
1210
+ height: "2.25rem",
1211
+ borderRadius: radius,
1212
+ cursor: "pointer",
1213
+ border: `1px solid ${styling.theme === "dark" ? "#4b5563" : "#d1d5db"}`,
1214
+ background: current === n ? styling.primaryColor : styling.theme === "dark" ? "#374151" : "#ffffff",
1215
+ color: current === n ? "white" : styling.textColor,
1216
+ fontSize: "0.875rem",
1217
+ transition: "all 0.15s"
1218
+ },
1219
+ children: n
1220
+ },
1221
+ n
1222
+ )) }),
1223
+ (field.lowLabel || field.highLabel) && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", fontSize: "0.75rem", color: styling.theme === "dark" ? "#9ca3af" : "#6b7280", marginTop: "0.25rem" }, children: [
1224
+ /* @__PURE__ */ jsx2("span", { children: field.lowLabel }),
1225
+ /* @__PURE__ */ jsx2("span", { children: field.highLabel })
1226
+ ] })
1227
+ ] });
1228
+ } else if (field.type === "slider") {
1229
+ const min = field.min ?? 0;
1230
+ const max = field.max ?? 100;
1231
+ const step = field.step ?? 1;
1232
+ fieldEl = /* @__PURE__ */ jsxs("div", { children: [
1233
+ /* @__PURE__ */ jsx2(
1234
+ "input",
1235
+ {
1236
+ type: "range",
1237
+ id: field.name,
1238
+ name: field.name,
1239
+ min,
1240
+ max,
1241
+ step,
1242
+ value: Number(value) || min,
1243
+ onChange: (e) => onValueChange(field.name, Number(e.target.value)),
1244
+ style: { width: "100%", accentColor: styling.primaryColor }
1245
+ }
1246
+ ),
1247
+ /* @__PURE__ */ jsx2("div", { style: { textAlign: "center", fontSize: "0.875rem", marginTop: "0.25rem" }, children: String(value ?? min) })
1248
+ ] });
1249
+ } else if (field.type === "imageChoice") {
1250
+ const selected = value;
1251
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: getOpts().map((opt) => /* @__PURE__ */ jsxs(
1252
+ "button",
1253
+ {
1254
+ type: "button",
1255
+ onClick: () => onValueChange(field.name, opt.value),
1256
+ style: {
1257
+ border: `2px solid ${selected === opt.value ? styling.primaryColor : styling.theme === "dark" ? "#4b5563" : "#d1d5db"}`,
1258
+ borderRadius: radius,
1259
+ padding: "0.5rem",
1260
+ cursor: "pointer",
1261
+ textAlign: "center",
1262
+ background: "none",
1263
+ transition: "border-color 0.15s"
1264
+ },
1265
+ children: [
1266
+ opt.imageUrl && /* @__PURE__ */ jsx2("img", { src: opt.imageUrl, alt: opt.label, style: { maxWidth: "80px", maxHeight: "80px", objectFit: "cover", borderRadius: radius } }),
1267
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: "0.875rem", marginTop: "0.25rem" }, children: opt.label })
1268
+ ]
1269
+ },
1270
+ opt.value
1271
+ )) });
1272
+ } else if (field.type === "file") {
1273
+ fieldEl = /* @__PURE__ */ jsx2(
1274
+ "input",
1275
+ {
1276
+ type: "file",
1277
+ id: field.name,
1278
+ name: field.name,
1279
+ onChange,
1280
+ required: field.required,
1281
+ accept: field.allowedMimeTypes?.join(","),
1282
+ multiple: field.multiple,
1283
+ style: inputStyle
1284
+ }
1285
+ );
1286
+ } else if (field.type === "name") {
1287
+ const nameVal = value || {};
1288
+ const nameFields = field.nameFields || ["first", "last"];
1289
+ const labels = { prefix: "Prefix", first: "First Name", middle: "Middle", last: "Last Name", suffix: "Suffix" };
1290
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "0.5rem", flexWrap: "wrap" }, children: nameFields.map((nf) => /* @__PURE__ */ jsx2(
1291
+ "input",
1292
+ {
1293
+ placeholder: labels[nf] || nf,
1294
+ value: nameVal[nf] || "",
1295
+ onChange: (e) => onValueChange(field.name, { ...nameVal, [nf]: e.target.value }),
1296
+ style: { ...inputStyle, flex: 1, minWidth: "120px" }
1297
+ },
1298
+ nf
1299
+ )) });
1300
+ } else if (field.type === "address") {
1301
+ const addr = value || {};
1302
+ const addrFields = field.addressFields || ["street", "city", "state", "zip", "country"];
1303
+ const labels = { street: "Street", street2: "Street 2", city: "City", state: "State", zip: "ZIP", country: "Country" };
1304
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: addrFields.map((af) => /* @__PURE__ */ jsx2(
1305
+ "input",
1306
+ {
1307
+ placeholder: labels[af] || af,
1308
+ value: addr[af] || "",
1309
+ onChange: (e) => onValueChange(field.name, { ...addr, [af]: e.target.value }),
1310
+ style: inputStyle
1311
+ },
1312
+ af
1313
+ )) });
1314
+ } else if (field.type === "currency") {
1315
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
1316
+ field.currencySymbol && /* @__PURE__ */ jsx2("span", { children: field.currencySymbol }),
1317
+ /* @__PURE__ */ jsx2(
1318
+ "input",
1319
+ {
1320
+ type: "number",
1321
+ id: field.name,
1322
+ name: field.name,
1323
+ value: String(value || ""),
1324
+ onChange,
1325
+ step: 0.01,
1326
+ min: field.min,
1327
+ max: field.max,
1328
+ required: field.required,
1329
+ style: inputStyle
1330
+ }
1331
+ )
1332
+ ] });
1333
+ } else if (field.type === "colorPicker") {
1334
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [
1335
+ /* @__PURE__ */ jsx2(
1336
+ "input",
1337
+ {
1338
+ type: "color",
1339
+ id: field.name,
1340
+ value: String(value || "#000000"),
1341
+ onChange: (e) => onValueChange(field.name, e.target.value),
1342
+ style: { width: "3rem", height: "2.25rem", border: "none", cursor: "pointer", padding: 0 }
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsx2(
1346
+ "input",
1347
+ {
1348
+ type: "text",
1349
+ value: String(value || ""),
1350
+ onChange: (e) => onValueChange(field.name, e.target.value),
1351
+ placeholder: "#000000",
1352
+ style: { ...inputStyle, flex: 1 }
1353
+ }
1354
+ )
1355
+ ] });
1356
+ } else if (field.type === "dateRange") {
1357
+ const range = value || {};
1358
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [
1359
+ /* @__PURE__ */ jsx2("input", { type: "date", value: range.start || "", onChange: (e) => onValueChange(field.name, { ...range, start: e.target.value }), style: { ...inputStyle, flex: 1 } }),
1360
+ /* @__PURE__ */ jsx2("span", { children: "to" }),
1361
+ /* @__PURE__ */ jsx2("input", { type: "date", value: range.end || "", onChange: (e) => onValueChange(field.name, { ...range, end: e.target.value }), style: { ...inputStyle, flex: 1 } })
1362
+ ] });
1363
+ } else {
1364
+ const typeMap = {
1365
+ phone: "tel",
1366
+ url: "url",
1367
+ datetime: "datetime-local",
1368
+ time: "time",
1369
+ date: "date",
1370
+ number: "number",
1371
+ email: "email",
1372
+ password: "password"
1373
+ };
1374
+ fieldEl = /* @__PURE__ */ jsx2(
1375
+ "input",
1376
+ {
1377
+ type: typeMap[field.type] || "text",
1378
+ id: field.name,
1379
+ name: field.name,
1380
+ value: String(value || ""),
1381
+ onChange,
1382
+ placeholder: field.placeholder,
1383
+ required: field.required,
1384
+ min: field.min,
1385
+ max: field.max,
1386
+ step: field.step,
1387
+ maxLength: field.maxLength,
1388
+ style: inputStyle
1389
+ }
1390
+ );
903
1391
  }
904
1392
  return /* @__PURE__ */ jsxs(
905
1393
  "div",
906
1394
  {
907
1395
  style: {
908
- marginBottom: "1rem",
909
- ...styling.labelPosition === "left" ? { display: "flex", alignItems: "flex-start", gap: "1rem" } : {}
1396
+ marginBottom: fieldSpacing,
1397
+ ...isInline ? { display: "flex", alignItems: "flex-start", gap: "1rem" } : {}
910
1398
  },
911
1399
  children: [
912
- /* @__PURE__ */ jsxs(
913
- "label",
914
- {
915
- htmlFor: field.name,
916
- style: {
917
- display: "block",
918
- fontWeight: 500,
919
- ...styling.labelPosition === "left" ? { width: "33%", flexShrink: 0, paddingTop: "0.5rem" } : { marginBottom: "0.25rem" }
920
- },
921
- children: [
922
- field.label || field.name,
923
- field.required && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
924
- ]
925
- }
926
- ),
927
- /* @__PURE__ */ jsxs("div", { style: styling.labelPosition === "left" ? { flex: 1 } : {}, children: [
928
- field.type === "textarea" ? /* @__PURE__ */ jsx2(
929
- "textarea",
930
- {
931
- id: field.name,
932
- name: field.name,
933
- value: String(value || ""),
934
- onChange,
935
- placeholder: field.placeholder,
936
- required: field.required,
937
- style: { ...inputStyle, minHeight: "100px", resize: "vertical" }
938
- }
939
- ) : field.type === "select" ? /* @__PURE__ */ jsxs(
940
- "select",
941
- {
942
- id: field.name,
943
- name: field.name,
944
- value: String(value || ""),
945
- onChange,
946
- required: field.required,
947
- style: inputStyle,
948
- children: [
949
- /* @__PURE__ */ jsx2("option", { value: "", children: "Select an option..." }),
950
- field.options?.map((opt) => {
951
- const val = typeof opt === "string" ? opt : opt.value;
952
- const label = typeof opt === "string" ? opt : opt.label;
953
- return /* @__PURE__ */ jsx2("option", { value: val, children: label }, val);
954
- })
955
- ]
956
- }
957
- ) : field.type === "file" ? /* @__PURE__ */ jsx2(
958
- "input",
959
- {
960
- type: "file",
961
- id: field.name,
962
- name: field.name,
963
- onChange,
964
- required: field.required,
965
- accept: field.allowedMimeTypes?.join(","),
966
- multiple: field.multiple,
967
- style: inputStyle
968
- }
969
- ) : /* @__PURE__ */ jsx2(
970
- "input",
971
- {
972
- type: field.type,
973
- id: field.name,
974
- name: field.name,
975
- value: String(value || ""),
976
- onChange,
977
- placeholder: field.placeholder,
978
- required: field.required,
979
- style: inputStyle
980
- }
981
- ),
982
- error && /* @__PURE__ */ jsx2("div", { style: { color: "#ef4444", fontSize: "0.875rem", marginTop: "0.25rem" }, children: error })
1400
+ labelEl,
1401
+ /* @__PURE__ */ jsxs("div", { style: isInline ? { flex: 1 } : {}, children: [
1402
+ fieldEl,
1403
+ errorEl
983
1404
  ] })
984
1405
  ]
985
1406
  }