@forms.expert/sdk 0.4.3 → 0.4.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.
@@ -94,9 +94,11 @@ interface FormStyling {
94
94
  formWidth?: 'narrow' | 'medium' | 'wide' | 'full';
95
95
  fieldLayout?: 'stacked' | 'inline';
96
96
  fieldBorderStyle?: 'full' | 'bottom';
97
+ fieldBorderColor?: string;
97
98
  fieldBorderRadius?: 'none' | 'small' | 'medium' | 'large' | 'full';
98
99
  fieldPaddingX?: number;
99
100
  fieldPaddingY?: number;
101
+ separatorColor?: string;
100
102
  buttonColor?: string;
101
103
  buttonText?: string;
102
104
  buttonRadius?: 'none' | 'small' | 'medium' | 'large' | 'full';
@@ -94,9 +94,11 @@ interface FormStyling {
94
94
  formWidth?: 'narrow' | 'medium' | 'wide' | 'full';
95
95
  fieldLayout?: 'stacked' | 'inline';
96
96
  fieldBorderStyle?: 'full' | 'bottom';
97
+ fieldBorderColor?: string;
97
98
  fieldBorderRadius?: 'none' | 'small' | 'medium' | 'large' | 'full';
98
99
  fieldPaddingX?: number;
99
100
  fieldPaddingY?: number;
101
+ separatorColor?: string;
100
102
  buttonColor?: string;
101
103
  buttonText?: string;
102
104
  buttonRadius?: 'none' | 'small' | 'medium' | 'large' | 'full';
@@ -1283,11 +1283,12 @@ function FormFieldInput({
1283
1283
  const isInline = styling.labelPosition === "left" || styling.fieldLayout === "inline";
1284
1284
  const isBottomBorder = styling.fieldBorderStyle === "bottom";
1285
1285
  const fieldPadding = styling.fieldPaddingX != null || styling.fieldPaddingY != null ? `${styling.fieldPaddingY ?? 8}px ${styling.fieldPaddingX ?? 12}px` : "0.5rem 0.75rem";
1286
+ const defaultBorderColor = error ? "#ef4444" : styling.fieldBorderColor || (styling.theme === "dark" ? "#4b5563" : "#d1d5db");
1286
1287
  const inputStyle = {
1287
1288
  width: "100%",
1288
1289
  padding: fieldPadding,
1289
- border: isBottomBorder ? "none" : `1px solid ${error ? "#ef4444" : styling.theme === "dark" ? "#4b5563" : "#d1d5db"}`,
1290
- ...isBottomBorder ? { borderBottom: `1px solid ${error ? "#ef4444" : styling.theme === "dark" ? "#4b5563" : "#d1d5db"}` } : {},
1290
+ border: isBottomBorder ? "none" : `1px solid ${defaultBorderColor}`,
1291
+ ...isBottomBorder ? { borderBottom: `1px solid ${defaultBorderColor}` } : {},
1291
1292
  borderRadius: isBottomBorder ? 0 : fieldRadius,
1292
1293
  fontSize,
1293
1294
  fontFamily: "inherit",
@@ -1305,7 +1306,7 @@ function FormFieldInput({
1305
1306
  ] });
1306
1307
  }
1307
1308
  if (field.type === "divider") {
1308
- return /* @__PURE__ */ jsx2("hr", { style: { marginBottom: fieldSpacing, border: "none", borderTop: `1px solid ${styling.theme === "dark" ? "#4b5563" : "#d1d5db"}` } });
1309
+ return /* @__PURE__ */ jsx2("hr", { style: { marginBottom: fieldSpacing, border: "none", borderTop: `1px solid ${styling.separatorColor || (styling.theme === "dark" ? "#4b5563" : "#d1d5db")}` } });
1309
1310
  }
1310
1311
  if (field.type === "paragraph") {
1311
1312
  const pSize = field.paragraphFontSize ? `${field.paragraphFontSize}px` : getParagraphSize(styling.paragraphSize);
@@ -1515,18 +1516,91 @@ function FormFieldInput({
1515
1516
  opt.value
1516
1517
  )) });
1517
1518
  } else if (field.type === "file") {
1518
- fieldEl = /* @__PURE__ */ jsx2(
1519
- "input",
1519
+ const fileValue = value;
1520
+ const formatSize = (size) => size < 1024 ? `${size} B` : size < 1048576 ? `${(size / 1024).toFixed(1)} KB` : `${(size / 1048576).toFixed(1)} MB`;
1521
+ const borderColor = error ? styling.errorColor || "#ef4444" : styling.theme === "dark" ? "#4b5563" : "#d1d5db";
1522
+ const mutedColor = styling.theme === "dark" ? "#9ca3af" : "#6b7280";
1523
+ fieldEl = /* @__PURE__ */ jsxs(
1524
+ "label",
1520
1525
  {
1521
- type: "file",
1522
- id: field.name,
1523
- name: field.name,
1524
- onChange,
1525
- required: field.required,
1526
- accept: field.allowedMimeTypes?.join(","),
1527
- multiple: field.multiple,
1528
- style: inputStyle,
1529
- className: styling.fieldClassName
1526
+ htmlFor: field.name,
1527
+ style: {
1528
+ position: "relative",
1529
+ display: "flex",
1530
+ flexDirection: "column",
1531
+ alignItems: "center",
1532
+ justifyContent: "center",
1533
+ gap: "0.5rem",
1534
+ borderRadius: fieldRadius,
1535
+ border: `2px dashed ${borderColor}`,
1536
+ padding: "1.5rem",
1537
+ cursor: "pointer",
1538
+ transition: "border-color 0.15s, background-color 0.15s",
1539
+ backgroundColor: fileValue ? styling.theme === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.02)" : "transparent"
1540
+ },
1541
+ onDragOver: (e) => {
1542
+ e.preventDefault();
1543
+ e.currentTarget.style.borderColor = styling.primaryColor || "#3b82f6";
1544
+ e.currentTarget.style.backgroundColor = styling.theme === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.04)";
1545
+ },
1546
+ onDragLeave: (e) => {
1547
+ e.currentTarget.style.borderColor = borderColor;
1548
+ e.currentTarget.style.backgroundColor = fileValue ? styling.theme === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.02)" : "transparent";
1549
+ },
1550
+ onDrop: (e) => {
1551
+ e.preventDefault();
1552
+ e.currentTarget.style.borderColor = borderColor;
1553
+ e.currentTarget.style.backgroundColor = "transparent";
1554
+ const file = e.dataTransfer.files?.[0];
1555
+ if (file) onValueChange(field.name, file);
1556
+ },
1557
+ children: [
1558
+ /* @__PURE__ */ jsx2(
1559
+ "input",
1560
+ {
1561
+ id: field.name,
1562
+ name: field.name,
1563
+ type: "file",
1564
+ style: { position: "absolute", width: "1px", height: "1px", overflow: "hidden", clip: "rect(0,0,0,0)", whiteSpace: "nowrap", border: 0 },
1565
+ onChange,
1566
+ required: field.required,
1567
+ accept: field.allowedMimeTypes?.join(","),
1568
+ multiple: field.multiple
1569
+ }
1570
+ ),
1571
+ fileValue ? /* @__PURE__ */ jsxs(Fragment, { children: [
1572
+ /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: styling.primaryColor || "#3b82f6", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1573
+ /* @__PURE__ */ jsx2("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }),
1574
+ /* @__PURE__ */ jsx2("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })
1575
+ ] }),
1576
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: "0.875rem", fontWeight: 500, maxWidth: "100%", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: fileValue.name }),
1577
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: "0.75rem", color: mutedColor }, children: formatSize(fileValue.size) }),
1578
+ /* @__PURE__ */ jsx2(
1579
+ "button",
1580
+ {
1581
+ type: "button",
1582
+ style: { fontSize: "0.75rem", color: styling.errorColor || "#ef4444", background: "none", border: "none", cursor: "pointer", marginTop: "0.25rem", textDecoration: "underline" },
1583
+ onClick: (e) => {
1584
+ e.preventDefault();
1585
+ onValueChange(field.name, void 0);
1586
+ },
1587
+ children: "Remove"
1588
+ }
1589
+ )
1590
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1591
+ /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: mutedColor, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1592
+ /* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1593
+ /* @__PURE__ */ jsx2("polyline", { points: "17 8 12 3 7 8" }),
1594
+ /* @__PURE__ */ jsx2("line", { x1: "12", x2: "12", y1: "3", y2: "15" })
1595
+ ] }),
1596
+ /* @__PURE__ */ jsx2("span", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Drag & drop a file here, or click to browse" }),
1597
+ field.allowedMimeTypes && field.allowedMimeTypes.length > 0 && /* @__PURE__ */ jsx2("span", { style: { fontSize: "0.75rem", color: mutedColor }, children: field.allowedMimeTypes.join(", ") }),
1598
+ field.maxFileSize && /* @__PURE__ */ jsxs("span", { style: { fontSize: "0.75rem", color: mutedColor }, children: [
1599
+ "Max size: ",
1600
+ formatSize(field.maxFileSize)
1601
+ ] })
1602
+ ] })
1603
+ ]
1530
1604
  }
1531
1605
  );
1532
1606
  } else if (field.type === "name") {