Skip to content

Instantly share code, notes, and snippets.

@yanickrochon
Last active September 8, 2022 19:02
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yanickrochon/0d5c41a03ed1a8bef4c47140400bb802 to your computer and use it in GitHub Desktop.
Save yanickrochon/0d5c41a03ed1a8bef4c47140400bb802 to your computer and use it in GitHub Desktop.
Material UI integration of react-signature-canvas (https://github.com/agilgur5/react-signature-canvas)
import React, { useEffect, useRef, useState } from 'react';
import PropType from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import classNames from 'classnames';
import Fade from '@material-ui/core/Fade';
import FormControl from '@material-ui/core/FormControl';
import IconButton from '@material-ui/core/IconButton';
import InputLabel from '@material-ui/core/InputLabel';
import EraserIcon from 'mdi-react/EraserIcon';
import SignatureCanvas from 'react-signature-canvas'
const useStyles = makeStyles(theme => ({
label: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(0, 1),
},
signatureCanvasControl: {
position: 'relative',
},
signatureCanvas: {
borderRadius: '4px',
borderWidth: 2,
borderStyle: 'solid',
borderColor: theme.palette.grey[300],
'&.hover': {
borderColor: theme.palette.grey[500]
},
'&.focus': {
borderColor: theme.palette.secondary.main,
}
},
signatureCanvasAction: {
position: 'absolute',
right: theme.spacing(1),
top: theme.spacing(1)
},
}));
const UPDATE_DELAY = 300;
const SignaturePad = ({
id,
value,
disabled,
onChange
}) => {
const classes = useStyles();
const signRef = useRef();
const [ hover, setHover ] = useState(false);
const [ focused, setFocused ] = useState(false);
const [ hasData, setHasData ] = useState(false);
useEffect(() => {
const data = JSON.parse(value);
if (data) {
signRef.current.fromData( data );
setHasData(true);
} else {
signRef.current.clear();
setHasData(false);
}
}, [ value ]);
useEffect(() => {
if (disabled) {
signRef.current.off();
} else {
signRef.current.on();
}
}, [ disabled ]);
useEffect(() => {
const timer = setTimeout(() => {
if (!focused && !signRef.current.isEmpty()) {
onChange && onChange( JSON.stringify(signRef.current.toData()) );
}
}, UPDATE_DELAY);
return () => clearTimeout(timer);
}, [ focused ]);
const handleMouseEnter = () => setHover(true);
const handleMouseLeave = () => setHover(false);
const  handleLockUpdate = () => {
setFocused(true);
setHasData(true);
};
const handleUpdateData = () => {
setFocused(false);
};
const handleClear = () => {
if (onChange) {
onChange(null);
} else {
signRef.current.clear();
setHasData(false);
}
};
return (
<FormControl variant="outlined" color="secondary"
focused={ focused }
className={ classes.signatureCanvasControl }
onMouseEnter={ handleMouseEnter }
onMouseLeave={ handleMouseLeave }
>
<InputLabel variant="outlined" htmlFor="canvas-signature" className={ classes.label } shrink={ hasData }>Signature</InputLabel>
<SignatureCanvas id={ id } ref={signRef} penColor="#0d47a1"
canvasProps={{
width: 500,
height: 200,
className: classNames(classes.signatureCanvas, focused ? 'focus' : hover ? 'hover' : '' ),
}}
onBegin={ handleLockUpdate }
onEnd={ handleUpdateData }
/>
<Fade in={ hasData }>
<IconButton size="small" title={ "Effacer" } className={ classes.signatureCanvasAction } onClick={handleClear}>
<EraserIcon />
</IconButton>
</Fade>
</FormControl>
);
}
SignaturePad.propTypes = {
disabled: PropType.bool,
id: PropType.string,
onChange: PropType.func,
value: PropType.string,
};
SignaturePad.defaultProps = {
value: null
};
export default SignaturePad;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment