diff options
author | Francesco Cioria <firefelix@gmail.com> | 2017-01-20 00:38:25 +0100 |
---|---|---|
committer | Francesco Cioria <firefelix@gmail.com> | 2017-01-22 19:02:12 +0100 |
commit | f33ab29153b3949b42f32d7ccc1e76e832bef809 (patch) | |
tree | 39aa78f86c49ffc235d23de01c473a19796e0450 | |
parent | 4266b0abc46d4bc6a624b4e8bf58be9b6322eb27 (diff) | |
download | react-autosize-textarea-f33ab29153b3949b42f32d7ccc1e76e832bef809.zip react-autosize-textarea-f33ab29153b3949b42f32d7ccc1e76e832bef809.tar.gz react-autosize-textarea-f33ab29153b3949b42f32d7ccc1e76e832bef809.tar.bz2 |
add prop maxRows and use it to fix textarea maxHeight
-rw-r--r-- | src/TextareaAutosize.js | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/src/TextareaAutosize.js b/src/TextareaAutosize.js index 8677c6a..44b0bef 100644 --- a/src/TextareaAutosize.js +++ b/src/TextareaAutosize.js @@ -7,20 +7,29 @@ const UPDATE = 'autosize:update', RESIZED = 'autosize:resized'; export const Props = { + rows: t.maybe(t.Integer), + maxRows: t.maybe(t.Integer), onResize: t.maybe(t.Function) }; /** A light replacement for built-in textarea component * which automaticaly adjusts its height to match the content * @param onResize - called whenever the textarea resizes + * @param rows - minimum number of visible rows + * @param maxRows - maximum number of visible rows */ @props(Props, { strict: false }) export default class TextareaAutosize extends React.Component { static defaultProps = { - rows: 1 + rows: 1, + maxRows: 5 }; + state = { + maxHeight: null + } + componentDidMount() { autosize(this.textarea); if (this.props.onResize) { @@ -44,10 +53,52 @@ export default class TextareaAutosize extends React.Component { getValue = ({ valueLink, value }) => valueLink ? valueLink.value : value; + onChange = e => { + const { + props: { maxRows, onChange }, + state: { maxHeight } + } = this; + + const numberOfRows = e.target.value.split('\n').length; + + if (!maxHeight && numberOfRows >= maxRows) { + const computedStyle = window.getComputedStyle(this.textarea); + + const paddingTop = parseFloat(computedStyle.getPropertyValue('padding-top'), 10); + const paddingBottom = parseFloat(computedStyle.getPropertyValue('padding-top'), 10); + const verticalPadding = (paddingTop || 0) + (paddingBottom || 0); + + const borderTopWidth = parseInt(computedStyle.getPropertyValue('border-top-width'), 10); + const borderBottomWidth = parseInt(computedStyle.getPropertyValue('border-bottom-width'), 10); + const verticalBorderWidth = (borderTopWidth || 0) + (borderBottomWidth || 0); + + this.setState({ + maxHeight: this.textarea.offsetHeight - verticalPadding - verticalBorderWidth + }); + } else if (maxHeight && numberOfRows < maxRows) { + this.setState({ maxHeight: null }); + } + + onChange && onChange(e); + } + + getLocals = () => { + const { + props: { onResize, maxRows, onChange, style, ...props }, // eslint-disable-line no-unused-vars + state: { maxHeight } + } = this; + + return { + ...props, + style: maxHeight ? { ...style, maxHeight } : style, + onChange: this.onChange + }; + } + render() { - const { children, onResize, ...props } = this.props; // eslint-disable-line no-unused-vars + const { children, ...locals } = this.getLocals(); return ( - <textarea {...props} ref={(ref) => { this.textarea = ref; }}> + <textarea {...locals} ref={(ref) => { this.textarea = ref; }}> {children} </textarea> ); |