fix: prevent accidental signatures (#1515)

![CleanShot 2024-12-06 at 03 30
39](https://github.com/user-attachments/assets/d47dc820-f19d-43b7-a60d-914fc9ab24b8)

![CleanShot 2024-12-06 at 03 32
34](https://github.com/user-attachments/assets/0db98735-8c91-469b-873c-adb19d0fff7b)
This commit is contained in:
Ephraim Duncan
2024-12-08 03:17:58 +00:00
committed by GitHub
parent a88ae1cc1e
commit dd162205fa
23 changed files with 443 additions and 292 deletions

View File

@ -97,6 +97,8 @@ export type SignaturePadProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'onChang
disabled?: boolean;
allowTypedSignature?: boolean;
defaultValue?: string;
onValidityChange?: (isValid: boolean) => void;
minCoverageThreshold?: number;
};
export const SignaturePad = ({
@ -106,6 +108,8 @@ export const SignaturePad = ({
onChange,
disabled = false,
allowTypedSignature,
onValidityChange,
minCoverageThreshold = 0.01,
...props
}: SignaturePadProps) => {
const $el = useRef<HTMLCanvasElement>(null);
@ -134,6 +138,29 @@ export const SignaturePad = ({
} satisfies StrokeOptions;
}, []);
const checkSignatureValidity = () => {
if ($el.current) {
const ctx = $el.current.getContext('2d');
if (ctx) {
const imageData = ctx.getImageData(0, 0, $el.current.width, $el.current.height);
const data = imageData.data;
let filledPixels = 0;
const totalPixels = data.length / 4;
for (let i = 0; i < data.length; i += 4) {
if (data[i + 3] > 0) filledPixels++;
}
const filledPercentage = filledPixels / totalPixels;
const isValid = filledPercentage > minCoverageThreshold;
onValidityChange?.(isValid);
return isValid;
}
}
};
const onMouseDown = (event: MouseEvent | PointerEvent | TouchEvent) => {
if (event.cancelable) {
event.preventDefault();
@ -218,7 +245,6 @@ export const SignaturePad = ({
if (ctx) {
ctx.restore();
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
ctx.fillStyle = selectedColor;
@ -230,7 +256,11 @@ export const SignaturePad = ({
ctx.fill(pathData);
});
onChange?.($el.current.toDataURL());
const isValidSignature = checkSignatureValidity();
if (isValidSignature) {
onChange?.($el.current.toDataURL());
}
ctx.save();
}
}