formanitor 0.0.5 → 0.0.6

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.
package/dist/index.cjs CHANGED
@@ -353,10 +353,13 @@ var FormStore = class {
353
353
  if (field.type === "image_upload" || field.type === "signature") {
354
354
  const raw = values[field.id];
355
355
  if (raw !== void 0 && raw !== null && raw !== "") {
356
- result[field.id] = {
357
- _type: "s3_key",
358
- value: raw
359
- };
356
+ const key = typeof raw === "string" ? raw : raw.s3_key || raw.value || null;
357
+ if (key && typeof key === "string") {
358
+ result[field.id] = {
359
+ _type: "s3_key",
360
+ value: key
361
+ };
362
+ }
360
363
  }
361
364
  }
362
365
  });
@@ -1539,8 +1542,15 @@ var smoothPoint = (prev, curr, smoothing = 0.75) => {
1539
1542
  y: prev.y * smoothing + curr.y * (1 - smoothing)
1540
1543
  };
1541
1544
  };
1545
+ function extractDisplayUrl(value) {
1546
+ if (!value || typeof value !== "object") return null;
1547
+ if (typeof value.presigned_url === "string" && value.presigned_url) {
1548
+ return value.presigned_url;
1549
+ }
1550
+ return null;
1551
+ }
1542
1552
  var SignatureUploadWidget = ({ fieldId }) => {
1543
- const { fieldDef, setValue, setTouched, error, disabled, touched } = useField(fieldId);
1553
+ const { fieldDef, setValue, setTouched, error, disabled, touched, value } = useField(fieldId);
1544
1554
  const store = useFormStore();
1545
1555
  const { state } = useForm();
1546
1556
  const canvasRef = React11.useRef(null);
@@ -1549,13 +1559,14 @@ var SignatureUploadWidget = ({ fieldId }) => {
1549
1559
  const lastTimeRef = React11.useRef(null);
1550
1560
  const lastWidthRef = React11.useRef(2);
1551
1561
  const [isDrawing, setIsDrawing] = React11.useState(false);
1552
- const [hasSignature, setHasSignature] = React11.useState(false);
1562
+ const [hasDrawing, setHasDrawing] = React11.useState(false);
1553
1563
  const [isUploading, setIsUploading] = React11.useState(false);
1564
+ const [isConfirmed, setIsConfirmed] = React11.useState(false);
1554
1565
  const showError = !!error && (touched || state.submitAttempted);
1555
- if (!fieldDef) return null;
1556
- const uploadHandler = store.getUploadHandler();
1557
- if (!uploadHandler) return null;
1566
+ const displayUrl = React11.useMemo(() => extractDisplayUrl(value), [value]);
1567
+ const showPreview = displayUrl !== null;
1558
1568
  React11.useEffect(() => {
1569
+ if (showPreview) return;
1559
1570
  const canvas = canvasRef.current;
1560
1571
  if (!canvas) return;
1561
1572
  const ctx = canvas.getContext("2d");
@@ -1573,7 +1584,9 @@ var SignatureUploadWidget = ({ fieldId }) => {
1573
1584
  ctx.strokeStyle = "#000";
1574
1585
  ctx.fillStyle = "#fff";
1575
1586
  ctx.fillRect(0, 0, width, height);
1576
- }, []);
1587
+ }, [showPreview]);
1588
+ const uploadHandler = store.getUploadHandler();
1589
+ if (!fieldDef || !uploadHandler) return null;
1577
1590
  const getPoint = (event) => {
1578
1591
  const canvas = canvasRef.current;
1579
1592
  const rect = canvas.getBoundingClientRect();
@@ -1586,6 +1599,7 @@ var SignatureUploadWidget = ({ fieldId }) => {
1586
1599
  const startDrawing = (event) => {
1587
1600
  if (disabled) return;
1588
1601
  setIsDrawing(true);
1602
+ setIsConfirmed(false);
1589
1603
  setTouched();
1590
1604
  const ctx = canvasRef.current?.getContext("2d");
1591
1605
  if (!ctx) return;
@@ -1627,23 +1641,31 @@ var SignatureUploadWidget = ({ fieldId }) => {
1627
1641
  lastPointRef.current = smoothed;
1628
1642
  lastTimeRef.current = now;
1629
1643
  lastWidthRef.current = width;
1630
- setHasSignature(true);
1644
+ setHasDrawing(true);
1631
1645
  };
1632
1646
  const stopDrawing = () => {
1633
1647
  setIsDrawing(false);
1634
1648
  lastPointRef.current = null;
1635
1649
  lastTimeRef.current = null;
1636
1650
  };
1637
- const clearCanvas = () => {
1651
+ const clearSignature = () => {
1652
+ if (showPreview) {
1653
+ setValue(null);
1654
+ setTouched();
1655
+ return;
1656
+ }
1638
1657
  const canvas = canvasRef.current;
1639
1658
  const ctx = canvas?.getContext("2d");
1640
- if (!canvas || !ctx) return;
1641
- ctx.fillStyle = "#fff";
1642
- ctx.fillRect(0, 0, 400, 200);
1659
+ if (canvas && ctx) {
1660
+ ctx.fillStyle = "#fff";
1661
+ ctx.fillRect(0, 0, 400, 200);
1662
+ }
1643
1663
  pathRef.current = "";
1644
1664
  lastPointRef.current = null;
1645
- setHasSignature(false);
1665
+ setHasDrawing(false);
1666
+ setIsConfirmed(false);
1646
1667
  setValue(null);
1668
+ setTouched();
1647
1669
  };
1648
1670
  const generateSVG = () => `
1649
1671
  <svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
@@ -1656,7 +1678,7 @@ var SignatureUploadWidget = ({ fieldId }) => {
1656
1678
  fill="none"/>
1657
1679
  </svg>`.trim();
1658
1680
  const confirmSignature = async () => {
1659
- if (!hasSignature) return;
1681
+ if (!hasDrawing) return;
1660
1682
  setIsUploading(true);
1661
1683
  setTouched();
1662
1684
  try {
@@ -1665,55 +1687,95 @@ var SignatureUploadWidget = ({ fieldId }) => {
1665
1687
  const filename = `signature_${Date.now()}.svg`;
1666
1688
  const key = await uploadHandler(blob, filename);
1667
1689
  setValue(key);
1690
+ setIsConfirmed(true);
1691
+ setHasDrawing(false);
1692
+ } catch (err) {
1693
+ console.error("[SignatureUpload] Upload failed:", err);
1668
1694
  } finally {
1669
1695
  setIsUploading(false);
1670
1696
  }
1671
1697
  };
1698
+ const canClear = showPreview ? !disabled : hasDrawing || isConfirmed;
1672
1699
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
1673
1700
  /* @__PURE__ */ jsxRuntime.jsxs(Label, { children: [
1674
1701
  fieldDef.label,
1675
1702
  fieldDef.required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: "*" })
1676
1703
  ] }),
1677
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1678
- /* @__PURE__ */ jsxRuntime.jsx(
1679
- "canvas",
1680
- {
1681
- ref: canvasRef,
1682
- className: "border border-gray-200 rounded cursor-crosshair touch-none",
1683
- onMouseDown: startDrawing,
1684
- onMouseMove: draw,
1685
- onMouseUp: stopDrawing,
1686
- onMouseLeave: stopDrawing,
1687
- onTouchStart: startDrawing,
1688
- onTouchMove: draw,
1689
- onTouchEnd: stopDrawing
1690
- }
1691
- ),
1692
- /* @__PURE__ */ jsxRuntime.jsx(
1693
- Button,
1694
- {
1695
- type: "button",
1696
- size: "icon",
1697
- variant: "ghost",
1698
- className: "absolute top-2 left-2 bg-white/80",
1699
- onClick: clearCanvas,
1700
- disabled: !hasSignature,
1701
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
1702
- }
1703
- )
1704
- ] }),
1705
- /* @__PURE__ */ jsxRuntime.jsxs(
1706
- Button,
1707
- {
1708
- type: "button",
1709
- onClick: confirmSignature,
1710
- disabled: !hasSignature || isUploading,
1711
- className: "text-xs",
1712
- children: [
1713
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 mr-1" }),
1714
- isUploading ? "Saving\u2026" : "Confirm"
1715
- ]
1716
- }
1704
+ showPreview ? (
1705
+ /* ── Preview mode: existing signature from backend ── */
1706
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1707
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-gray-200 rounded bg-white flex items-center justify-start p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
1708
+ "img",
1709
+ {
1710
+ src: displayUrl,
1711
+ alt: "Signature",
1712
+ className: "object-contain max-w-full",
1713
+ style: { width: 400, height: 200 }
1714
+ }
1715
+ ) }),
1716
+ /* @__PURE__ */ jsxRuntime.jsx(
1717
+ Button,
1718
+ {
1719
+ type: "button",
1720
+ size: "icon",
1721
+ variant: "ghost",
1722
+ className: "absolute top-2 left-2 bg-white/80 hover:bg-red-50",
1723
+ onClick: clearSignature,
1724
+ disabled: !canClear,
1725
+ title: "Delete signature and draw a new one",
1726
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
1727
+ }
1728
+ )
1729
+ ] })
1730
+ ) : (
1731
+ /* ── Canvas mode: drawing / confirmed ── */
1732
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1733
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1734
+ /* @__PURE__ */ jsxRuntime.jsx(
1735
+ "canvas",
1736
+ {
1737
+ ref: canvasRef,
1738
+ className: `border rounded touch-none ${isConfirmed ? "border-green-300 cursor-default" : "border-gray-200 cursor-crosshair"}`,
1739
+ onMouseDown: startDrawing,
1740
+ onMouseMove: draw,
1741
+ onMouseUp: stopDrawing,
1742
+ onMouseLeave: stopDrawing,
1743
+ onTouchStart: startDrawing,
1744
+ onTouchMove: draw,
1745
+ onTouchEnd: stopDrawing
1746
+ }
1747
+ ),
1748
+ /* @__PURE__ */ jsxRuntime.jsx(
1749
+ Button,
1750
+ {
1751
+ type: "button",
1752
+ size: "icon",
1753
+ variant: "ghost",
1754
+ className: "absolute top-2 left-2 bg-white/80",
1755
+ onClick: clearSignature,
1756
+ disabled: !canClear,
1757
+ title: isConfirmed ? "Clear saved signature" : "Clear canvas",
1758
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" })
1759
+ }
1760
+ )
1761
+ ] }),
1762
+ isConfirmed ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-green-600", children: [
1763
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }),
1764
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Signature saved" })
1765
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
1766
+ Button,
1767
+ {
1768
+ type: "button",
1769
+ onClick: confirmSignature,
1770
+ disabled: !hasDrawing || isUploading,
1771
+ className: "text-xs",
1772
+ children: [
1773
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 mr-1" }),
1774
+ isUploading ? "Saving\u2026" : "Confirm"
1775
+ ]
1776
+ }
1777
+ )
1778
+ ] })
1717
1779
  ),
1718
1780
  showError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-red-500", children: error })
1719
1781
  ] });
@@ -2271,7 +2333,7 @@ var ReadOnlyText = ({ fieldDef, value }) => {
2271
2333
  className: "prose prose-sm max-w-none text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50",
2272
2334
  dangerouslySetInnerHTML: { __html: displayValue }
2273
2335
  }
2274
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] flex items-center", children: displayValue || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 italic", children: "No value" }) })
2336
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-900 border border-gray-200 rounded-md p-3 bg-gray-50 min-h-[2.5rem] whitespace-pre-wrap", children: displayValue || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 italic", children: "No value" }) })
2275
2337
  ] });
2276
2338
  };
2277
2339
  var ReadOnlySelect = ({ fieldDef, value }) => {