add fill color component

This commit is contained in:
DD 2017-09-07 17:12:50 -04:00
parent f96c26ddbe
commit 9e4c510372
6 changed files with 155 additions and 10 deletions

View file

@ -0,0 +1,38 @@
import React from 'react';
import PropTypes from 'prop-types';
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({
fill: {
id: 'paint.paintEditor.fill',
description: 'Label for the color picker for the fill color',
defaultMessage: 'Fill'
}
});
const FillColorIndicatorComponent = props => (
<div className={styles.inputGroup}>
<Label text={props.intl.formatMessage(messages.fill)}>
<BufferedInput
tabIndex="1"
type="text"
value={props.fillColor}
onSubmit={props.onChangeFillColor}
/>
</Label>
</div>
);
FillColorIndicatorComponent.propTypes = {
fillColor: PropTypes.string.isRequired,
intl: intlShape,
onChangeFillColor: PropTypes.func.isRequired
};
export default injectIntl(FillColorIndicatorComponent);

View file

@ -5,6 +5,7 @@ import BrushMode from '../containers/brush-mode.jsx';
import EraserMode from '../containers/eraser-mode.jsx'; import EraserMode from '../containers/eraser-mode.jsx';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import LineMode from '../containers/line-mode.jsx'; import LineMode from '../containers/line-mode.jsx';
import FillColorIndicatorComponent from '../containers/fill-color-indicator.jsx';
import {defineMessages, injectIntl, intlShape} from 'react-intl'; import {defineMessages, injectIntl, intlShape} from 'react-intl';
import BufferedInputHOC from './forms/buffered-input-hoc.jsx'; import BufferedInputHOC from './forms/buffered-input-hoc.jsx';
@ -107,15 +108,7 @@ class PaintEditorComponent extends React.Component {
{/* Second Row */} {/* Second Row */}
<div className={styles.row}> <div className={styles.row}>
{/* To be fill */} {/* To be fill */}
<div className={styles.inputGroup}> <FillColorIndicatorComponent />
<Label text={this.props.intl.formatMessage(messages.fill)}>
<BufferedInput
tabIndex="1"
type="text"
value="meow"
/>
</Label>
</div>
{/* To be stroke */} {/* To be stroke */}
<div className={styles.inputGroup}> <div className={styles.inputGroup}>
<Label text={this.props.intl.formatMessage(messages.outline)}> <Label text={this.props.intl.formatMessage(messages.outline)}>

View file

@ -0,0 +1,31 @@
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {changeFillColor} from '../reducers/fill-color';
import FillColorIndicatorComponent from '../components/fill-color-indicator.jsx';
const FillColorIndicator = props => (
<FillColorIndicatorComponent
fillColor={props.fillColor}
onChangeFillColor={props.handleChangeFillColor}
/>
);
FillColorIndicator.propTypes = {
fillColor: PropTypes.string.isRequired,
handleChangeFillColor: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
fillColor: state.scratchPaint.fillColor
});
const mapDispatchToProps = dispatch => ({
handleChangeFillColor: fillColor => {
dispatch(changeFillColor(fillColor));
}
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(FillColorIndicator);

View file

@ -0,0 +1,33 @@
import log from '../log/log';
const CHANGE_FILL_COLOR = 'scratch-paint/fill-color/CHANGE_FILL_COLOR';
const initialState = '#000';
// Matches hex colors
const regExp = /^#([0-9a-f]{3}){1,2}$/i;
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case CHANGE_FILL_COLOR:
if (!regExp.test(action.fillColor)) {
log.warn(`Invalid hex color code: ${action.fillColor}`);
return state;
}
return action.fillColor;
default:
return state;
}
};
// Action creators ==================================
const changeFillColor = function (fillColor) {
return {
type: CHANGE_FILL_COLOR,
fillColor: fillColor
};
};
export {
reducer as default,
changeFillColor
};

View file

@ -3,10 +3,12 @@ import modeReducer from './modes';
import brushModeReducer from './brush-mode'; import brushModeReducer from './brush-mode';
import eraserModeReducer from './eraser-mode'; import eraserModeReducer from './eraser-mode';
import lineModeReducer from './line-mode'; import lineModeReducer from './line-mode';
import fillColorReducer from './fill-color';
export default combineReducers({ export default combineReducers({
mode: modeReducer, mode: modeReducer,
brushMode: brushModeReducer, brushMode: brushModeReducer,
eraserMode: eraserModeReducer, eraserMode: eraserModeReducer,
lineMode: lineModeReducer lineMode: lineModeReducer,
fillColor: fillColorReducer
}); });

View file

@ -0,0 +1,48 @@
/* eslint-env jest */
import fillColorReducer from '../../src/reducers/fill-color';
import {changeFillColor} from '../../src/reducers/fill-color';
test('initialState', () => {
let defaultState;
expect(fillColorReducer(defaultState /* state */, {type: 'anything'} /* action */)).toBeDefined();
});
test('changeFillColor', () => {
let defaultState;
// 3 value hex code
let newFillColor = '#fff';
expect(fillColorReducer(defaultState /* state */, changeFillColor(newFillColor) /* action */))
.toEqual(newFillColor);
expect(fillColorReducer('#010' /* state */, changeFillColor(newFillColor) /* action */))
.toEqual(newFillColor);
// 6 value hex code
newFillColor = '#facade';
expect(fillColorReducer(defaultState /* state */, changeFillColor(newFillColor) /* action */))
.toEqual(newFillColor);
expect(fillColorReducer('#010' /* state */, changeFillColor(newFillColor) /* action */))
.toEqual(newFillColor);
});
test('invalidChangeFillColor', () => {
const origState = '#fff';
expect(fillColorReducer(origState /* state */, changeFillColor() /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#1') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#12') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#1234') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#12345') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('#1234567') /* action */))
.toBe(origState);
expect(fillColorReducer(origState /* state */, changeFillColor('invalid argument') /* action */))
.toBe(origState);
});