@forms.expert/sdk 0.3.0 → 0.4.1

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.
@@ -42,6 +42,7 @@ interface FormField {
42
42
  paragraphFontSize?: number;
43
43
  consentText?: string;
44
44
  consentUrl?: string;
45
+ consentFontSize?: number;
45
46
  maxLength?: number;
46
47
  stepId?: string;
47
48
  visibleWhen?: {
@@ -68,20 +69,22 @@ interface SecondaryButton {
68
69
  color?: string;
69
70
  textColor?: string;
70
71
  fontSize?: number;
72
+ icon?: string;
73
+ iconPosition?: 'left' | 'right';
71
74
  }
72
75
  /**
73
76
  * Form styling configuration
74
77
  */
75
78
  interface FormStyling {
76
- theme: 'light' | 'dark' | 'system';
79
+ theme: 'light' | 'dark' | 'system' | 'custom';
77
80
  primaryColor: string;
78
81
  backgroundColor: string;
79
82
  textColor: string;
80
83
  errorColor?: string;
81
84
  successColor?: string;
82
85
  borderRadius: 'none' | 'sm' | 'md' | 'lg';
83
- fontSize: 'sm' | 'md' | 'lg';
84
- buttonStyle: 'filled' | 'outline';
86
+ fontSize: 'sm' | 'md' | 'lg' | 'small' | 'medium' | 'large';
87
+ buttonStyle: 'filled' | 'outline' | 'outlined' | 'minimal';
85
88
  labelPosition: 'top' | 'left' | 'floating';
86
89
  labelClassName?: string;
87
90
  fieldClassName?: string;
@@ -102,6 +105,8 @@ interface FormStyling {
102
105
  buttonGradient?: string;
103
106
  buttonFullWidth?: boolean;
104
107
  buttonFontSize?: number;
108
+ buttonIcon?: string;
109
+ buttonIconPosition?: 'left' | 'right';
105
110
  fieldSpacing?: 'compact' | 'normal' | 'relaxed' | 'spacious';
106
111
  formPadding?: 'none' | 'compact' | 'normal' | 'relaxed' | 'spacious';
107
112
  labelSpacing?: 'compact' | 'normal' | 'relaxed';
@@ -118,6 +123,8 @@ interface FormStyling {
118
123
  backgroundOverlay?: number;
119
124
  transparentBackground?: boolean;
120
125
  secondaryButton?: SecondaryButton;
126
+ inputBackgroundColor?: string;
127
+ placeholderColor?: string;
121
128
  }
122
129
  /**
123
130
  * Form schema
@@ -42,6 +42,7 @@ interface FormField {
42
42
  paragraphFontSize?: number;
43
43
  consentText?: string;
44
44
  consentUrl?: string;
45
+ consentFontSize?: number;
45
46
  maxLength?: number;
46
47
  stepId?: string;
47
48
  visibleWhen?: {
@@ -68,20 +69,22 @@ interface SecondaryButton {
68
69
  color?: string;
69
70
  textColor?: string;
70
71
  fontSize?: number;
72
+ icon?: string;
73
+ iconPosition?: 'left' | 'right';
71
74
  }
72
75
  /**
73
76
  * Form styling configuration
74
77
  */
75
78
  interface FormStyling {
76
- theme: 'light' | 'dark' | 'system';
79
+ theme: 'light' | 'dark' | 'system' | 'custom';
77
80
  primaryColor: string;
78
81
  backgroundColor: string;
79
82
  textColor: string;
80
83
  errorColor?: string;
81
84
  successColor?: string;
82
85
  borderRadius: 'none' | 'sm' | 'md' | 'lg';
83
- fontSize: 'sm' | 'md' | 'lg';
84
- buttonStyle: 'filled' | 'outline';
86
+ fontSize: 'sm' | 'md' | 'lg' | 'small' | 'medium' | 'large';
87
+ buttonStyle: 'filled' | 'outline' | 'outlined' | 'minimal';
85
88
  labelPosition: 'top' | 'left' | 'floating';
86
89
  labelClassName?: string;
87
90
  fieldClassName?: string;
@@ -102,6 +105,8 @@ interface FormStyling {
102
105
  buttonGradient?: string;
103
106
  buttonFullWidth?: boolean;
104
107
  buttonFontSize?: number;
108
+ buttonIcon?: string;
109
+ buttonIconPosition?: 'left' | 'right';
105
110
  fieldSpacing?: 'compact' | 'normal' | 'relaxed' | 'spacious';
106
111
  formPadding?: 'none' | 'compact' | 'normal' | 'relaxed' | 'spacious';
107
112
  labelSpacing?: 'compact' | 'normal' | 'relaxed';
@@ -118,6 +123,8 @@ interface FormStyling {
118
123
  backgroundOverlay?: number;
119
124
  transparentBackground?: boolean;
120
125
  secondaryButton?: SecondaryButton;
126
+ inputBackgroundColor?: string;
127
+ placeholderColor?: string;
121
128
  }
122
129
  /**
123
130
  * Form schema
@@ -633,10 +633,13 @@ function getButtonRadius(radius) {
633
633
  function getFontSize(size) {
634
634
  switch (size) {
635
635
  case "sm":
636
+ case "small":
636
637
  return "0.875rem";
637
638
  case "md":
639
+ case "medium":
638
640
  return "1rem";
639
641
  case "lg":
642
+ case "large":
640
643
  return "1.125rem";
641
644
  default:
642
645
  return "1rem";
@@ -1050,7 +1053,7 @@ function FormsExpertForm({
1050
1053
  children: [
1051
1054
  googleFontUrl && /* @__PURE__ */ jsx2("link", { rel: "stylesheet", href: googleFontUrl }),
1052
1055
  /* @__PURE__ */ jsx2("style", { dangerouslySetInnerHTML: { __html: `
1053
- form[data-fe-scope="${formScopeId}"] input::placeholder, form[data-fe-scope="${formScopeId}"] textarea::placeholder { font-size: ${phFontSize}; }
1056
+ form[data-fe-scope="${formScopeId}"] input::placeholder, form[data-fe-scope="${formScopeId}"] textarea::placeholder { font-size: ${phFontSize};${styling.placeholderColor ? ` color: ${styling.placeholderColor};` : ""} }
1054
1057
  form[data-fe-scope="${formScopeId}"] button[type="submit"]:hover:not(:disabled) { filter: brightness(0.9); }
1055
1058
  form[data-fe-scope="${formScopeId}"] button[type="submit"]:active:not(:disabled) { filter: brightness(0.85); transform: scale(0.98); }
1056
1059
  form[data-fe-scope="${formScopeId}"] a[href]:hover { filter: brightness(0.9); }
@@ -1162,8 +1165,12 @@ function FormsExpertForm({
1162
1165
  } : void 0;
1163
1166
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1164
1167
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: btnAlign, marginTop: "1rem", gap: "0.5rem", flexWrap: "wrap" }, children: [
1165
- sec?.enabled && secStyle && sec.position === "left" && /* @__PURE__ */ jsx2("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: secStyle, children: sec.text || "Learn More" }),
1166
- /* @__PURE__ */ jsx2(
1168
+ sec?.enabled && secStyle && sec.position === "left" && /* @__PURE__ */ jsxs("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: { ...secStyle, display: "inline-flex", alignItems: "center", gap: "0.5rem" }, children: [
1169
+ sec.icon && sec.iconPosition !== "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } }),
1170
+ /* @__PURE__ */ jsx2("span", { children: sec.text || "Learn More" }),
1171
+ sec.icon && sec.iconPosition === "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } })
1172
+ ] }),
1173
+ /* @__PURE__ */ jsxs(
1167
1174
  "button",
1168
1175
  {
1169
1176
  type: "submit",
@@ -1187,19 +1194,35 @@ function FormsExpertForm({
1187
1194
  minWidth: 0,
1188
1195
  whiteSpace: "nowrap",
1189
1196
  overflow: "hidden",
1190
- textOverflow: "ellipsis"
1197
+ textOverflow: "ellipsis",
1198
+ display: "inline-flex",
1199
+ alignItems: "center",
1200
+ justifyContent: "center",
1201
+ gap: "0.5rem"
1191
1202
  },
1192
- children: form.isLoading ? "Submitting..." : resolvedButtonText
1203
+ children: [
1204
+ !form.isLoading && styling.buttonIcon && styling.buttonIconPosition !== "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: styling.buttonIcon } }),
1205
+ /* @__PURE__ */ jsx2("span", { children: form.isLoading ? "Submitting..." : resolvedButtonText }),
1206
+ !form.isLoading && styling.buttonIcon && styling.buttonIconPosition === "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: styling.buttonIcon } })
1207
+ ]
1193
1208
  }
1194
1209
  ),
1195
- sec?.enabled && secStyle && sec.position !== "left" && sec.position !== "below" && /* @__PURE__ */ jsx2("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: { ...secStyle, marginLeft: "auto" }, children: sec.text || "Learn More" })
1210
+ sec?.enabled && secStyle && sec.position !== "left" && sec.position !== "below" && /* @__PURE__ */ jsxs("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: { ...secStyle, display: "inline-flex", alignItems: "center", gap: "0.5rem", marginLeft: "auto" }, children: [
1211
+ sec.icon && sec.iconPosition !== "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } }),
1212
+ /* @__PURE__ */ jsx2("span", { children: sec.text || "Learn More" }),
1213
+ sec.icon && sec.iconPosition === "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } })
1214
+ ] })
1196
1215
  ] }),
1197
1216
  sec?.enabled && secStyle && sec.position === "below" && /* @__PURE__ */ jsx2("div", { style: {
1198
1217
  display: "flex",
1199
1218
  justifyContent: sec.align === "center" ? "center" : sec.align === "right" ? "flex-end" : sec.align === "left" ? "flex-start" : btnAlign,
1200
1219
  marginTop: sec.marginTop != null ? `${sec.marginTop}px` : "0.5rem",
1201
1220
  marginBottom: sec.marginBottom != null ? `${sec.marginBottom}px` : void 0
1202
- }, children: /* @__PURE__ */ jsx2("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: { ...secStyle, marginTop: 0, marginBottom: 0 }, children: sec.text || "Learn More" }) })
1221
+ }, children: /* @__PURE__ */ jsxs("a", { href: sec.href || "#", target: sec.openInNewTab ? "_blank" : void 0, rel: sec.openInNewTab ? "noopener noreferrer" : void 0, style: { ...secStyle, display: "inline-flex", alignItems: "center", gap: "0.5rem", marginTop: 0, marginBottom: 0 }, children: [
1222
+ sec.icon && sec.iconPosition !== "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } }),
1223
+ /* @__PURE__ */ jsx2("span", { children: sec.text || "Learn More" }),
1224
+ sec.icon && sec.iconPosition === "right" && /* @__PURE__ */ jsx2("span", { style: { display: "inline-flex", flexShrink: 0 }, dangerouslySetInnerHTML: { __html: sec.icon } })
1225
+ ] }) })
1203
1226
  ] });
1204
1227
  })(),
1205
1228
  showBranding && /* @__PURE__ */ jsx2(
@@ -1267,7 +1290,7 @@ function FormFieldInput({
1267
1290
  borderRadius: isBottomBorder ? 0 : fieldRadius,
1268
1291
  fontSize,
1269
1292
  fontFamily: "inherit",
1270
- backgroundColor: styling.theme === "dark" ? "#374151" : "#ffffff",
1293
+ backgroundColor: styling.inputBackgroundColor || (styling.theme === "dark" ? "#374151" : "#ffffff"),
1271
1294
  color: styling.textColor
1272
1295
  };
1273
1296
  const getOpts = () => {
@@ -1300,7 +1323,8 @@ function FormFieldInput({
1300
1323
  return /* @__PURE__ */ jsx2("input", { type: "hidden", name: field.name, value: String(value || field.defaultValue || "") });
1301
1324
  }
1302
1325
  if (field.type === "checkbox" || field.type === "toggle" || field.type === "consent") {
1303
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: fieldSpacing }, children: [
1326
+ const consentSize = field.type === "consent" && field.consentFontSize ? `${field.consentFontSize}px` : void 0;
1327
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "flex-start", gap: "0.5rem", marginBottom: fieldSpacing }, children: [
1304
1328
  /* @__PURE__ */ jsx2(
1305
1329
  "input",
1306
1330
  {
@@ -1310,18 +1334,17 @@ function FormFieldInput({
1310
1334
  checked: Boolean(value),
1311
1335
  onChange,
1312
1336
  required: field.required,
1313
- style: { width: "1rem", height: "1rem", accentColor: styling.primaryColor }
1337
+ style: { width: "1rem", height: "1rem", accentColor: styling.primaryColor, marginTop: "0.125rem", flexShrink: 0 }
1314
1338
  }
1315
1339
  ),
1316
- (field.label || field.type === "consent" && field.consentText) && /* @__PURE__ */ jsxs("label", { htmlFor: field.name, className: styling.labelClassName, children: [
1317
- field.type === "consent" && field.consentText ? field.consentUrl ? /* @__PURE__ */ jsxs("span", { children: [
1318
- field.consentText,
1319
- " ",
1320
- /* @__PURE__ */ jsx2("a", { href: field.consentUrl, target: "_blank", rel: "noopener noreferrer", style: { color: styling.primaryColor }, children: "(link)" })
1321
- ] }) : field.consentText : field.label,
1322
- field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
1323
- ] }),
1324
- error && /* @__PURE__ */ jsx2("span", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginLeft: "0.5rem" }, children: error })
1340
+ /* @__PURE__ */ jsxs("div", { children: [
1341
+ (field.label || field.type === "consent" && field.consentText) && /* @__PURE__ */ jsxs("label", { htmlFor: field.name, className: styling.labelClassName, style: { cursor: "pointer", ...consentSize ? { fontSize: consentSize } : {} }, children: [
1342
+ field.type === "consent" && field.consentText ? field.consentText : field.label,
1343
+ field.required && !styling.hideRequiredAsterisk && /* @__PURE__ */ jsx2("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
1344
+ ] }),
1345
+ field.type === "consent" && field.consentUrl && /* @__PURE__ */ jsx2("a", { href: field.consentUrl, target: "_blank", rel: "noopener noreferrer", style: { color: styling.primaryColor, fontSize: "0.75rem", marginTop: "0.125rem", display: "inline-block" }, children: "View policy" }),
1346
+ error && /* @__PURE__ */ jsx2("div", { style: { color: styling.errorColor || "#ef4444", fontSize: "0.875rem", marginTop: "0.25rem" }, children: error })
1347
+ ] })
1325
1348
  ] });
1326
1349
  }
1327
1350
  const labelEl = field.label ? /* @__PURE__ */ jsxs(