npm package: @siamf/react-signature-pad
Description: A lightweight, dependency-free React signature pad with an essential API and extensive customization.
Author: Siam Ahnaf
Latest version: 2.0.1

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-white.png">
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-black.png">
  <img alt="Siam Ahnaf" src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/logo/logo-black.png" height="auto" width="240">
</picture>
<br/>

# @siamf/react-signature-pad
A lightweight, dependency-free React signature pad with an essential API and extensive customization.

<a href="https://www.buymeacoffee.com/siamahnaf" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>

# Demo
Live [Demo](https://signature.siamahnaf.com/)

# Installation

```bash
$ npm i @siamf/react-signature-pad
```

# Usage

```javascript
import { SignaturePad } from "@siamf/react-signature-pad";

//SignaturePad Component
<SignaturePad />
```

### How to use API?

```javascript
import { SignaturePad, SignaturePadRef } from "@siamf/react-signature-pad";
import { useRef, useState } from "react";

const MyComponent = () => {
    //Get data url or file from ref
    const ref = useRef<SignaturePadRef>(null);
    const getDataOrFile = async () => {
        if (ref.current) {
            const { dataUrl, file } = await ref.current.export();
            console.log('Signature as PNG:', dataUrl);
            //save(file)
        }
    };

    //Save State on Every Changes
    const [file, setFile] = useState<File>();
    //Then use this file from state anywhere

    return (
        <div>
          <SignaturePad
            canvasProps={{ width: 600, height: 300 }}
            ref={ref}
            onEnd={(e)=> setFile(e.file)} //or e.dataUrl
          />
          <button onClick={getDataUrl}>
            Download Signature
          </button>
        </div>
    )
}

export default MyComponent;
````


# Props

<table width="100%">
  <tr>
    <th> Name </th>
    <th> Types </th>
    <th> Description </th>
  </tr>
  <tr>
    <td> className </td>
    <td> string </td>
    <td> Optional - Main container classname </td>
  </tr>
   <tr>
    <td> style </td>
    <td> CSSProperties </td>
    <td> Optional - Main container style API </td>
  </tr>
   <tr>
    <td> canvasClassName </td>
    <td> string </td>
    <td> Optional - Canvas class name </td>
  </tr>
   <tr>
    <td> canvasStyle </td>
    <td> CSSProperties </td>
    <td> Optional - Draw the next point at most once per every x milliseconds. Set it to 0 to turn off throttling. Defaults to 16. </td>
  </tr>
   <tr>
    <td> canvasProps </td>
    <td> HTMLCanvasElement </td>
    <td> Optional - Canvas html element props </td>
  </tr>
  <tr>
    <td> previewClassName </td>
    <td> string </td>
    <td> Optional - Preview signature class </td>
  </tr>
  <tr>
    <td> previewStyle </td>
    <td> CSSProperties </td>
    <td> Optional - Preview signature styles </td>
  </tr>
  <tr>
    <td> imgProps </td>
    <td> HTMLImageElement </td>
    <td> Optional - Preview Image Props</td>
  </tr>
  <tr>
    <td> width </td>
    <td> number </td>
    <td> Optional - Canvas width</td>
  </tr>
  <tr>
    <td> height </td>
    <td> number </td>
    <td> Optional - Canvas Height</td>
  </tr>
  <tr>
    <td> fitToContainer </td>
    <td> boolean </td>
    <td> Optional - Fit canvas to parent width and height </td>
  </tr>
  <tr>
    <td> disabled </td>
    <td> boolean </td>
    <td> Optional - Disable canvas drawing </td>
  </tr>
  <tr>
    <td> readOnly </td>
    <td> boolean </td>
    <td> Optional - Readonly Canvas </td>
  </tr>
  <tr>
    <td> penColor </td>
    <td> string </td>
    <td> Optional - Pen color for drawing lines </td>
  </tr>
  <tr>
    <td> backgroundColor </td>
    <td> string </td>
    <td> Optional - Canvas Background color </td>
  </tr>
  <tr>
    <td> strokeWidth </td>
    <td> number </td>
    <td> Optional - Stroke width line, default  is 3 </td>
  </tr>
  <tr>
    <td> value </td>
    <td> string | null </td>
    <td> Optional - A value props to show as image as default value </td>
  </tr>
  <tr>
    <td> exportType </td>
    <td> "image/png" | "image/jpeg" | "image/webp" </td>
    <td> Optional - Export file type </td>
  </tr>
  <tr>
    <td> exportQuality </td>
    <td> number </td>
    <td> Optional - Export file(Image) quality </td>
  </tr>
  <tr>
    <td> fileName </td>
    <td> string </td>
    <td> Optional - Exported file name </td>
  </tr>
  <tr>
    <td> exportBackground </td>
    <td> "transparent" | "canvas" </td>
    <td> Optional - Export file background type </td>
  </tr>
  <tr>
    <td> exportBackgroundColor </td>
    <td> string </td>
    <td> Optional - Export file background color when type is "canvas" </td>
  </tr>
  <tr>
    <td> onBegin </td>
    <td> ()=> void </td>
    <td> Optional - Callback when drawing start </td>
  </tr>
  <tr>
    <td> onEnd </td>
    <td> (payload: EndPayload | null) => void </td>
    <td> Optional - Callback when drawing end. EndPayload can provide url or dataUrl</td>
  </tr>
  <tr>
    <td> onChange </td>
    <td> (hasContent: boolean) => void; </td>
    <td> Optional - Callback when get changed with hasContent </td>
  </tr>
  <tr>
    <td> pencilCursor </td>
    <td> boolean </td>
    <td> Optional - Show custom pencil cursor type </td>
  </tr>
  <tr>
    <td> cursorHotspot </td>
    <td> { x: number; y: number } </td>
    <td> Optional - For cursor position on writing hotspot point </td>
  </tr>
  <tr>
    <td> cursorSvg </td>
    <td> string </td>
    <td> Optional - Cursor svg for showing custom cursor </td>
  </tr>
  <tr>
    <td> toolBar </td>
    <td> boolean </td>
    <td> Optional - Show toolbar </td>
  </tr>
  <tr>
    <td> colors </td>
    <td> string[] </td>
    <td> Optional - Colors array for toolbars </td>
  </tr>
  <tr>
    <td> toolbarClassName </td>
    <td> string </td>
    <td> Optional - Toolbar class </td>
  </tr>
  <tr>
    <td> toolbarStyle </td>
    <td> CSSProperties </td>
    <td> Optional - Toolbar styles </td>
  </tr>
  <tr>
    <td> showUndo </td>
    <td> boolean </td>
    <td> Optional - Show/Hide undo button </td>
  </tr>
  <tr>
    <td> showRedo </td>
    <td> boolean </td>
    <td> Optional - Show/Hide redo button </td>
  </tr>
  <tr>
    <td> showClear </td>
    <td> boolean </td>
    <td> Optional - Show/Hide clear button </td>
  </tr>
  <tr>
    <td> editLabel </td>
    <td> string </td>
    <td> Optional - Edit button label </td>
  </tr>
  <tr>
    <td> cancelLabel </td>
    <td> string </td>
    <td> Optional - Cancel button label </td>
  </tr>
  <tr>
    <td> renderToolbar </td>
    <td> (api: ToolbarTypes)=> ReactNode </td>
    <td> Optional - Render your own toolbar </td>
  </tr>
  <tr>
    <td> renderPreview </td>
    <td> (api: PreviewTypes)=> ReactNode </td>
    <td> Optional - Render your own preview container </td>
  </tr>
</table>

### API for ToolbarTypes
You find all following options on `renderToolbar` props

<table width="100%">
  <tr>
    <th> Name </th>
    <th> Types </th>
    <th> Description </th>
  </tr>
  <tr>
    <td> color </td>
    <td> string </td>
    <td> Current color </td>
  </tr>
  <tr>
    <td> canUndo </td>
    <td> boolean </td>
    <td> Can undo </td>
  </tr>
  <tr>
    <td> canRedo </td>
    <td> boolean </td>
    <td> Can redo </td>
  </tr>
  <tr>
    <td> clear() </td>
    <td> ()=> void </td>
    <td> Callback for clearing drawings </td>
  </tr>
  <tr>
    <td> undo() </td>
    <td> ()=> void </td>
    <td> Callback for undo drawings </td>
  </tr>
  <tr>
    <td> redo() </td>
    <td> ()=> void </td>
    <td> Callback for redo drawings </td>
  </tr>
  <tr>
    <td> cancel() </td>
    <td> ()=> void </td>
    <td> Callback for cancel drawing canvas and render value image again </td>
  </tr>
  <tr>
    <td> hasContent </td>
    <td> boolean </td>
    <td> Has hasContent or not </td>
  </tr>
</table>

### API for PreviewTypes
You find all following options on `renderPreview` props

<table width="100%">
  <tr>
    <th> Name </th>
    <th> Types </th>
    <th> Description </th>
  </tr>
  <tr>
    <td> src </td>
    <td> string </td>
    <td> Image src </td>
  </tr>
  <tr>
    <td> startEdit() </td>
    <td> ()=> void </td>
    <td> Callback for starting drawing/loading canvas </td>
  </tr>
  <tr>
    <td> disabled </td>
    <td> boolean </td>
    <td> Disable/Enable button </td>
  </tr>
</table>


## API for `SignaturePadRef`
You will get following options on `SignaturePadRef` Ref

<table width="100%">
  <tr>
    <td> clear() </td>
    <td> ()=> void </td>
    <td> Callback for clearing drawings </td>
  </tr>
  <tr>
    <td> undo() </td>
    <td> ()=> void </td>
    <td> Callback for undo drawings </td>
  </tr>
  <tr>
    <td> redo() </td>
    <td> ()=> void </td>
    <td> Callback for redo drawings </td>
  </tr>
  <tr>
    <td> cancel() </td>
    <td> ()=> void </td>
    <td> Callback for cancel drawing canvas and render value image again </td>
  </tr>
  <tr>
    <td> export() </td>
    <td> ()=> Promise<EndPayLoad> </td>
    <td> Export file/dataURL from export function. See example code </td>
  </tr>
  <tr>
    <td> hasContent() </td>
    <td> ()=> boolean </td>
    <td> Is hasContent or not </td>
  </tr>
  <tr>
    <td> startEdit() </td>
    <td> ()=> void </td>
    <td> Callback for start edit button </td>
  </tr>
  <tr>
    <td> cancelEdit() </td>
    <td> ()=> void </td>
    <td> Callback for cancel canvas </td>
  </tr>
</table>

## Connect with me
<div style="display: flex; align-items: center; gap: 3px;">
<a href="https://wa.me/8801611994403"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/whatsapp.png" width="40" height="40"></a>
<a href="https://siamahnaf.com/" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/web.png" width="40" height="40"></a>
<a href="https://www.linkedin.com/in/siamahnaf/" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/linkedin.png" width="40" height="40"></a>
<a href="https://x.com/siamahnaf198" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/x.png" width="40" height="40"></a>
<a href="https://www.facebook.com/siamahnaf198/" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/facebook.png" width="40" height="40"></a>
<a href="https://t.me/siamahnaf198" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/telegram.png" width="40" height="40"></a>
<a href="https://www.npmjs.com/~siamahnaf" style="margin-right: 8px"><img src="https://raw.githubusercontent.com/siamahnaf/assets-kit/main/icons/npm.png" width="40" height="40"></a>
</div>