summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancesco Cioria <firefelix@gmail.com>2017-01-20 00:38:25 +0100
committerFrancesco Cioria <firefelix@gmail.com>2017-01-22 19:02:12 +0100
commitf33ab29153b3949b42f32d7ccc1e76e832bef809 (patch)
tree39aa78f86c49ffc235d23de01c473a19796e0450
parent4266b0abc46d4bc6a624b4e8bf58be9b6322eb27 (diff)
downloadreact-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.js57
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>
);