Skip to content

Commit

Permalink
Create custom autosize textarea component
Browse files Browse the repository at this point in the history
Replaces autosize, which presently has scroll issues in iOS 11. See: jackmoore/autosize#343
  • Loading branch information
aduth committed Dec 12, 2017
1 parent dab80a8 commit c401b44
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 32 deletions.
5 changes: 0 additions & 5 deletions package-lock.json

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

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
"webpack": "3.8.1"
},
"dependencies": {
"autosize": "4.0.0",
"classcat": "1.0.1",
"date-fns": "1.28.5",
"fast-stable-stringify": "1.0.0",
Expand Down
1 change: 1 addition & 0 deletions src/assets/stylesheets/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@import 'elements';

// Components
@import '~components/autosize-textarea/style';
@import '~components/button/style';
@import '~components/button-group/style';
@import '~components/card/style';
Expand Down
3 changes: 3 additions & 0 deletions src/components/autosize-textarea/_style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.autosize-textarea {
overflow-y: hidden;
}
39 changes: 39 additions & 0 deletions src/components/autosize-textarea/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* External dependencies
*/
import { Component, createElement } from 'preact';
import classcat from 'classcat';

export default class AutosizeTextarea extends Component {
componentDidMount() {
this.resize();
}

resize = () => {
const { base } = this;
base.style.height = '0';
base.style.height = base.scrollHeight + 'px';
};

onInput = ( event ) => {
this.resize();

// Preserve original prop handler behavior
const { onInput } = this.props;
if ( onInput ) {
onInput( event );
}
};

render() {
const { className } = this.props;
const classes = classcat( [ 'autosize-textarea', className ] );

return (
<textarea
{ ...this.props }
onInput={ this.onInput }
className={ classes } />
);
}
}
35 changes: 10 additions & 25 deletions src/components/done-input/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
* External dependencies
*/
import { createElement, Component } from 'preact';
import autosize from 'autosize';
import caret from 'textarea-caret';

/**
* Internal dependencies
*/
import { translate } from 'lib/i18n';
import AutosizeTextarea from 'components/autosize-textarea';
import PopoverMenu from 'components/popover-menu';

export default class DoneInputTextarea extends Component {
Expand All @@ -21,39 +21,24 @@ export default class DoneInputTextarea extends Component {
const { autoFocus, selectionOffset } = this.props;

if ( autoFocus ) {
this.textarea.focus();
this.textarea.base.focus();
}

if ( selectionOffset ) {
const [ start, stop ] = selectionOffset;
this.textarea.setSelectionRange( start, stop );
this.textarea.base.setSelectionRange( start, stop );
}

autosize( this.textarea );
}

componentWillUnmount() {
autosize.destroy( this.textarea );
}

componentDidUpdate( prevProps ) {
const { value, selectionOffset } = this.props;

if ( value !== prevProps.value ) {
this.resize();
}

const { selectionOffset } = this.props;
if ( selectionOffset && selectionOffset !== prevProps.selectionOffset ) {
const [ start, stop ] = selectionOffset;
this.textarea.setSelectionRange( start, stop );
this.textarea.base.setSelectionRange( start, stop );
}
}

resize() {
autosize.update( this.textarea );
}

setRef = ( textarea ) => this.textarea = textarea;
bindTextarea = ( textarea ) => this.textarea = textarea;

setCaretOffset = ( event ) => {
// Calculate caret offset for use in positioning suggestions menu
Expand All @@ -73,10 +58,10 @@ export default class DoneInputTextarea extends Component {

onSelectSuggestion = ( suggestion ) => {
// Insert suggestion at current caret index
this.props.onSuggestionSelected( suggestion, this.textarea.selectionStart );
this.props.onSuggestionSelected( suggestion, this.textarea.base.selectionStart );

// If suggestion inserted via click on PopoverMenu, preserve focus
setTimeout( () => this.textarea && this.textarea.focus() );
setTimeout( () => this.textarea.base && this.textarea.base.focus() );
};

render() {
Expand All @@ -85,8 +70,8 @@ export default class DoneInputTextarea extends Component {

return (
<div className="done-input__textarea">
<textarea
ref={ this.setRef }
<AutosizeTextarea
ref={ this.bindTextarea }
value={ value }
onKeyDown={ onKeyDown }
rows="1"
Expand Down
1 change: 0 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const config = module.exports = {
'./src/index.js',
],
vendor: [
'autosize',
'classcat',
'fast-stable-stringify',
'flatpickr',
Expand Down

0 comments on commit c401b44

Please sign in to comment.