diff --git a/example/src/index.js b/example/src/index.js index a2e9d40..837a2ad 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import ReactDOM from 'react-dom' -import SignaturePad from '../../src/index.js' +import SignaturePad from '../../src/index.tsx' import styles from './styles.module.css' diff --git a/jest.config.js b/jest.config.js index 63a60ef..3923a2c 100644 --- a/jest.config.js +++ b/jest.config.js @@ -9,7 +9,8 @@ module.exports = { ], transform: { // support babel-jest. TSDX defaults to just ts-jest. see https://github.com/jaredpalmer/tsdx/pull/486 - '\\.js$': 'babel-jest' + '\\.js$': 'babel-jest', + '\\.tsx$': 'ts-jest' }, // support JS + JSX. TSDX defaults to just TS + TSX. see https://github.com/jaredpalmer/tsdx/pull/486 testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], diff --git a/package-lock.json b/package-lock.json index 52ecd7a..4f5031c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6401,12 +6401,29 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", + "dev": true + }, "@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", "dev": true }, + "@types/react": { + "version": "17.0.44", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.44.tgz", + "integrity": "sha512-Ye0nlw09GeMp2Suh8qoOv0odfgCoowfM/9MG6WeRD60Gq9wS90bdkdRtYbRkNhXOpG4H+YXGvj4wOWhAC0LJ1g==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, "@types/resolve": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", @@ -6426,6 +6443,12 @@ "@types/node": "*" } }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, "@types/shelljs": { "version": "0.8.6", "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.6.tgz", @@ -6436,6 +6459,11 @@ "@types/node": "*" } }, + "@types/signature_pad": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@types/signature_pad/-/signature_pad-2.3.0.tgz", + "integrity": "sha512-3g03oFi6Xy7oA1foIP80X9Np+psq1CDGsGIRIEgvEuFzJZsS5oRGGqgl9K5ONlfLlnYU+Ei8vMszWKlIlMA/cA==" + }, "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", @@ -10029,6 +10057,12 @@ "cssom": "0.3.x" } }, + "csstype": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", + "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", + "dev": true + }, "damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", diff --git a/package.json b/package.json index 03d8ef0..5879292 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "react-dom": "0.14 - 17" }, "dependencies": { + "@types/signature_pad": "^2.3.0", "signature_pad": "^2.3.2", "trim-canvas": "^0.1.0" }, @@ -62,6 +63,8 @@ "@agilgur5/changelog-maker": "^3.0.0", "@babel/core": "^7.8.4", "@babel/preset-react": "^7.8.3", + "@types/prop-types": "^15.7.3", + "@types/react": "^17.0.44", "@wojtekmaj/enzyme-adapter-react-17": "^0.6.6", "babel-eslint": "^10.0.2", "canvas": "^2.9.0", diff --git a/src/index.js b/src/index.tsx similarity index 70% rename from src/index.js rename to src/index.tsx index ce553ed..444d4fd 100644 --- a/src/index.js +++ b/src/index.tsx @@ -3,7 +3,12 @@ import React, { Component } from 'react' import SignaturePad from 'signature_pad' import trimCanvas from 'trim-canvas' -export class SignatureCanvas extends Component { +export interface SignatureCanvasProps extends SignaturePad.SignaturePadOptions { + canvasProps?: React.CanvasHTMLAttributes, + clearOnResize?: boolean +} + +export class SignatureCanvas extends Component { static propTypes = { // signature_pad's props velocityFilterWeight: PropTypes.number, @@ -24,7 +29,15 @@ export class SignatureCanvas extends Component { clearOnResize: true } - _sigPad = null + // this is some hack-ish init and casting to avoid `| null` everywhere :/ + _sigPad: SignaturePad = {} as SignaturePad + _canvas: HTMLCanvasElement = {} as HTMLCanvasElement + + private readonly setRef = (ref: HTMLCanvasElement | null) => { + if (ref) { + this._canvas = ref + } + } _excludeOurProps = () => { const { canvasProps, clearOnResize, ...sigPadProps } = this.props @@ -47,23 +60,23 @@ export class SignatureCanvas extends Component { } // return the canvas ref for operations like toDataURL - getCanvas = () => { + getCanvas = (): HTMLCanvasElement => { return this._canvas } // return a trimmed copy of the canvas - getTrimmedCanvas = () => { + getTrimmedCanvas = (): HTMLCanvasElement => { // copy the canvas const copy = document.createElement('canvas') copy.width = this._canvas.width copy.height = this._canvas.height - copy.getContext('2d').drawImage(this._canvas, 0, 0) + copy.getContext('2d')!.drawImage(this._canvas, 0, 0) // then trim it return trimCanvas(copy) } // return the internal SignaturePad reference - getSignaturePad = () => { + getSignaturePad = (): SignaturePad => { return this._sigPad } @@ -94,48 +107,48 @@ export class SignatureCanvas extends Component { if (!height) { canvas.height = canvas.offsetHeight * ratio } - canvas.getContext('2d').scale(ratio, ratio) + canvas.getContext('2d')!.scale(ratio, ratio) this.clear() } render () { const { canvasProps } = this.props - return { this._canvas = ref }} {...canvasProps} /> + return } // all wrapper functions below render // - on = () => { + on: SignaturePad['on'] = () => { window.addEventListener('resize', this._checkClearOnResize) return this._sigPad.on() } - off = () => { + off: SignaturePad['off'] = () => { window.removeEventListener('resize', this._checkClearOnResize) return this._sigPad.off() } - clear = () => { + clear: SignaturePad['clear'] = () => { return this._sigPad.clear() } - isEmpty = () => { + isEmpty: SignaturePad['isEmpty'] = () => { return this._sigPad.isEmpty() } - fromDataURL = (dataURL, options) => { + fromDataURL: SignaturePad['fromDataURL'] = (dataURL, options) => { return this._sigPad.fromDataURL(dataURL, options) } - toDataURL = (type, encoderOptions) => { + toDataURL: SignaturePad['toDataURL'] = (type, encoderOptions) => { return this._sigPad.toDataURL(type, encoderOptions) } - fromData = (pointGroups) => { + fromData: SignaturePad['fromData'] = (pointGroups) => { return this._sigPad.fromData(pointGroups) } - toData = () => { + toData: SignaturePad['toData'] = () => { return this._sigPad.toData() } } diff --git a/test/index.spec.js b/test/index.spec.js index f21f65c..557204b 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -2,7 +2,7 @@ import { jest, describe, it, test, expect } from 'jest-without-globals' import { mount } from 'enzyme' import React from 'react' -import SignatureCanvas from '../src/index.js' +import SignatureCanvas from '../src/index.tsx' import { propsF, dotF } from './fixtures.js' test('mounts canvas and instance properly', () => { diff --git a/tsconfig.json b/tsconfig.json index a1ed096..7bf4001 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "include": ["src", "types"], + "include": ["src", "typings"], "compilerOptions": { "module": "esnext", "lib": ["dom", "esnext"], @@ -18,6 +18,6 @@ "*": ["src/*", "node_modules/*"] }, "esModuleInterop": true, - "allowJs": true + "jsx": "react" } } diff --git a/typings/trim-canvas.d.ts b/typings/trim-canvas.d.ts new file mode 100644 index 0000000..b909bca --- /dev/null +++ b/typings/trim-canvas.d.ts @@ -0,0 +1,3 @@ +declare module 'trim-canvas' { + export default function trimCanvas (canvas: HTMLCanvasElement): HTMLCanvasElement +}