From 4c6898657b744ee3386670fe33ae2a464b29836d Mon Sep 17 00:00:00 2001 From: DD Date: Wed, 6 Sep 2017 18:01:49 -0400 Subject: [PATCH] Bring in buffered input from GUI --- src/components/forms/buffered-input-hoc.jsx | 60 +++++++++++++++++++ src/components/forms/input.css | 42 ++++++++++++++ src/components/forms/input.jsx | 27 +++++++++ src/components/forms/label.css | 19 ++++++ src/components/forms/label.jsx | 25 ++++++++ src/components/paint-editor.css | 55 ++++++++---------- src/components/paint-editor.jsx | 64 +++++++++++++++------ src/containers/paper-canvas.css | 7 +++ src/containers/paper-canvas.jsx | 5 ++ src/css/colors.css | 19 ++++++ src/css/units.css | 11 ++++ 11 files changed, 286 insertions(+), 48 deletions(-) create mode 100644 src/components/forms/buffered-input-hoc.jsx create mode 100644 src/components/forms/input.css create mode 100644 src/components/forms/input.jsx create mode 100644 src/components/forms/label.css create mode 100644 src/components/forms/label.jsx create mode 100644 src/containers/paper-canvas.css create mode 100644 src/css/colors.css create mode 100644 src/css/units.css diff --git a/src/components/forms/buffered-input-hoc.jsx b/src/components/forms/buffered-input-hoc.jsx new file mode 100644 index 00000000..246dfc03 --- /dev/null +++ b/src/components/forms/buffered-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 blur and + * @param {React.Component} Input text input that consumes onChange, onBlur, onKeyPress + * @returns {React.Component} Buffered input that calls onSubmit on blur and + */ +export default function (Input) { + class BufferedInput extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleChange', + 'handleKeyPress', + 'handleFlush' + ]); + this.state = { + value: null + }; + } + handleKeyPress (e) { + if (e.key === 'Enter') { + this.handleFlush(); + e.target.blur(); + } + } + handleFlush () { + const isNumeric = typeof this.props.value === 'number'; + const validatesNumeric = isNumeric ? !isNaN(this.state.value) : true; + if (this.state.value !== null && validatesNumeric) { + this.props.onSubmit(isNumeric ? Number(this.state.value) : this.state.value); + } + this.setState({value: null}); + } + handleChange (e) { + this.setState({value: e.target.value}); + } + render () { + const bufferedValue = this.state.value === null ? this.props.value : this.state.value; + return ( + + ); + } + } + + BufferedInput.propTypes = { + onSubmit: PropTypes.func.isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + }; + + return BufferedInput; +} diff --git a/src/components/forms/input.css b/src/components/forms/input.css new file mode 100644 index 00000000..6d5eefa5 --- /dev/null +++ b/src/components/forms/input.css @@ -0,0 +1,42 @@ +@import "../../css/units.css"; +@import "../../css/colors.css"; + +.input-form { + height: 2rem; + padding: 0 0.75rem; + + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 0.625rem; + font-weight: bold; + color: $text-primary; + + border-width: 1px; + border-style: solid; + border-color: $form-border; + border-radius: 2rem; + + outline: none; + cursor: text; + transition: 0.25s ease-out; /* @todo: standardize with var */ + box-shadow: none; + + /* + For truncating overflowing text gracefully + Min-width is for a bug: https://css-tricks.com/flexbox-truncated-text + @todo: move this out into a mixin or a helper component + */ + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + min-width: 0; +} + +.input-form:focus { + border-color: #4c97ff; + box-shadow: inset 0 0 0 -2px rgba(0, 0, 0, 0.1); +} + +.input-small { + width: 3rem; + text-align: center; +} diff --git a/src/components/forms/input.jsx b/src/components/forms/input.jsx new file mode 100644 index 00000000..6f9cbffa --- /dev/null +++ b/src/components/forms/input.jsx @@ -0,0 +1,27 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import classNames from 'classnames'; + +import styles from './input.css'; + +const Input = props => { + const {small, ...componentProps} = props; + return ( + + ); +}; + +Input.propTypes = { + small: PropTypes.bool +}; + +Input.defaultProps = { + small: false +}; + +export default Input; diff --git a/src/components/forms/label.css b/src/components/forms/label.css new file mode 100644 index 00000000..5eb280b8 --- /dev/null +++ b/src/components/forms/label.css @@ -0,0 +1,19 @@ +@import "../../css/units.css"; +@import "../../css/colors.css"; + +.input-group { + display: inline-flex; + flex-direction: row; + align-items: center; +} + +.input-label, .input-label-secondary { + font-size: 0.625rem; + margin-right: calc($space / 2); + user-select: none; + cursor: default; +} + +.input-label { + font-weight: bold; +} diff --git a/src/components/forms/label.jsx b/src/components/forms/label.jsx new file mode 100644 index 00000000..62f077a7 --- /dev/null +++ b/src/components/forms/label.jsx @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +import styles from './label.css'; + +const Label = props => ( + +); + +Label.propTypes = { + children: PropTypes.node, + secondary: PropTypes.bool, + text: PropTypes.string.isRequired +}; + +Label.defaultProps = { + secondary: false +}; + +export default Label; diff --git a/src/components/paint-editor.css b/src/components/paint-editor.css index 37991495..2048c9cc 100644 --- a/src/components/paint-editor.css +++ b/src/components/paint-editor.css @@ -1,35 +1,5 @@ -$ui-pane-border: #D9D9D9; -$ui-pane-gray: #F9F9F9; -$ui-background-blue: #e8edf1; - -$text-primary: #575e75; - -$motion-primary: #4C97FF; -$motion-tertiary: #3373CC; -$motion-transparent: hsla(215, 100%, 65%, 0.20); - -$red-primary: #FF661A; -$red-tertiary: #E64D00; - -$sound-primary: #CF63CF; -$sound-tertiary: #A63FA6; - -$control-primary: #FFAB19; - -$form-border: #E9EEF2; - -$space: 0.5rem; - -$sprites-per-row: 5; - -$menu-bar-height: 3rem; -$sprite-info-height: 6rem; -$stage-menu-height: 2.75rem; - -$library-header-height: 4.375rem; - -$form-radius: calc($space / 2); - +@import "../css/colors.css"; +@import "../css/units.css"; .editor-container { display: flex; @@ -43,6 +13,12 @@ $form-radius: calc($space / 2); align-items: center; } +.top-align-row { + padding-top:20px; + display: flex; + flex-direction: row; +} + .row + .row { margin-top: calc(2 * $space); } @@ -143,3 +119,18 @@ $border-radius: 0.25rem; .button:disabled > img { opacity: 0.25; } + +.canvas-container { + width: 503px; + height: 403px; + background-color: #e8edf1; + border: 1px solid #e8edf1; + border-radius: 2px; + position: relative; + overflow: visible; +} + +.mode-selector { + display: flex; + flex-direction: column; +} \ No newline at end of file diff --git a/src/components/paint-editor.jsx b/src/components/paint-editor.jsx index d95db51a..4b482f5d 100644 --- a/src/components/paint-editor.jsx +++ b/src/components/paint-editor.jsx @@ -6,8 +6,32 @@ import EraserMode from '../containers/eraser-mode.jsx'; import PropTypes from 'prop-types'; import LineMode from '../containers/line-mode.jsx'; +import {defineMessages, injectIntl, intlShape} from 'react-intl'; +import BufferedInputHOC from './forms/buffered-input-hoc.jsx'; +import Label from './forms/label.jsx'; +import Input from './forms/input.jsx'; + import styles from './paint-editor.css'; +const BufferedInput = BufferedInputHOC(Input); +const messages = defineMessages({ + costume: { + id: 'paint.paintEditor.costume', + description: 'Label for the name of a sound', + defaultMessage: 'Costume' + }, + fill: { + id: 'paint.paintEditor.fill', + description: 'Label for the color picker for the fill color', + defaultMessage: 'Fill' + }, + outline: { + id: 'paint.paintEditor.outline', + description: 'Label for the color picker for the outline color', + defaultMessage: 'Outline' + } +}); + class PaintEditorComponent extends React.Component { constructor (props) { super(props); @@ -26,10 +50,13 @@ class PaintEditorComponent extends React.Component {
{/* Name field */}
- {/* Todo use Label and BufferedInput from Gui */} - +
{/* Undo/Redo */} @@ -81,19 +108,23 @@ class PaintEditorComponent extends React.Component {
{/* To be fill */}
- +
{/* To be stroke */}
- +
@@ -101,7 +132,7 @@ class PaintEditorComponent extends React.Component {
-
+
{/* Modes */} {this.state.canvas ? (
@@ -136,10 +167,11 @@ class PaintEditorComponent extends React.Component { } PaintEditorComponent.propTypes = { + intl: intlShape, onUpdateSvg: PropTypes.func.isRequired, rotationCenterX: PropTypes.number, rotationCenterY: PropTypes.number, svg: PropTypes.string }; -export default PaintEditorComponent; +export default injectIntl(PaintEditorComponent); diff --git a/src/containers/paper-canvas.css b/src/containers/paper-canvas.css new file mode 100644 index 00000000..525853fd --- /dev/null +++ b/src/containers/paper-canvas.css @@ -0,0 +1,7 @@ +.paper-canvas { + width: 500px; + height: 400px; + margin: auto; + position: relative; + background-color: #fff; +} \ No newline at end of file diff --git a/src/containers/paper-canvas.jsx b/src/containers/paper-canvas.jsx index fdd6e44d..50e95b51 100644 --- a/src/containers/paper-canvas.jsx +++ b/src/containers/paper-canvas.jsx @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import React from 'react'; import paper from 'paper'; +import styles from './paper-canvas.css'; + class PaperCanvas extends React.Component { constructor (props) { super(props); @@ -60,7 +62,10 @@ class PaperCanvas extends React.Component { render () { return ( ); } diff --git a/src/css/colors.css b/src/css/colors.css new file mode 100644 index 00000000..d524795c --- /dev/null +++ b/src/css/colors.css @@ -0,0 +1,19 @@ +$ui-pane-border: #D9D9D9; +$ui-pane-gray: #F9F9F9; +$ui-background-blue: #e8edf1; + +$text-primary: #575e75; + +$motion-primary: #4C97FF; +$motion-tertiary: #3373CC; +$motion-transparent: hsla(215, 100%, 65%, 0.20); + +$red-primary: #FF661A; +$red-tertiary: #E64D00; + +$sound-primary: #CF63CF; +$sound-tertiary: #A63FA6; + +$control-primary: #FFAB19; + +$form-border: #E9EEF2; diff --git a/src/css/units.css b/src/css/units.css new file mode 100644 index 00000000..3de6174a --- /dev/null +++ b/src/css/units.css @@ -0,0 +1,11 @@ +$space: 0.5rem; + +$sprites-per-row: 5; + +$menu-bar-height: 3rem; +$sprite-info-height: 6rem; +$stage-menu-height: 2.75rem; + +$library-header-height: 4.375rem; + +$form-radius: calc($space / 2);