From 7dbabf60a90637f39e80e3df91891884461ef283 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 1 Nov 2017 13:41:36 -0400 Subject: [PATCH 1/4] change size inputs to input with custon onChange This fixes #122 by reverting the changes to `bufferedInputHOC`, and adding a custom `onChange` handler to the mode tools for brush and eraser, and making them `Input` components. Same goes for the strok width indicator. --- src/components/forms/buffered-input-hoc.jsx | 9 --------- src/components/mode-tools/mode-tools.jsx | 16 ++++++++++++---- src/components/stroke-width-indicator.jsx | 10 +++++++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/components/forms/buffered-input-hoc.jsx b/src/components/forms/buffered-input-hoc.jsx index e7bc25a3..b3561136 100644 --- a/src/components/forms/buffered-input-hoc.jsx +++ b/src/components/forms/buffered-input-hoc.jsx @@ -2,10 +2,6 @@ @todo This file is copied from GUI and should be pulled out into a shared library. See https://github.com/LLK/scratch-paint/issues/13 */ -/* ACTUALLY, THIS HAS BEEN EDITED ;) -handleChange() was adjusted here to actually send a change to `onSubmit()` so that -brush/eraser sizes change immediately on a numeric input*/ - import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; @@ -43,11 +39,6 @@ export default function (Input) { this.setState({value: null}); } handleChange (e) { - const isNumeric = typeof this.props.value === 'number'; - const validatesNumeric = isNumeric ? !isNaN(e.target.value) : true; - if (e.target.value !== null && validatesNumeric) { - this.props.onSubmit(isNumeric ? Number(e.target.value) : e.target.value); - } this.setState({value: e.target.value}); } render () { diff --git a/src/components/mode-tools/mode-tools.jsx b/src/components/mode-tools/mode-tools.jsx index ef6dad32..3fe3332f 100644 --- a/src/components/mode-tools/mode-tools.jsx +++ b/src/components/mode-tools/mode-tools.jsx @@ -6,7 +6,6 @@ import React from 'react'; import {changeBrushSize} from '../../reducers/brush-mode'; import {changeBrushSize as changeEraserSize} from '../../reducers/eraser-mode'; -import BufferedInputHOC from '../forms/buffered-input-hoc.jsx'; import {injectIntl, intlShape} from 'react-intl'; import Input from '../forms/input.jsx'; // import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx'; @@ -22,7 +21,6 @@ import eraserIcon from '../eraser-mode/eraser.svg'; import {MAX_STROKE_WIDTH} from '../../reducers/stroke-width'; -const BufferedInput = BufferedInputHOC(Input); const ModeToolsComponent = props => { const brushMessage = props.intl.formatMessage({ defaultMessage: 'Brush', @@ -46,12 +44,17 @@ const ModeToolsComponent = props => { src={brushIcon} /> - @@ -66,12 +69,17 @@ const ModeToolsComponent = props => { src={eraserIcon} /> - diff --git a/src/components/stroke-width-indicator.jsx b/src/components/stroke-width-indicator.jsx index a0947b67..c7ecb7a2 100644 --- a/src/components/stroke-width-indicator.jsx +++ b/src/components/stroke-width-indicator.jsx @@ -1,22 +1,26 @@ import React from 'react'; import PropTypes from 'prop-types'; -import BufferedInputHOC from './forms/buffered-input-hoc.jsx'; import Input from './forms/input.jsx'; import InputGroup from './input-group/input-group.jsx'; import {MAX_STROKE_WIDTH} from '../reducers/stroke-width'; -const BufferedInput = BufferedInputHOC(Input); const StrokeWidthIndicatorComponent = props => ( - From d2952c2114ca5c6fd2b3192265d80d7311eb028a Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Wed, 1 Nov 2017 15:57:31 -0400 Subject: [PATCH 2/4] create liveinput hoc instead this should solve the issue of being able to delete what you typed. Thanks! --- src/components/forms/live-input-hoc.jsx | 60 +++++++++++++++++++++++ src/components/mode-tools/mode-tools.jsx | 16 ++---- src/components/stroke-width-indicator.jsx | 10 ++-- 3 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 src/components/forms/live-input-hoc.jsx diff --git a/src/components/forms/live-input-hoc.jsx b/src/components/forms/live-input-hoc.jsx new file mode 100644 index 00000000..dac4a905 --- /dev/null +++ b/src/components/forms/live-input-hoc.jsx @@ -0,0 +1,60 @@ +import bindAll from 'lodash.bindall'; +import PropTypes from 'prop-types'; +import React from 'react'; + +/** + * Higher Order Component to manage inputs that submit on change and + * @param {React.Component} Input text input that consumes onChange, onBlur, onKeyPress + * @returns {React.Component} Live input that calls onSubmit on change and + */ +export default function (Input) { + class LiveInput extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleChange', + 'handleKeyPress', + 'handleFlush' + ]); + this.state = { + value: null + }; + } + handleKeyPress (e) { + if (e.key === 'Enter') { + this.handleChange(e); + e.target.blur(); + } + } + handleFlush () { + this.setState({value: null}); + } + handleChange (e) { + const isNumeric = typeof this.props.value === 'number'; + const validatesNumeric = isNumeric ? !isNaN(e.target.value) : true; + if (e.target.value !== null && validatesNumeric) { + this.props.onSubmit(Number(e.target.value)); + } + this.setState({value: e.target.value}); + } + render () { + const liveValue = this.state.value === null ? this.props.value : this.state.value; + return ( + + ); + } + } + + LiveInput.propTypes = { + onSubmit: PropTypes.func.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + }; + + return LiveInput; +} diff --git a/src/components/mode-tools/mode-tools.jsx b/src/components/mode-tools/mode-tools.jsx index 3fe3332f..7c297677 100644 --- a/src/components/mode-tools/mode-tools.jsx +++ b/src/components/mode-tools/mode-tools.jsx @@ -6,6 +6,7 @@ import React from 'react'; import {changeBrushSize} from '../../reducers/brush-mode'; import {changeBrushSize as changeEraserSize} from '../../reducers/eraser-mode'; +import LiveInputHOC from '../forms/live-input-hoc.jsx'; import {injectIntl, intlShape} from 'react-intl'; import Input from '../forms/input.jsx'; // import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx'; @@ -21,6 +22,7 @@ import eraserIcon from '../eraser-mode/eraser.svg'; import {MAX_STROKE_WIDTH} from '../../reducers/stroke-width'; +const LiveInput = LiveInputHOC(Input); const ModeToolsComponent = props => { const brushMessage = props.intl.formatMessage({ defaultMessage: 'Brush', @@ -44,17 +46,12 @@ const ModeToolsComponent = props => { src={brushIcon} /> - @@ -69,17 +66,12 @@ const ModeToolsComponent = props => { src={eraserIcon} /> - diff --git a/src/components/stroke-width-indicator.jsx b/src/components/stroke-width-indicator.jsx index c7ecb7a2..66b79faa 100644 --- a/src/components/stroke-width-indicator.jsx +++ b/src/components/stroke-width-indicator.jsx @@ -3,24 +3,20 @@ import PropTypes from 'prop-types'; import Input from './forms/input.jsx'; import InputGroup from './input-group/input-group.jsx'; +import LiveInputHOC from './forms/live-input-hoc.jsx'; import {MAX_STROKE_WIDTH} from '../reducers/stroke-width'; +const LiveInput = LiveInputHOC(Input); const StrokeWidthIndicatorComponent = props => ( - From 9eb3b7af3952dffadf308c5df60dbe8c057244a1 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Thu, 2 Nov 2017 22:15:25 -0400 Subject: [PATCH 3/4] Validate max value in live input Also snap to max if the value is larger. Thanks @fsih! --- src/components/forms/live-input-hoc.jsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/forms/live-input-hoc.jsx b/src/components/forms/live-input-hoc.jsx index dac4a905..812f3ed5 100644 --- a/src/components/forms/live-input-hoc.jsx +++ b/src/components/forms/live-input-hoc.jsx @@ -32,8 +32,12 @@ export default function (Input) { handleChange (e) { const isNumeric = typeof this.props.value === 'number'; const validatesNumeric = isNumeric ? !isNaN(e.target.value) : true; - if (e.target.value !== null && validatesNumeric) { - this.props.onSubmit(Number(e.target.value)); + if (e.target.value !== null && validatesNumeric ) { + let val = Number(e.target.value); + if (typeof this.props.max !== 'undefined' && val > this.props.max) { + val = this.props.max; + } + this.props.onSubmit(val); } this.setState({value: e.target.value}); } @@ -52,6 +56,7 @@ export default function (Input) { } LiveInput.propTypes = { + max: PropTypes.number, onSubmit: PropTypes.func.isRequired, value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) }; From e39b4edce1f09bc557f4a2472df52b25b41e3ca0 Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Fri, 3 Nov 2017 12:49:34 -0400 Subject: [PATCH 4/4] check min too --- src/components/forms/live-input-hoc.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/forms/live-input-hoc.jsx b/src/components/forms/live-input-hoc.jsx index 812f3ed5..30792962 100644 --- a/src/components/forms/live-input-hoc.jsx +++ b/src/components/forms/live-input-hoc.jsx @@ -34,9 +34,12 @@ export default function (Input) { const validatesNumeric = isNumeric ? !isNaN(e.target.value) : true; if (e.target.value !== null && validatesNumeric ) { let val = Number(e.target.value); - if (typeof this.props.max !== 'undefined' && val > this.props.max) { + if (typeof this.props.max !== 'undefined' && val > Number(this.props.max)) { val = this.props.max; } + if (typeof this.props.min !== 'undefined' && val < Number(this.props.min)) { + val = this.props.min; + } this.props.onSubmit(val); } this.setState({value: e.target.value}); @@ -57,6 +60,7 @@ export default function (Input) { LiveInput.propTypes = { max: PropTypes.number, + min: PropTypes.number, onSubmit: PropTypes.func.isRequired, value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) };