Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
[terra-signature] Example update (#4071)
Browse files Browse the repository at this point in the history
  • Loading branch information
MadanKumarGovindaswamy authored Mar 26, 2024
1 parent e7481a3 commit 7c269b0
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 52 deletions.
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/terra-core-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Added an example for `terra-hyperlink` to demonstrate text ellipses when its content should overflow.
* Changed
* Fixed typos and imports in `terra-list` docs.
* Updated `terra-signature` example to include text and image signature.

## 1.68.0 - (March 20, 2024)

Expand Down
1 change: 1 addition & 0 deletions packages/terra-core-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
"terra-status-view": "^4.75.0",
"terra-switch": "^1.14.0",
"terra-tag": "^2.68.0",
"terra-tabs": "^7.21.0",
"terra-text": "^4.56.0",
"terra-theme-context": "^1.0.0",
"terra-toggle": "^3.62.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import classNames from 'classnames/bind';
import Signature from 'terra-signature';
import PropTypes from 'prop-types';
import styles from './SignatureExample.module.scss';

const cx = classNames.bind(styles);

const propTypes = { onClearSignature: PropTypes.func };

const ImageSignature = (props) => {
const handleFileSelect = () => {
const canvas = document.getElementById('upload');
if (canvas) {
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 1000, 100);
const imgFile = document.getElementById('file-select').files[0];
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 10, 0, 200, canvas.offsetHeight);
};
img.src = URL.createObjectURL(imgFile);
}
};

const handleClear = () => {
const canvas = document.getElementById('upload');
if (canvas) {
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 1000, 100);
document.getElementById('file-select').value = '';
props.onClearSignature();
}
};

return (
<div>
<div className={cx('signature-wrapper')}>
<Signature id="upload" />
</div>
<br />
<button type="button" onClick={handleClear}>Clear</button>
<input className={cx('input-image')} id="file-select" type="file" accept="image/*" onChange={handleFileSelect} />
</div>
);
};

ImageSignature.propTypes = propTypes;

export default ImageSignature;
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React from 'react';
import Signature from 'terra-signature';
import classNames from 'classnames/bind';
import Tabs from 'terra-tabs';
import VisuallyHiddenText from 'terra-visually-hidden-text';
import TextSignature from './TextSignature';
import ImageSignature from './ImageSignature';
import styles from './SignatureExample.module.scss';

const cx = classNames.bind(styles);
Expand All @@ -9,73 +13,73 @@ class SignatureExample extends React.Component {
constructor() {
super();

this.state = { lineSegments: [], lineWidth: Signature.Opts.Width.FINE };

this.handleSingleLine = this.handleSingleLine.bind(this);
this.state = { lineSegments: [], lineWidth: Signature.Opts.Width.FINE, message: '' };
this.handleClear = this.handleClear.bind(this);
this.handleLineWidth = this.handleLineWidth.bind(this);
}

handleSingleLine() {
const singleLine = [{
x1: 71, y1: 8, x2: 71, y2: 8,
}, {
x1: 71, y1: 8, x2: 71, y2: 10,
}, {
x1: 71, y1: 10, x2: 71, y2: 17,
}, {
x1: 71, y1: 17, x2: 71, y2: 28,
}, {
x1: 71, y1: 28, x2: 71, y2: 44,
}, {
x1: 71, y1: 44, x2: 71, y2: 56,
}, {
x1: 71, y1: 56, x2: 71, y2: 68,
}, {
x1: 71, y1: 68, x2: 71, y2: 75,
}, {
x1: 71, y1: 75, x2: 71, y2: 81,
}, {
x1: 71, y1: 81, x2: 71, y2: 84,
}, {
x1: 71, y1: 84, x2: 71, y2: 86,
}, {
x1: 71, y1: 86, x2: 71, y2: 87,
}, {
x1: 71, y1: 87, x2: 71, y2: 87,
}];
const newState = { ...this.state, lineSegments: singleLine };
this.setState(newState);
this.handleLiveRegion = this.handleLiveRegion.bind(this);
this.tabKey = 'compact';
}

handleClear() {
const newState = { ...this.state, lineSegments: [] };
this.setState(newState);
this.handleLiveRegion();
}

handleLineWidth(event) {
this.setState({ [event.target.name]: event.target.value });
}

handleLiveRegion(value) {
this.setState({ message: value ? 'Added Signature' : 'Cleared Signature' });
setTimeout(() => {
this.setState({ message: '' });
}, 3000);
}

render() {
return (
<div>
<div className={cx('signature-wrapper')}>
<Signature id="foo" lineWidth={this.state.lineWidth} lineSegments={this.state.lineSegments} />
</div>
<div>
<button type="button" onClick={this.handleClear}>Clear </button>
<button type="button" onClick={this.handleSingleLine}>Sign w/Line </button>
<div>
<p><label htmlFor="lineWidth">Select a line width:</label></p>
<select id="lineWidth" name="lineWidth" value={this.state.lineWidth} onChange={this.handleLineWidth}>
<option value="1">EXTRAFINE</option>
<option value="2">FINE</option>
<option value="4">MEDIUM</option>
<option value="6">HEAVY</option>
</select>
</div>
</div>
<Tabs setFocusOnContent defaultActiveKey={`${this.tabKey}DrawTab`} id={this.tabKey}>
<Tabs.Pane label="Draw" key={`${this.tabKey}DrawTab`} id={`${this.tabKey}DrawTab`}>
<br />
<>
<div className={cx('signature-wrapper')}>
<Signature id="draw" lineWidth={this.state.lineWidth} lineSegments={this.state.lineSegments} />
</div>
</>
<br />
<div>
<button type="button" onClick={this.handleClear}>Clear </button>
<div>
<p><label htmlFor="lineWidth">Select a line width:</label></p>
<select id="lineWidth" name="lineWidth" value={this.state.lineWidth} onChange={this.handleLineWidth}>
<option value="1">EXTRAFINE</option>
<option value="2">FINE</option>
<option value="4">MEDIUM</option>
<option value="6">HEAVY</option>
</select>
</div>
</div>
</Tabs.Pane>
<Tabs.Pane label="Type" key={`${this.tabKey}TextTab`} id={`${this.tabKey}TextTab`}>
<br />
<TextSignature onClearSignature={this.handleLiveRegion} onAddSignature={this.handleLiveRegion} />
</Tabs.Pane>
<Tabs.Pane label="Upload" key={`${this.tabKey}UploadTab`} id={`${this.tabKey}UploadTab`}>
<br />
<ImageSignature onClearSignature={this.handleLiveRegion} />
</Tabs.Pane>
</Tabs>
<p>
<strong>Note: </strong>
<br />
<ul>
<li>This example Terra Signature currently supports only Draw Functionality.</li>
<li>Signature Text and Signature Upload Image functionalities will be part of future enhancement.</li>
</ul>
</p>
<VisuallyHiddenText aria-live="polite" text={this.state.message} />
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,31 @@
.signature-wrapper {
border: 1px solid rgb(0, 0, 0);
height: 100px;
padding: 5px;
padding: 7px;
width: 100%;
}

.text-area-style {
border: 0;
height: 88px;
width: calc(100% - 0.2rem);

&:focus {
outline: 2px dotted #000;
outline-offset: -2px;
}
}

.clear-button {
position: relative;
z-index: 0;
}

.add-button {
margin: 5px;
}

.input-image {
margin: 5px;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import classNames from 'classnames/bind';
import Signature from 'terra-signature';
import PropTypes from 'prop-types';
import styles from './SignatureExample.module.scss';

const cx = classNames.bind(styles);

const propTypes = { onClearSignature: PropTypes.func, onAddSignature: PropTypes.func };

const TextSignature = (props) => {
const [showTextArea, setshowTextArea] = React.useState(true);
const textArea = React.useRef();

const handleClear = () => {
if (showTextArea) {
if (textArea && textArea.current) textArea.current.value = null;
return;
}
const canvas = document.getElementById('text');
const ctx = canvas?.getContext('2d');
if (ctx) {
ctx.font = '30px Arial';
ctx.clearRect(0, 0, 1000, 100);
}
if (textArea && textArea.current) textArea.current.value = null;
setshowTextArea(true);
props.onClearSignature();
};

const handleAdd = () => {
if (textArea && textArea.current.value) {
const canvas = document.getElementById('text');
const ctx = canvas?.getContext('2d');
if (ctx && canvas) {
ctx.font = '30px Arial';
ctx.fillText(textArea.current.value, 100, 50);
canvas.setAttribute('aria-label', textArea.current.value);
setshowTextArea(false);
props.onAddSignature(true);
}
}
};

return (
<div>
<div className={cx('signature-wrapper')}>
{(showTextArea) ? <textarea aria-label="Enter Name" ref={(node) => { textArea.current = node; }} className={cx('text-area-style')} /> : null}
<Signature id="text" />
</div>
<br />
<div className={cx('clear-button')}>
<button type="button" onClick={handleClear}>Clear</button>
<button className={cx('add-button')} type="button" onClick={handleAdd}>Add</button>
</div>
</div>
);
};
TextSignature.propTypes = propTypes;
export default TextSignature;

0 comments on commit 7c269b0

Please sign in to comment.