@forms.expert/sdk 0.1.2 → 0.1.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.
@@ -31,7 +31,7 @@ var FormsApiClient = class {
31
31
  constructor(config) {
32
32
  this.apiKey = config.apiKey;
33
33
  this.resourceId = config.resourceId;
34
- this.baseUrl = (config.baseUrl || "https://api.formsapp.io/api/v1").replace(/\/$/, "");
34
+ this.baseUrl = (config.baseUrl || "https://api.forms.expert/api/v1").replace(/\/$/, "");
35
35
  }
36
36
  /**
37
37
  * Build URL with token query parameter
@@ -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,
@@ -671,7 +775,17 @@ function FormsExpertForm({
671
775
  };
672
776
  const styling = form.config?.schema?.styling || defaultStyling;
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,25 @@ 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__ */ jsx2("h2", { style: { marginBottom: fieldSpacing, fontSize: getHeadingSize(styling.headingSize), fontWeight: 600 }, children: field.content || field.label });
1060
+ }
1061
+ if (field.type === "divider") {
1062
+ return /* @__PURE__ */ jsx2("hr", { style: { marginBottom: fieldSpacing, border: "none", borderTop: `1px solid ${styling.theme === "dark" ? "#4b5563" : "#d1d5db"}` } });
1063
+ }
1064
+ if (field.type === "paragraph") {
1065
+ const pSize = field.paragraphFontSize ? `${field.paragraphFontSize}px` : getParagraphSize(styling.paragraphSize);
1066
+ return /* @__PURE__ */ jsx2("p", { style: { marginBottom: fieldSpacing, fontSize: pSize, color: styling.theme === "dark" ? "#9ca3af" : "#6b7280" }, children: field.content || field.label });
1067
+ }
1068
+ if (field.type === "hidden") {
1069
+ return /* @__PURE__ */ jsx2("input", { type: "hidden", name: field.name, value: String(value || field.defaultValue || "") });
1070
+ }
1071
+ if (field.type === "checkbox" || field.type === "toggle" || field.type === "consent") {
1072
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: fieldSpacing }, children: [
885
1073
  /* @__PURE__ */ jsx2(
886
1074
  "input",
887
1075
  {
@@ -895,91 +1083,312 @@ function FormFieldInput({
895
1083
  }
896
1084
  ),
897
1085
  /* @__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: "*" })
1086
+ field.type === "consent" && field.consentText ? field.consentUrl ? /* @__PURE__ */ jsxs("span", { children: [
1087
+ field.consentText,
1088
+ " ",
1089
+ /* @__PURE__ */ jsx2("a", { href: field.consentUrl, target: "_blank", rel: "noopener noreferrer", style: { color: styling.primaryColor }, children: "(link)" })
1090
+ ] }) : field.consentText : field.label || field.name,
1091
+ field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
900
1092
  ] }),
901
- error && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", fontSize: "0.875rem", marginLeft: "0.5rem" }, children: error })
1093
+ error && /* @__PURE__ */ jsx2("span", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginLeft: "0.5rem" }, children: error })
1094
+ ] });
1095
+ }
1096
+ const labelEl = /* @__PURE__ */ jsxs(
1097
+ "label",
1098
+ {
1099
+ htmlFor: field.name,
1100
+ style: {
1101
+ display: "block",
1102
+ fontWeight: 500,
1103
+ ...isInline ? { width: "33%", flexShrink: 0, paddingTop: "0.5rem", marginBottom: 0 } : { marginBottom: labelSpacing }
1104
+ },
1105
+ children: [
1106
+ field.label || field.name,
1107
+ field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
1108
+ ]
1109
+ }
1110
+ );
1111
+ const errorEl = error ? /* @__PURE__ */ jsx2("div", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginTop: "0.25rem" }, children: error }) : null;
1112
+ let fieldEl;
1113
+ if (field.type === "textarea" || field.type === "richText") {
1114
+ fieldEl = /* @__PURE__ */ jsx2(
1115
+ "textarea",
1116
+ {
1117
+ id: field.name,
1118
+ name: field.name,
1119
+ value: String(value || ""),
1120
+ onChange,
1121
+ placeholder: field.placeholder,
1122
+ required: field.required,
1123
+ style: { ...inputStyle, minHeight: "100px", resize: "vertical" }
1124
+ }
1125
+ );
1126
+ } else if (field.type === "select" || field.type === "dropdown") {
1127
+ fieldEl = /* @__PURE__ */ jsxs("select", { id: field.name, name: field.name, value: String(value || ""), onChange, required: field.required, style: inputStyle, children: [
1128
+ /* @__PURE__ */ jsx2("option", { value: "", children: "Select an option..." }),
1129
+ getOpts().map((opt) => /* @__PURE__ */ jsx2("option", { value: opt.value, children: opt.label }, opt.value))
1130
+ ] });
1131
+ } else if (field.type === "radio") {
1132
+ 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: [
1133
+ /* @__PURE__ */ jsx2(
1134
+ "input",
1135
+ {
1136
+ type: "radio",
1137
+ name: field.name,
1138
+ value: opt.value,
1139
+ checked: value === opt.value,
1140
+ onChange: () => onValueChange(field.name, opt.value),
1141
+ style: { accentColor: styling.primaryColor }
1142
+ }
1143
+ ),
1144
+ opt.label
1145
+ ] }, opt.value)) });
1146
+ } else if (field.type === "multiselect") {
1147
+ const selected = Array.isArray(value) ? value : [];
1148
+ 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: [
1149
+ /* @__PURE__ */ jsx2(
1150
+ "input",
1151
+ {
1152
+ type: "checkbox",
1153
+ checked: selected.includes(opt.value),
1154
+ onChange: () => {
1155
+ const next = selected.includes(opt.value) ? selected.filter((v) => v !== opt.value) : [...selected, opt.value];
1156
+ onValueChange(field.name, next);
1157
+ },
1158
+ style: { accentColor: styling.primaryColor }
1159
+ }
1160
+ ),
1161
+ opt.label
1162
+ ] }, opt.value)) });
1163
+ } else if (field.type === "rating") {
1164
+ const max = field.ratingMax || 5;
1165
+ const current = Number(value) || 0;
1166
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "0.25rem" }, children: Array.from({ length: max }, (_, i) => i + 1).map((n) => /* @__PURE__ */ jsx2(
1167
+ "button",
1168
+ {
1169
+ type: "button",
1170
+ onClick: () => onValueChange(field.name, n),
1171
+ style: {
1172
+ width: "2rem",
1173
+ height: "2rem",
1174
+ cursor: "pointer",
1175
+ border: "none",
1176
+ background: "none",
1177
+ padding: 0,
1178
+ fontSize: "1.5rem",
1179
+ color: n <= current ? "#f59e0b" : styling.theme === "dark" ? "#4b5563" : "#d1d5db",
1180
+ transition: "color 0.15s"
1181
+ },
1182
+ children: "\u2605"
1183
+ },
1184
+ n
1185
+ )) });
1186
+ } else if (field.type === "scale" || field.type === "opinionScale") {
1187
+ const min = field.min ?? 1;
1188
+ const max = field.max ?? 10;
1189
+ const current = value;
1190
+ fieldEl = /* @__PURE__ */ jsxs("div", { children: [
1191
+ /* @__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(
1192
+ "button",
1193
+ {
1194
+ type: "button",
1195
+ onClick: () => onValueChange(field.name, n),
1196
+ style: {
1197
+ minWidth: "2.25rem",
1198
+ height: "2.25rem",
1199
+ borderRadius: radius,
1200
+ cursor: "pointer",
1201
+ border: `1px solid ${styling.theme === "dark" ? "#4b5563" : "#d1d5db"}`,
1202
+ background: current === n ? styling.primaryColor : styling.theme === "dark" ? "#374151" : "#ffffff",
1203
+ color: current === n ? "white" : styling.textColor,
1204
+ fontSize: "0.875rem",
1205
+ transition: "all 0.15s"
1206
+ },
1207
+ children: n
1208
+ },
1209
+ n
1210
+ )) }),
1211
+ (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: [
1212
+ /* @__PURE__ */ jsx2("span", { children: field.lowLabel }),
1213
+ /* @__PURE__ */ jsx2("span", { children: field.highLabel })
1214
+ ] })
1215
+ ] });
1216
+ } else if (field.type === "slider") {
1217
+ const min = field.min ?? 0;
1218
+ const max = field.max ?? 100;
1219
+ const step = field.step ?? 1;
1220
+ fieldEl = /* @__PURE__ */ jsxs("div", { children: [
1221
+ /* @__PURE__ */ jsx2(
1222
+ "input",
1223
+ {
1224
+ type: "range",
1225
+ id: field.name,
1226
+ name: field.name,
1227
+ min,
1228
+ max,
1229
+ step,
1230
+ value: Number(value) || min,
1231
+ onChange: (e) => onValueChange(field.name, Number(e.target.value)),
1232
+ style: { width: "100%", accentColor: styling.primaryColor }
1233
+ }
1234
+ ),
1235
+ /* @__PURE__ */ jsx2("div", { style: { textAlign: "center", fontSize: "0.875rem", marginTop: "0.25rem" }, children: String(value ?? min) })
1236
+ ] });
1237
+ } else if (field.type === "imageChoice") {
1238
+ const selected = value;
1239
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem" }, children: getOpts().map((opt) => /* @__PURE__ */ jsxs(
1240
+ "button",
1241
+ {
1242
+ type: "button",
1243
+ onClick: () => onValueChange(field.name, opt.value),
1244
+ style: {
1245
+ border: `2px solid ${selected === opt.value ? styling.primaryColor : styling.theme === "dark" ? "#4b5563" : "#d1d5db"}`,
1246
+ borderRadius: radius,
1247
+ padding: "0.5rem",
1248
+ cursor: "pointer",
1249
+ textAlign: "center",
1250
+ background: "none",
1251
+ transition: "border-color 0.15s"
1252
+ },
1253
+ children: [
1254
+ opt.imageUrl && /* @__PURE__ */ jsx2("img", { src: opt.imageUrl, alt: opt.label, style: { maxWidth: "80px", maxHeight: "80px", objectFit: "cover", borderRadius: radius } }),
1255
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: "0.875rem", marginTop: "0.25rem" }, children: opt.label })
1256
+ ]
1257
+ },
1258
+ opt.value
1259
+ )) });
1260
+ } else if (field.type === "file") {
1261
+ fieldEl = /* @__PURE__ */ jsx2(
1262
+ "input",
1263
+ {
1264
+ type: "file",
1265
+ id: field.name,
1266
+ name: field.name,
1267
+ onChange,
1268
+ required: field.required,
1269
+ accept: field.allowedMimeTypes?.join(","),
1270
+ multiple: field.multiple,
1271
+ style: inputStyle
1272
+ }
1273
+ );
1274
+ } else if (field.type === "name") {
1275
+ const nameVal = value || {};
1276
+ const nameFields = field.nameFields || ["first", "last"];
1277
+ const labels = { prefix: "Prefix", first: "First Name", middle: "Middle", last: "Last Name", suffix: "Suffix" };
1278
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", gap: "0.5rem", flexWrap: "wrap" }, children: nameFields.map((nf) => /* @__PURE__ */ jsx2(
1279
+ "input",
1280
+ {
1281
+ placeholder: labels[nf] || nf,
1282
+ value: nameVal[nf] || "",
1283
+ onChange: (e) => onValueChange(field.name, { ...nameVal, [nf]: e.target.value }),
1284
+ style: { ...inputStyle, flex: 1, minWidth: "120px" }
1285
+ },
1286
+ nf
1287
+ )) });
1288
+ } else if (field.type === "address") {
1289
+ const addr = value || {};
1290
+ const addrFields = field.addressFields || ["street", "city", "state", "zip", "country"];
1291
+ const labels = { street: "Street", street2: "Street 2", city: "City", state: "State", zip: "ZIP", country: "Country" };
1292
+ fieldEl = /* @__PURE__ */ jsx2("div", { style: { display: "flex", flexDirection: "column", gap: "0.5rem" }, children: addrFields.map((af) => /* @__PURE__ */ jsx2(
1293
+ "input",
1294
+ {
1295
+ placeholder: labels[af] || af,
1296
+ value: addr[af] || "",
1297
+ onChange: (e) => onValueChange(field.name, { ...addr, [af]: e.target.value }),
1298
+ style: inputStyle
1299
+ },
1300
+ af
1301
+ )) });
1302
+ } else if (field.type === "currency") {
1303
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
1304
+ field.currencySymbol && /* @__PURE__ */ jsx2("span", { children: field.currencySymbol }),
1305
+ /* @__PURE__ */ jsx2(
1306
+ "input",
1307
+ {
1308
+ type: "number",
1309
+ id: field.name,
1310
+ name: field.name,
1311
+ value: String(value || ""),
1312
+ onChange,
1313
+ step: 0.01,
1314
+ min: field.min,
1315
+ max: field.max,
1316
+ required: field.required,
1317
+ style: inputStyle
1318
+ }
1319
+ )
1320
+ ] });
1321
+ } else if (field.type === "colorPicker") {
1322
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [
1323
+ /* @__PURE__ */ jsx2(
1324
+ "input",
1325
+ {
1326
+ type: "color",
1327
+ id: field.name,
1328
+ value: String(value || "#000000"),
1329
+ onChange: (e) => onValueChange(field.name, e.target.value),
1330
+ style: { width: "3rem", height: "2.25rem", border: "none", cursor: "pointer", padding: 0 }
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ jsx2(
1334
+ "input",
1335
+ {
1336
+ type: "text",
1337
+ value: String(value || ""),
1338
+ onChange: (e) => onValueChange(field.name, e.target.value),
1339
+ placeholder: "#000000",
1340
+ style: { ...inputStyle, flex: 1 }
1341
+ }
1342
+ )
902
1343
  ] });
1344
+ } else if (field.type === "dateRange") {
1345
+ const range = value || {};
1346
+ fieldEl = /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [
1347
+ /* @__PURE__ */ jsx2("input", { type: "date", value: range.start || "", onChange: (e) => onValueChange(field.name, { ...range, start: e.target.value }), style: { ...inputStyle, flex: 1 } }),
1348
+ /* @__PURE__ */ jsx2("span", { children: "to" }),
1349
+ /* @__PURE__ */ jsx2("input", { type: "date", value: range.end || "", onChange: (e) => onValueChange(field.name, { ...range, end: e.target.value }), style: { ...inputStyle, flex: 1 } })
1350
+ ] });
1351
+ } else {
1352
+ const typeMap = {
1353
+ phone: "tel",
1354
+ url: "url",
1355
+ datetime: "datetime-local",
1356
+ time: "time",
1357
+ date: "date",
1358
+ number: "number",
1359
+ email: "email",
1360
+ password: "password"
1361
+ };
1362
+ fieldEl = /* @__PURE__ */ jsx2(
1363
+ "input",
1364
+ {
1365
+ type: typeMap[field.type] || "text",
1366
+ id: field.name,
1367
+ name: field.name,
1368
+ value: String(value || ""),
1369
+ onChange,
1370
+ placeholder: field.placeholder,
1371
+ required: field.required,
1372
+ min: field.min,
1373
+ max: field.max,
1374
+ step: field.step,
1375
+ maxLength: field.maxLength,
1376
+ style: inputStyle
1377
+ }
1378
+ );
903
1379
  }
904
1380
  return /* @__PURE__ */ jsxs(
905
1381
  "div",
906
1382
  {
907
1383
  style: {
908
- marginBottom: "1rem",
909
- ...styling.labelPosition === "left" ? { display: "flex", alignItems: "flex-start", gap: "1rem" } : {}
1384
+ marginBottom: fieldSpacing,
1385
+ ...isInline ? { display: "flex", alignItems: "flex-start", gap: "1rem" } : {}
910
1386
  },
911
1387
  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 })
1388
+ labelEl,
1389
+ /* @__PURE__ */ jsxs("div", { style: isInline ? { flex: 1 } : {}, children: [
1390
+ fieldEl,
1391
+ errorEl
983
1392
  ] })
984
1393
  ]
985
1394
  }