Add svg icons to tool select components

This also adds a generic `tool-select` component which can be composed by each of the individual tools for presentation purposes.

Towards #40.
This commit is contained in:
Matthew Taylor 2017-10-19 15:08:15 -04:00
parent c49a469eda
commit 2e0b34a325
50 changed files with 534 additions and 217 deletions

View file

@ -75,6 +75,7 @@
"regenerator-runtime": "^0.10.5",
"rimraf": "^2.6.1",
"style-loader": "^0.18.0",
"svg-url-loader": "^2.2.0",
"tap": "^10.2.0",
"webpack": "^3.5.4",
"webpack-dev-server": "^2.7.0"

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const BrushModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Brush"
description="Label for the brush tool"
id="paint.brushMode.brush"
/>
</button>
);
BrushModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default BrushModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import brushIcon from './brush.svg';
const BrushModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Brush',
description: 'Label for the brush tool',
id: 'paint.brushMode.brush'
}}
imgSrc={brushIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
BrushModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default BrushModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>brush</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="brush" stroke="#575E75" stroke-width="0.5" fill="#575E75">
<path d="M12.5787225,11.2102026 C11.6196284,12.1692967 10.9129274,12.6614634 10.3576624,12.8507583 C10.1936069,12.3459719 9.91597437,11.8790445 9.52476494,11.4878351 C9.12093585,11.0966257 8.65400846,10.8189932 8.14922209,10.6423179 C8.35113664,10.0870529 8.84330335,9.38035203 9.78977778,8.43387759 C12.0613164,6.14971929 16.0996074,3.36077461 16.8694066,4.13057382 C17.6392058,4.90037303 14.8502611,8.93866396 12.5787225,11.2102026 Z M8.39124334,15.4120104 C8.01569197,15.7748657 7.53110955,15.9621459 7.04652713,15.9855559 L7.04652713,15.9972609 L6.92538153,15.9972609 C3.67867934,16.114311 2.26127577,12.4389379 3.37581533,12.8252032 C4.84167714,13.3285186 5.43650205,12.602808 5.45951972,12.579398 C6.27119527,11.8068673 7.57956779,11.8068673 8.39124334,12.579398 C9.20291889,13.3636337 9.20291889,14.6394798 8.39124334,15.4120104 Z" id="bursh-icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -0,0 +1,22 @@
$border-radius: .25rem;
.button {
padding: 0.25rem;
outline: none;
background: white;
border-radius: $border-radius;
border: 1px solid #ddd;
cursor: pointer;
font-size: 0.85rem;
transition: 0.2s;
}
.button > img {
flex-grow: 1;
width: 1.5rem;
height: 1.5rem;
}
.button:disabled > img {
opacity: 0.25;
}

View file

@ -0,0 +1,33 @@
// Copied from scratch-gui for now
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import styles from './button.css';
const ButtonComponent = ({
className,
onClick,
children,
...props
}) => (
<span
className={classNames(
styles.button,
className
)}
role="button"
onClick={onClick}
{...props}
>
{children}
</span>
);
ButtonComponent.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
onClick: PropTypes.func.isRequired
};
export default ButtonComponent;

View file

@ -5,9 +5,9 @@ import classNames from 'classnames';
import parseColor from 'parse-color';
import bindAll from 'lodash.bindall';
import {MIXED} from '../helper/style-path';
import {MIXED} from '../../helper/style-path';
import Slider from './forms/slider.jsx';
import Slider from '../forms/slider.jsx';
import styles from './color-picker.css';
const colorStringToHsv = hexString => {

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const EraserModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Eraser"
description="Label for the eraser tool"
id="paint.eraserMode.eraser"
/>
</button>
);
EraserModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default EraserModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import eraserIcon from './eraser.svg';
const EraserModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Eraser',
description: 'Label for the eraser tool',
id: 'paint.eraserMode.eraser'
}}
imgSrc={eraserIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
EraserModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default EraserModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>eraser</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="eraser" fill="#575E75">
<path d="M13.5370061,14.8291597 L10.9660545,14.8291597 L8.3016138,12.164719 L11.1686144,9.29771842 L15.1263216,13.2554257 L13.5370061,14.8291597 Z M16.7779633,12.6944908 L11.1686144,7.10072343 L8.3016138,4.23372287 C8.00556483,3.92209238 7.50695604,3.92209238 7.19532554,4.23372287 L3.22203673,8.20701169 C2.92598776,8.50306066 2.92598776,9.00166945 3.22203673,9.29771842 L6.10461881,12.164719 L10.0934891,16.1535893 C10.2337229,16.3094046 10.4362827,16.3873122 10.6388425,16.3873122 L13.8642181,16.3873122 C14.066778,16.3873122 14.2693378,16.3094046 14.4095715,16.1535893 L16.7779633,13.8007791 C17.0740122,13.5047301 17.0740122,13.0061213 16.7779633,12.6944908 L16.7779633,12.6944908 Z" id="eraser-icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -4,10 +4,10 @@ import Popover from 'react-popover';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import Label from './forms/label.jsx';
import ColorPicker from './color-picker.jsx';
import ColorButton from './color-button.jsx';
import ColorPicker from './color-picker/color-picker.jsx';
import ColorButton from './color-button/color-button.jsx';
import styles from './paint-editor.css';
import styles from './paint-editor/paint-editor.css';
const messages = defineMessages({
fill: {

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const LineModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Line"
description="Label for the line tool, which draws straight line segments"
id="paint.lineMode.line"
/>
</button>
);
LineModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default LineModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import lineIcon from './line.svg';
const LineModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Line',
description: 'Label for the line tool, which draws straight line segments',
id: 'paint.lineMode.line'
}}
imgSrc={lineIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
LineModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default LineModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>line</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="square">
<g id="line" stroke="#575E75" stroke-width="2">
<path d="M5,15 L15,5" id="Line"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 606 B

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const OvalModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Circle"
description="Label for the oval-drawing tool"
id="paint.ovalMode.oval"
/>
</button>
);
OvalModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default OvalModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import ovalIcon from './oval.svg';
const OvalModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Circle',
description: 'Label for the oval-drawing tool',
id: 'paint.ovalMode.oval'
}}
imgSrc={ovalIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
OvalModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default OvalModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>oval</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="oval" stroke-width="1.5" stroke="#575E75">
<circle id="oval-icon" cx="10" cy="10" r="5"></circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 599 B

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const PenModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Pen"
description="Label for the pen tool, which draws outlines"
id="paint.penMode.pen"
/>
</button>
);
PenModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default PenModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import penIcon from './pen.svg';
const PenModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Pen',
description: 'Label for the pen tool, which draws outlines',
id: 'paint.penMode.pen'
}}
imgSrc={penIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
PenModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default PenModeComponent;

12
src/components/pen-mode/pen.svg Executable file
View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>pen</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="pen" fill="#575E75">
<path d="M9.27946052,8.11513566 L11.8843907,10.7200659 L7.2902411,15.3142155 C7.13236654,15.47209 6.87976725,15.47209 6.72189269,15.3142155 L6.53244322,15.124766 L5.06420984,16.5772119 C4.98527256,16.6561492 4.89054782,16.6877241 4.78003563,16.6877241 C4.66952344,16.6877241 4.57479871,16.6561492 4.49586143,16.5772119 L4.24326214,16.3246126 L3.67491373,16.8929611 C3.59597645,16.9718983 3.48546426,17.0034732 3.39073953,17.0034732 C3.2960148,17.0034732 3.1855026,16.9718983 3.10656533,16.8929611 C2.96447822,16.7350865 2.96447822,16.4824872 3.10656533,16.3246126 L3.67491373,15.7562642 L3.42231444,15.5036649 C3.34337716,15.4247277 3.31180225,15.3300029 3.31180225,15.2194907 C3.31180225,15.1089786 3.34337716,15.0142538 3.42231444,14.9353165 L4.89054782,13.4828706 L4.6853109,13.2776337 C4.52743634,13.1197591 4.52743634,12.8671598 4.6853109,12.7092853 L9.27946052,8.11513566 Z M12.6000004,10 L10,7.30000019 L12.7689619,4.62610794 L12.1690385,4.02618462 L8.08008751,8.0993482 C8.00115023,8.17828548 7.90642549,8.22564785 7.81170076,8.22564785 C7.70118857,8.22564785 7.60646384,8.17828548 7.52752656,8.0993482 C7.369652,7.94147365 7.369652,7.70466181 7.52752656,7.54678725 L11.8848643,3.18944947 C11.9638016,3.11051219 12.0585264,3.06314982 12.1690385,3.06314982 C12.2795507,3.06314982 12.3742755,3.11051219 12.4532127,3.18944947 L13.3215228,4.07354699 L14.158258,3.23681184 C14.4740071,2.92106272 14.9792057,2.92106272 15.2949548,3.23681184 L16.7631882,4.70504522 C17.0789373,5.02079433 17.0789373,5.52599292 16.7631882,5.84174203 L12.6000004,10 Z" id="pen-icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const RectModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Rectangle"
description="Label for the rectangle tool"
id="paint.rectMode.rect"
/>
</button>
);
RectModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default RectModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import rectIcon from './rectangle.svg';
const RectModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Rectangle',
description: 'Label for the rectangle tool',
id: 'paint.rectMode.rect'
}}
imgSrc={rectIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
RectModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default RectModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>rectangle</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g id="rectangle" stroke="#575E75" stroke-width="1.5">
<rect id="rectangle-icon" x="5" y="5" width="10" height="10"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 670 B

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const ReshapeModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Reshape"
description="Label for the reshape tool, which allows changing the points in the lines of the vectors"
id="paint.reshapeMode.reshape"
/>
</button>
);
ReshapeModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default ReshapeModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import reshapeIcon from './reshape.svg';
const ReshapeModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Reshape',
description: 'Label for the reshape tool, which allows changing the points in the lines of the vectors',
id: 'paint.reshapeMode.reshape'
}}
imgSrc={reshapeIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
ReshapeModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default ReshapeModeComponent;

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>reshape</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="reshape">
<g id="reshape-icon" transform="translate(3.000000, 2.000000)">
<path d="M6.3718,4e-05 C6.3718,1.20298846 6.03840639,2.32811001 5.45898306,3.28804076 C5.31876362,3.52034235 4.30079812,3.15107034 3.82818604,3.61859131 C3.35557395,4.08611228 3.47873759,5.34529147 3.26181884,5.47482181 C2.30759304,6.04462589 1.19191205,6.37204 -0.0002,6.37204" id="Stroke-1" stroke="#575E75" stroke-width="0.75"></path>
<path d="M4,6.94999094 C2.85887984,6.71835578 2,5.70947896 2,4.5 C2,3.11928813 3.11928813,2 4.5,2 C5.88071187,2 7,3.11928813 7,4.5 C7,4.56854233 6.99724162,4.63644042 6.99182982,4.70358929 L6.68137747,4.42017327 C5.65792772,3.48493325 4,4.20484091 4,5.595932 L4,6.94999094 Z" id="Combined-Shape" fill="#575E75"></path>
<path d="M4,7.96455557 C2.30385293,7.72194074 1,6.26323595 1,4.5 C1,2.56700338 2.56700338,1 4.5,1 C6.43299662,1 8,2.56700338 8,4.5 C8,4.84508345 7.95005914,5.1785026 7.85701065,5.4934242 L6.68137747,4.42017327 C5.65792772,3.48493325 4,4.20484091 4,5.595932 L4,7.96455557 Z" id="Oval-2" fill-opacity="0.15" fill="#575E75"></path>
<path d="M7.87915329,13.1684522 L8.98467414,15.6316703 C9.20235954,16.1186581 9.76980913,16.3337238 10.2516521,16.1137141 C10.7334951,15.8924683 10.9462887,15.3189598 10.7286032,14.833208 L9.63583183,12.3973461 L12.3974628,12.3973461 C12.945512,12.3973461 13.207518,11.7313818 12.8048941,11.3644462 L6.00716065,5.15870674 C5.6225647,4.80725864 5,5.07769498 5,5.595932 L5,14.8026807 C5,15.3507015 5.68145595,15.608033 6.04802397,15.1994001 L7.87915329,13.1684522 Z" id="select-icon" fill="#575E75"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const RoundedRectModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Rounded Rectangle"
description="Label for the rounded rectangle tool"
id="paint.roundedRectMode.roundedRect"
/>
</button>
);
RoundedRectModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default RoundedRectModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import roundedRectIcon from './rounded-rectangle.svg';
const RoundedRectModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Rounded Rectangle',
description: 'Label for the rounded rectangle tool',
id: 'paint.roundedRectMode.roundedRect'
}}
imgSrc={roundedRectIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
RoundedRectModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default RoundedRectModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>rounded-rectangle</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="rounded-rectangle" stroke="#575E75" stroke-width="1.5">
<rect id="rounded-rectangle-icon" x="5" y="5" width="10" height="10" rx="2"></rect>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 654 B

View file

@ -1,19 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import {FormattedMessage} from 'react-intl';
const SelectModeComponent = props => (
<button onClick={props.onMouseDown}>
<FormattedMessage
defaultMessage="Select"
description="Label for the select tool, which allows selecting, moving, and resizing shapes"
id="paint.selectMode.select"
/>
</button>
);
SelectModeComponent.propTypes = {
onMouseDown: PropTypes.func.isRequired
};
export default SelectModeComponent;

View file

@ -0,0 +1,25 @@
import React from 'react';
import PropTypes from 'prop-types';
import ToolSelectComponent from '../tool-select-base/tool-select-base.jsx';
import selectIcon from './select.svg';
const SelectModeComponent = props => (
<ToolSelectComponent
imgDescriptor={{
defaultMessage: 'Select',
description: 'Label for the select tool, which allows selecting, moving, and resizing shapes',
id: 'paint.selectMode.select'
}}
imgSrc={selectIcon}
isSelected={props.isSelected}
onMouseDown={props.onMouseDown}
/>
);
SelectModeComponent.propTypes = {
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default SelectModeComponent;

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
<title>select</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="select" fill="#575E75">
<path d="M9.08480709,12.7519131 L10.2692937,15.3910753 C10.5025281,15.912848 11.1105098,16.1432755 11.6267701,15.9075508 C12.1430304,15.6705018 12.3710236,15.0560284 12.1377892,14.53558 L10.9669627,11.925728 L13.925853,11.925728 C14.5130486,11.925728 14.7937693,11.2121948 14.3623865,10.8190495 L7.0791007,4.17004294 C6.6670336,3.7934914 6,4.08324462 6,4.63849857 L6,14.5028722 C6,15.0900373 6.73013138,15.3657496 7.12288282,14.9279287 L9.08480709,12.7519131 Z" id="select-icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1,014 B

View file

@ -4,10 +4,10 @@ import Popover from 'react-popover';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import Label from './forms/label.jsx';
import ColorPicker from './color-picker.jsx';
import ColorButton from './color-button.jsx';
import ColorPicker from './color-picker/color-picker.jsx';
import ColorButton from './color-button/color-button.jsx';
import styles from './paint-editor.css';
import styles from './paint-editor/paint-editor.css';
const messages = defineMessages({
stroke: {

View file

@ -6,7 +6,7 @@ import Input from './forms/input.jsx';
import {MAX_STROKE_WIDTH} from '../reducers/stroke-width';
import styles from './paint-editor.css';
import styles from './paint-editor/paint-editor.css';
const BufferedInput = BufferedInputHOC(Input);
const StrokeWidthIndicatorComponent = props => (

View file

@ -0,0 +1,19 @@
@import '../../css/colors.css';
.tool-select {
background: none;
border: none;
}
.tool-select.is-selected {
background-color: $ui-background-blue;
}
.tool-select:focus {
outline: none;
}
img.tool-select-icon {
width: 2rem;
height: 2rem;
}

View file

@ -0,0 +1,44 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import {injectIntl, intlShape} from 'react-intl';
import Button from '../button/button.jsx';
import styles from './tool-select-base.css';
const ToolSelectComponent = props => (
<Button
className={
classNames(props.className, styles.toolSelect, {
[styles.isSelected]: props.isSelected
})
}
onClick={props.onMouseDown}
>
<img
alt={props.intl.formatMessage({
defaultMessage: props.imgDescriptor.defaultMessage,
description: props.imgDescriptor.description,
id: props.imgDescriptor.id
})}
className={styles.toolSelectIcon}
src={props.imgSrc}
/>
</Button>
);
ToolSelectComponent.propTypes = {
className: PropTypes.string,
imgDescriptor: PropTypes.shape({
defaultMessage: PropTypes.string,
description: PropTypes.string,
id: PropTypes.string
}).isRequired,
imgSrc: PropTypes.string.isRequired,
intl: intlShape.isRequired,
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default injectIntl(ToolSelectComponent);

View file

@ -10,7 +10,7 @@ import {changeMode} from '../reducers/modes';
import {clearSelectedItems} from '../reducers/selected-items';
import {clearSelection} from '../helper/selection';
import BrushModeComponent from '../components/brush-mode.jsx';
import BrushModeComponent from '../components/brush-mode/brush-mode.jsx';
class BrushMode extends React.Component {
constructor (props) {
@ -41,8 +41,8 @@ class BrushMode extends React.Component {
});
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isBrushModeActive !== this.props.isBrushModeActive;
}
activateTool () {
// TODO: Instead of clearing selection, consider a kind of "draw inside"
@ -71,7 +71,10 @@ class BrushMode extends React.Component {
}
render () {
return (
<BrushModeComponent onMouseDown={this.props.handleMouseDown} />
<BrushModeComponent
isSelected={this.props.isBrushModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -6,7 +6,7 @@ import Modes from '../modes/modes';
import Blobbiness from '../helper/blob-tools/blob';
import {changeBrushSize} from '../reducers/eraser-mode';
import {clearSelectedItems} from '../reducers/selected-items';
import EraserModeComponent from '../components/eraser-mode.jsx';
import EraserModeComponent from '../components/eraser-mode/eraser-mode.jsx';
import {changeMode} from '../reducers/modes';
class EraserMode extends React.Component {
@ -37,8 +37,8 @@ class EraserMode extends React.Component {
});
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isEraserModeActive !== this.props.isEraserModeActive;
}
activateTool () {
this.props.canvas.addEventListener('mousewheel', this.onScroll);
@ -59,7 +59,10 @@ class EraserMode extends React.Component {
}
render () {
return (
<EraserModeComponent onMouseDown={this.props.handleMouseDown} />
<EraserModeComponent
isSelected={this.props.isEraserModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {changeMode} from '../reducers/modes';
import {changeStrokeWidth} from '../reducers/stroke-width';
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import LineModeComponent from '../components/line-mode.jsx';
import LineModeComponent from '../components/line-mode/line-mode.jsx';
class LineMode extends React.Component {
static get SNAP_TOLERANCE () {
@ -42,8 +42,8 @@ class LineMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isLineModeActive !== this.props.isLineModeActive;
}
activateTool () {
clearSelection(this.props.clearSelectedItems);
@ -266,7 +266,10 @@ class LineMode extends React.Component {
}
render () {
return (
<LineModeComponent onMouseDown={this.props.handleMouseDown} />
<LineModeComponent
isSelected={this.props.isLineModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import OvalTool from '../helper/tools/oval-tool';
import OvalModeComponent from '../components/oval-mode.jsx';
import OvalModeComponent from '../components/oval-mode/oval-mode.jsx';
class OvalMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class OvalMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isOvalModeActive !== this.props.isOvalModeActive;
}
activateTool () {
this.tool = new OvalTool(
@ -56,7 +56,10 @@ class OvalMode extends React.Component {
}
render () {
return (
<OvalModeComponent onMouseDown={this.props.handleMouseDown} />
<OvalModeComponent
isSelected={this.props.isOvalModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -1,6 +1,6 @@
import PropTypes from 'prop-types';
import React from 'react';
import PaintEditorComponent from '../components/paint-editor.jsx';
import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx';
import {changeMode} from '../reducers/modes';
import {undo, redo, undoSnapshot} from '../reducers/undo';

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import PenTool from '../helper/tools/pen-tool';
import PenModeComponent from '../components/pen-mode.jsx';
import PenModeComponent from '../components/pen-mode/pen-mode.jsx';
class PenMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class PenMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isPenModeActive !== this.props.isPenModeActive;
}
activateTool () {
this.tool = new PenTool(
@ -56,7 +56,10 @@ class PenMode extends React.Component {
}
render () {
return (
<PenModeComponent onMouseDown={this.props.handleMouseDown} />
<PenModeComponent
isSelected={this.props.isPenModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import RectTool from '../helper/tools/rect-tool';
import RectModeComponent from '../components/rect-mode.jsx';
import RectModeComponent from '../components/rect-mode/rect-mode.jsx';
class RectMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class RectMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isRectModeActive !== this.props.isRectModeActive;
}
activateTool () {
this.tool = new RectTool(
@ -56,7 +56,10 @@ class RectMode extends React.Component {
}
render () {
return (
<RectModeComponent onMouseDown={this.props.handleMouseDown} />
<RectModeComponent
isSelected={this.props.isRectModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import ReshapeTool from '../helper/selection-tools/reshape-tool';
import ReshapeModeComponent from '../components/reshape-mode.jsx';
import ReshapeModeComponent from '../components/reshape-mode/reshape-mode.jsx';
class ReshapeMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class ReshapeMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isReshapeModeActive !== this.props.isReshapeModeActive;
}
activateTool () {
this.tool = new ReshapeTool(
@ -58,7 +58,10 @@ class ReshapeMode extends React.Component {
}
render () {
return (
<ReshapeModeComponent onMouseDown={this.props.handleMouseDown} />
<ReshapeModeComponent
isSelected={this.props.isReshapeModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import RoundedRectTool from '../helper/tools/rounded-rect-tool';
import RoundedRectModeComponent from '../components/rounded-rect-mode.jsx';
import RoundedRectModeComponent from '../components/rounded-rect-mode/rounded-rect-mode.jsx';
class RoundedRectMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class RoundedRectMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isRoundedRectModeActive !== this.props.isRoundedRectModeActive;
}
activateTool () {
this.tool = new RoundedRectTool(
@ -56,7 +56,10 @@ class RoundedRectMode extends React.Component {
}
render () {
return (
<RoundedRectModeComponent onMouseDown={this.props.handleMouseDown} />
<RoundedRectModeComponent
isSelected={this.props.isRoundedRectModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -10,7 +10,7 @@ import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {getSelectedLeafItems} from '../helper/selection';
import SelectTool from '../helper/selection-tools/select-tool';
import SelectModeComponent from '../components/select-mode.jsx';
import SelectModeComponent from '../components/select-mode/select-mode.jsx';
class SelectMode extends React.Component {
constructor (props) {
@ -36,8 +36,8 @@ class SelectMode extends React.Component {
this.deactivateTool();
}
}
shouldComponentUpdate () {
return false; // Static component, for now
shouldComponentUpdate (nextProps) {
return nextProps.isSelectModeActive !== this.props.isSelectModeActive;
}
activateTool () {
this.tool = new SelectTool(
@ -56,7 +56,10 @@ class SelectMode extends React.Component {
}
render () {
return (
<SelectModeComponent onMouseDown={this.props.handleMouseDown} />
<SelectModeComponent
isSelected={this.props.isSelectModeActive}
onMouseDown={this.props.handleMouseDown}
/>
);
}
}

View file

@ -49,6 +49,10 @@ const base = {
}
}
}]
},
{
test: /\.svg$/,
loader: 'svg-url-loader?noquotes'
}]
},
plugins: []