Merge pull request #7125 from KDSBrowne/2.2-add-pan-hotkey

Add spacebar hotkey to toggle whiteboard Pan tool
This commit is contained in:
Chad Pilkey 2019-03-28 19:47:37 -04:00 committed by GitHub
commit dc9b827bd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,6 +5,7 @@ import { HEXToINTColor, INTToHEXColor } from '/imports/utils/hexInt';
import { defineMessages, injectIntl, intlShape } from 'react-intl'; import { defineMessages, injectIntl, intlShape } from 'react-intl';
import browser from 'browser-detect'; import browser from 'browser-detect';
import { noop } from 'lodash'; import { noop } from 'lodash';
import KEY_CODES from '/imports/utils/keyCodes';
import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component'; import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
import { styles } from './styles.scss'; import { styles } from './styles.scss';
import ToolbarMenuItem from './toolbar-menu-item/component'; import ToolbarMenuItem from './toolbar-menu-item/component';
@ -57,6 +58,10 @@ const intlMessages = defineMessages({
id: 'app.whiteboard.toolbar.fontSize', id: 'app.whiteboard.toolbar.fontSize',
description: 'Whiteboard toolbar font size menu', description: 'Whiteboard toolbar font size menu',
}, },
toolbarItemPan: {
id: 'app.whiteboard.toolbar.tools.hand',
description: 'Label for the pan toolbar item',
},
}); });
const isEdge = browser().name === 'edge'; const isEdge = browser().name === 'edge';
@ -84,6 +89,7 @@ class WhiteboardToolbar extends Component {
// variables to keep current selected draw settings // variables to keep current selected draw settings
annotationSelected, annotationSelected,
prevAnnotationSelected: annotationSelected,
thicknessSelected: { value: 2 }, thicknessSelected: { value: 2 },
colorSelected: { value: '#ff0000' }, colorSelected: { value: '#ff0000' },
fontSizeSelected: { value: 20 }, fontSizeSelected: { value: 20 },
@ -97,6 +103,8 @@ class WhiteboardToolbar extends Component {
// (click anywhere on the screen) thus we have to control the blur manually by disabling it // (click anywhere on the screen) thus we have to control the blur manually by disabling it
// when you hover over the buttons in the list and enabling when the mouse leaves the list // when you hover over the buttons in the list and enabling when the mouse leaves the list
onBlurEnabled: true, onBlurEnabled: true,
panMode: false,
}; };
this.displaySubMenu = this.displaySubMenu.bind(this); this.displaySubMenu = this.displaySubMenu.bind(this);
@ -112,10 +120,13 @@ class WhiteboardToolbar extends Component {
this.handleMouseLeave = this.handleMouseLeave.bind(this); this.handleMouseLeave = this.handleMouseLeave.bind(this);
this.componentDidMount = runExceptInEdge(this.componentDidMount); this.componentDidMount = runExceptInEdge(this.componentDidMount);
this.componentDidUpdate = runExceptInEdge(this.componentDidUpdate); this.componentDidUpdate = runExceptInEdge(this.componentDidUpdate);
this.panOn = this.panOn.bind(this);
this.panOff = this.panOff.bind(this);
} }
componentWillMount() { componentWillMount() {
const drawSettings = this.props.actions.getCurrentDrawSettings(); const { actions } = this.props;
const drawSettings = actions.getCurrentDrawSettings();
// if there are saved drawSettings in the session storage // if there are saved drawSettings in the session storage
// - retrieve them and update toolbar values // - retrieve them and update toolbar values
if (drawSettings) { if (drawSettings) {
@ -126,7 +137,7 @@ class WhiteboardToolbar extends Component {
const { const {
annotationSelected, thicknessSelected, colorSelected, fontSizeSelected, annotationSelected, thicknessSelected, colorSelected, fontSizeSelected,
} = this.state; } = this.state;
this.props.actions.setInitialWhiteboardToolbarValues( actions.setInitialWhiteboardToolbarValues(
annotationSelected.value, annotationSelected.value,
thicknessSelected.value * 2, thicknessSelected.value * 2,
HEXToINTColor(colorSelected.value), HEXToINTColor(colorSelected.value),
@ -140,7 +151,12 @@ class WhiteboardToolbar extends Component {
} }
componentDidMount() { componentDidMount() {
if (this.state.annotationSelected.value !== 'text') { const { annotationSelected } = this.state;
document.addEventListener('keydown', this.panOn);
document.addEventListener('keyup', this.panOff);
if (annotationSelected.value !== 'text') {
// trigger initial animation on the thickness circle, otherwise it stays at 0 // trigger initial animation on the thickness circle, otherwise it stays at 0
this.thicknessListIconColor.beginElement(); this.thicknessListIconColor.beginElement();
this.thicknessListIconRadius.beginElement(); this.thicknessListIconRadius.beginElement();
@ -168,16 +184,31 @@ class WhiteboardToolbar extends Component {
} }
} }
componentWillUnmount() {
document.removeEventListener('keydown', this.panOn);
document.removeEventListener('keyup', this.panOff);
}
setToolbarValues(drawSettings) { setToolbarValues(drawSettings) {
const {
annotations,
} = this.props;
const {
whiteboardAnnotationThickness,
textFontSize, whiteboardAnnotationColor,
whiteboardAnnotationTool,
} = drawSettings;
// divide by 2, since we need the radius for the thickness icon // divide by 2, since we need the radius for the thickness icon
const thicknessSelected = { value: drawSettings.whiteboardAnnotationThickness / 2 }; const thicknessSelected = { value: whiteboardAnnotationThickness / 2 };
const fontSizeSelected = { value: drawSettings.textFontSize }; const fontSizeSelected = { value: textFontSize };
const colorSelected = { value: INTToHEXColor(drawSettings.whiteboardAnnotationColor) }; const colorSelected = { value: INTToHEXColor(whiteboardAnnotationColor) };
let annotationSelected = {}; let annotationSelected = {};
for (let i = 0; i < this.props.annotations.length; i += 1) { for (let i = 0; i < annotations.length; i += 1) {
if (drawSettings.whiteboardAnnotationTool === this.props.annotations[i].value) { if (whiteboardAnnotationTool === annotations[i].value) {
annotationSelected = this.props.annotations[i]; annotationSelected = annotations[i];
break; break;
} }
} }
@ -189,7 +220,47 @@ class WhiteboardToolbar extends Component {
}); });
} }
panOn(event) {
const { annotationSelected } = this.state;
const { target, which } = event;
const isInputArea = target.nodeName === 'TEXTAREA' || target.nodeName === 'INPUT';
if (annotationSelected.value === 'hand' || isInputArea) return;
const { annotations } = this.props;
if ([KEY_CODES.SPACE].includes(which)) {
this.setState(
{
panMode: true,
prevAnnotationSelected: annotationSelected,
},
this.handleAnnotationChange(annotations[annotations.length - 1]),
);
}
}
panOff(event) {
const { target, which } = event;
const isInputArea = target.nodeName === 'TEXTAREA' || target.nodeName === 'INPUT';
if (isInputArea) return;
const { prevAnnotationSelected } = this.state;
if ([KEY_CODES.SPACE].includes(which)) {
this.setState({ panMode: false },
this.handleAnnotationChange(prevAnnotationSelected));
}
}
animateSvgIcons(prevState) { animateSvgIcons(prevState) {
const {
colorSelected,
annotationSelected,
thicknessSelected,
} = this.state;
/* Animation for the svg icons that we use for thickness (circle) and color (rectangle) /* Animation for the svg icons that we use for thickness (circle) and color (rectangle)
* has to be triggered manually * has to be triggered manually
* we have 4 main cases: * we have 4 main cases:
@ -202,18 +273,18 @@ class WhiteboardToolbar extends Component {
* 4. Trigger initial animation for the icons * 4. Trigger initial animation for the icons
*/ */
// 1st case // 1st case
if (this.state.colorSelected.value !== prevState.colorSelected.value) { if (colorSelected.value !== prevState.colorSelected.value) {
// 1st case b) // 1st case b)
if (this.state.annotationSelected.value !== 'text') { if (annotationSelected.value !== 'text') {
this.thicknessListIconColor.beginElement(); this.thicknessListIconColor.beginElement();
} }
// 1st case a) // 1st case a)
this.colorListIconColor.beginElement(); this.colorListIconColor.beginElement();
// 2nd case // 2nd case
} else if (this.state.thicknessSelected.value !== prevState.thicknessSelected.value) { } else if (thicknessSelected.value !== prevState.thicknessSelected.value) {
this.thicknessListIconRadius.beginElement(); this.thicknessListIconRadius.beginElement();
// 3rd case // 3rd case
} else if (this.state.annotationSelected.value !== 'text' } else if (annotationSelected.value !== 'text'
&& prevState.annotationSelected.value === 'text') { && prevState.annotationSelected.value === 'text') {
this.thicknessListIconRadius.beginElement(); this.thicknessListIconRadius.beginElement();
this.thicknessListIconColor.beginElement(); this.thicknessListIconColor.beginElement();
@ -223,19 +294,27 @@ class WhiteboardToolbar extends Component {
// open a submenu // open a submenu
displaySubMenu(listName) { displaySubMenu(listName) {
const { currentSubmenuOpen } = this.state;
this.setState({ this.setState({
currentSubmenuOpen: this.state.currentSubmenuOpen === listName ? '' : listName, currentSubmenuOpen: currentSubmenuOpen === listName ? '' : listName,
}); });
} }
// close a current submenu (fires onBlur only, when you click anywhere on the screen) // close a current submenu (fires onBlur only, when you click anywhere on the screen)
closeSubMenu() { closeSubMenu() {
// a separate case for the active text shape const {
if (this.state.annotationSelected.value === 'text' && this.props.textShapeActiveId !== '') { annotationSelected,
return; onBlurEnabled,
} } = this.state;
if (this.state.onBlurEnabled) { const {
textShapeActiveId,
} = this.props;
// a separate case for the active text shape
if (annotationSelected.value === 'text' && textShapeActiveId !== '') return;
if (onBlurEnabled) {
this.setState({ this.setState({
currentSubmenuOpen: undefined, currentSubmenuOpen: undefined,
}); });
@ -244,22 +323,38 @@ class WhiteboardToolbar extends Component {
// undo annotation // undo annotation
handleUndo() { handleUndo() {
this.props.actions.undoAnnotation(this.props.whiteboardId); const {
actions,
whiteboardId,
} = this.props;
actions.undoAnnotation(whiteboardId);
} }
// clear all annotations // clear all annotations
handleClearAll() { handleClearAll() {
this.props.actions.clearWhiteboard(this.props.whiteboardId); const {
actions,
whiteboardId,
} = this.props;
actions.clearWhiteboard(whiteboardId);
} }
handleSwitchWhiteboardMode() { handleSwitchWhiteboardMode() {
const { multiUser, whiteboardId } = this.props; const {
this.props.actions.changeWhiteboardMode(!multiUser, whiteboardId); multiUser,
whiteboardId,
actions,
} = this.props;
actions.changeWhiteboardMode(!multiUser, whiteboardId);
} }
// changes a current selected annotation both in the state and in the session // changes a current selected annotation both in the state and in the session
// and closes the annotation list // and closes the annotation list
handleAnnotationChange(annotation) { handleAnnotationChange(annotation) {
const { actions } = this.props;
const obj = { const obj = {
annotationSelected: annotation, annotationSelected: annotation,
onBlurEnabled: true, onBlurEnabled: true,
@ -271,18 +366,21 @@ class WhiteboardToolbar extends Component {
obj.prevThicknessSelected = { value: 0 }; obj.prevThicknessSelected = { value: 0 };
} }
this.props.actions.setTool(annotation.value); actions.setTool(annotation.value);
this.setState(obj); this.setState(obj);
} }
// changes a current selected thickness both in the state and in the session // changes a current selected thickness both in the state and in the session
// and closes the thickness list // and closes the thickness list
handleThicknessChange(thicknessSelected) { handleThicknessChange(incomingThickness) {
const { actions } = this.props;
const { thicknessSelected } = this.state;
// thickness value * 2 since this is radius, we need to double it // thickness value * 2 since this is radius, we need to double it
this.props.actions.setThickness(thicknessSelected.value * 2); actions.setThickness(incomingThickness.value * 2);
this.setState({ this.setState({
prevThicknessSelected: this.state.thicknessSelected, prevThicknessSelected: thicknessSelected,
thicknessSelected, thicknessSelected,
onBlurEnabled: true, onBlurEnabled: true,
currentSubmenuOpen: '', currentSubmenuOpen: '',
@ -290,7 +388,8 @@ class WhiteboardToolbar extends Component {
} }
handleFontSizeChange(fontSize) { handleFontSizeChange(fontSize) {
this.props.actions.setFontSize(fontSize.value); const { actions } = this.props;
actions.setFontSize(fontSize.value);
this.setState({ this.setState({
fontSizeSelected: fontSize, fontSizeSelected: fontSize,
@ -302,10 +401,12 @@ class WhiteboardToolbar extends Component {
// changes a current selected color both in the state and in the session // changes a current selected color both in the state and in the session
// and closes the color list // and closes the color list
handleColorChange(color) { handleColorChange(color) {
this.props.actions.setColor(HEXToINTColor(color.value)); const { actions } = this.props;
const { colorSelected } = this.state;
actions.setColor(HEXToINTColor(color.value));
this.setState({ this.setState({
prevColorSelected: this.state.colorSelected, prevColorSelected: colorSelected,
colorSelected: color, colorSelected: color,
onBlurEnabled: true, onBlurEnabled: true,
currentSubmenuOpen: '', currentSubmenuOpen: '',
@ -327,38 +428,49 @@ class WhiteboardToolbar extends Component {
} }
renderToolItem() { renderToolItem() {
const { panMode, annotationSelected, currentSubmenuOpen } = this.state;
const { intl, annotations } = this.props; const { intl, annotations } = this.props;
const isDisabled = !annotations.length; const isDisabled = !annotations.length;
return (
<ToolbarMenuItem return panMode
disabled={isDisabled} ? (
label={intl.formatMessage(intlMessages.toolbarTools)} <ToolbarMenuItem
icon={this.state.annotationSelected.icon} icon="hand"
onItemClick={this.displaySubMenu} label={intl.formatMessage(intlMessages.toolbarItemPan)}
objectToReturn="annotationList" onItemClick={() => {}}
onBlur={this.closeSubMenu} className={styles.toolbarButton}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'annotationList' ? styles.toolbarActive : null)} />
> ) : (
{this.state.currentSubmenuOpen === 'annotationList' && annotations.length > 1 <ToolbarMenuItem
? ( disabled={isDisabled}
<ToolbarSubmenu label={intl.formatMessage(intlMessages.toolbarTools)}
type="annotations" icon={annotationSelected.icon}
customIcon={false} onItemClick={this.displaySubMenu}
label="Annotations" objectToReturn="annotationList"
onItemClick={this.handleAnnotationChange} onBlur={this.closeSubMenu}
objectsToRender={annotations} className={cx(styles.toolbarButton, currentSubmenuOpen === 'annotationList' ? styles.toolbarActive : null)}
objectSelected={this.state.annotationSelected} >
handleMouseEnter={this.handleMouseEnter} {currentSubmenuOpen === 'annotationList' && annotations.length > 1
handleMouseLeave={this.handleMouseLeave} ? (
/> <ToolbarSubmenu
) type="annotations"
: null} customIcon={false}
</ToolbarMenuItem> label="Annotations"
); onItemClick={this.handleAnnotationChange}
objectsToRender={panMode ? annotations[annotations.length - 1] : annotations}
objectSelected={annotationSelected}
handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave}
/>
)
: null}
</ToolbarMenuItem>
);
} }
renderFontItem() { renderFontItem() {
const { intl } = this.props; const { intl, fontSizes } = this.props;
const { currentSubmenuOpen, fontSizeSelected } = this.state;
return ( return (
<ToolbarMenuItem <ToolbarMenuItem
@ -367,17 +479,17 @@ class WhiteboardToolbar extends Component {
onItemClick={this.displaySubMenu} onItemClick={this.displaySubMenu}
objectToReturn="fontSizeList" objectToReturn="fontSizeList"
onBlur={this.closeSubMenu} onBlur={this.closeSubMenu}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'fontSizeList' ? styles.toolbarActive : null)} className={cx(styles.toolbarButton, currentSubmenuOpen === 'fontSizeList' ? styles.toolbarActive : null)}
> >
{this.state.currentSubmenuOpen === 'fontSizeList' {currentSubmenuOpen === 'fontSizeList'
? ( ? (
<ToolbarSubmenu <ToolbarSubmenu
type="font-size" type="font-size"
customIcon customIcon
label="Font Size" label="Font Size"
onItemClick={this.handleFontSizeChange} onItemClick={this.handleFontSizeChange}
objectsToRender={this.props.fontSizes} objectsToRender={fontSizes}
objectSelected={this.state.fontSizeSelected} objectSelected={fontSizeSelected}
handleMouseEnter={this.handleMouseEnter} handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave} handleMouseLeave={this.handleMouseLeave}
/> />
@ -388,12 +500,13 @@ class WhiteboardToolbar extends Component {
} }
renderFontItemIcon() { renderFontItemIcon() {
const { fontSizeSelected, colorSelected } = this.state;
return ( return (
<p <p
className={styles.textThickness} className={styles.textThickness}
style={{ style={{
fontSize: this.state.fontSizeSelected.value, fontSize: fontSizeSelected.value,
color: this.state.colorSelected.value, color: colorSelected.value,
WebkitTransition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`, /* Safari */ WebkitTransition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`, /* Safari */
transition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`, transition: `color ${TRANSITION_DURATION}, font-size ${TRANSITION_DURATION}`,
}} }}
@ -404,8 +517,19 @@ class WhiteboardToolbar extends Component {
} }
renderThicknessItem() { renderThicknessItem() {
const { intl, annotations } = this.props; const {
const isDisabled = this.state.annotationSelected.value === 'hand' || !annotations.length; intl,
annotations,
thicknessRadiuses,
} = this.props;
const {
annotationSelected,
currentSubmenuOpen,
thicknessSelected,
} = this.state;
const isDisabled = annotationSelected.value === 'hand' || !annotations.length;
return ( return (
<ToolbarMenuItem <ToolbarMenuItem
disabled={isDisabled} disabled={isDisabled}
@ -415,18 +539,18 @@ class WhiteboardToolbar extends Component {
onItemClick={this.displaySubMenu} onItemClick={this.displaySubMenu}
objectToReturn="thicknessList" objectToReturn="thicknessList"
onBlur={this.closeSubMenu} onBlur={this.closeSubMenu}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'thicknessList' ? styles.toolbarActive : null)} className={cx(styles.toolbarButton, currentSubmenuOpen === 'thicknessList' ? styles.toolbarActive : null)}
customIcon={this.renderThicknessItemIcon()} customIcon={this.renderThicknessItemIcon()}
> >
{this.state.currentSubmenuOpen === 'thicknessList' {currentSubmenuOpen === 'thicknessList'
? ( ? (
<ToolbarSubmenu <ToolbarSubmenu
type="thickness" type="thickness"
customIcon customIcon
label="Thickness" label="Thickness"
onItemClick={this.handleThicknessChange} onItemClick={this.handleThicknessChange}
objectsToRender={this.props.thicknessRadiuses} objectsToRender={thicknessRadiuses}
objectSelected={this.state.thicknessSelected} objectSelected={thicknessSelected}
handleMouseEnter={this.handleMouseEnter} handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave} handleMouseLeave={this.handleMouseLeave}
/> />
@ -437,6 +561,13 @@ class WhiteboardToolbar extends Component {
} }
renderThicknessItemIcon() { renderThicknessItemIcon() {
const {
colorSelected,
thicknessSelected,
prevThicknessSelected,
prevColorSelected,
} = this.state;
return ( return (
<svg className={styles.customSvgIcon} shapeRendering="geometricPrecision"> <svg className={styles.customSvgIcon} shapeRendering="geometricPrecision">
{isEdge {isEdge
@ -444,10 +575,10 @@ class WhiteboardToolbar extends Component {
<circle <circle
cx="50%" cx="50%"
cy="50%" cy="50%"
r={this.state.thicknessSelected.value} r={thicknessSelected.value}
stroke="black" stroke="black"
strokeWidth="1" strokeWidth="1"
fill={this.state.colorSelected.value} fill={colorSelected.value}
/> />
) )
: ( : (
@ -462,8 +593,8 @@ class WhiteboardToolbar extends Component {
ref={(ref) => { this.thicknessListIconColor = ref; }} ref={(ref) => { this.thicknessListIconColor = ref; }}
attributeName="fill" attributeName="fill"
attributeType="XML" attributeType="XML"
from={this.state.prevColorSelected.value} from={prevColorSelected.value}
to={this.state.colorSelected.value} to={colorSelected.value}
begin="indefinite" begin="indefinite"
dur={TRANSITION_DURATION} dur={TRANSITION_DURATION}
repeatCount="0" repeatCount="0"
@ -473,8 +604,8 @@ class WhiteboardToolbar extends Component {
ref={(ref) => { this.thicknessListIconRadius = ref; }} ref={(ref) => { this.thicknessListIconRadius = ref; }}
attributeName="r" attributeName="r"
attributeType="XML" attributeType="XML"
from={this.state.prevThicknessSelected.value} from={prevThicknessSelected.value}
to={this.state.thicknessSelected.value} to={thicknessSelected.value}
begin="indefinite" begin="indefinite"
dur={TRANSITION_DURATION} dur={TRANSITION_DURATION}
repeatCount="0" repeatCount="0"
@ -487,8 +618,19 @@ class WhiteboardToolbar extends Component {
} }
renderColorItem() { renderColorItem() {
const { intl, annotations } = this.props; const {
const isDisabled = this.state.annotationSelected.value === 'hand' || !annotations.length; intl,
annotations,
colors,
} = this.props;
const {
annotationSelected,
currentSubmenuOpen,
colorSelected,
} = this.state;
const isDisabled = annotationSelected.value === 'hand' || !annotations.length;
return ( return (
<ToolbarMenuItem <ToolbarMenuItem
disabled={isDisabled} disabled={isDisabled}
@ -498,18 +640,18 @@ class WhiteboardToolbar extends Component {
onItemClick={this.displaySubMenu} onItemClick={this.displaySubMenu}
objectToReturn="colorList" objectToReturn="colorList"
onBlur={this.closeSubMenu} onBlur={this.closeSubMenu}
className={cx(styles.toolbarButton, this.state.currentSubmenuOpen === 'colorList' ? styles.toolbarActive : null)} className={cx(styles.toolbarButton, currentSubmenuOpen === 'colorList' ? styles.toolbarActive : null)}
customIcon={this.renderColorItemIcon()} customIcon={this.renderColorItemIcon()}
> >
{this.state.currentSubmenuOpen === 'colorList' {currentSubmenuOpen === 'colorList'
? ( ? (
<ToolbarSubmenu <ToolbarSubmenu
type="color" type="color"
customIcon customIcon
label="Color" label="Color"
onItemClick={this.handleColorChange} onItemClick={this.handleColorChange}
objectsToRender={this.props.colors} objectsToRender={colors}
objectSelected={this.state.colorSelected} objectSelected={colorSelected}
handleMouseEnter={this.handleMouseEnter} handleMouseEnter={this.handleMouseEnter}
handleMouseLeave={this.handleMouseLeave} handleMouseLeave={this.handleMouseLeave}
/> />
@ -520,6 +662,11 @@ class WhiteboardToolbar extends Component {
} }
renderColorItemIcon() { renderColorItemIcon() {
const {
colorSelected,
prevColorSelected,
} = this.state;
return ( return (
<svg className={styles.customSvgIcon}> <svg className={styles.customSvgIcon}>
{isEdge {isEdge
@ -531,7 +678,7 @@ class WhiteboardToolbar extends Component {
height="50%" height="50%"
stroke="black" stroke="black"
strokeWidth="1" strokeWidth="1"
fill={this.state.colorSelected.value} fill={colorSelected.value}
/> />
) : ( ) : (
<rect x="25%" y="25%" width="50%" height="50%" stroke="black" strokeWidth="1"> <rect x="25%" y="25%" width="50%" height="50%" stroke="black" strokeWidth="1">
@ -539,8 +686,8 @@ class WhiteboardToolbar extends Component {
ref={(ref) => { this.colorListIconColor = ref; }} ref={(ref) => { this.colorListIconColor = ref; }}
attributeName="fill" attributeName="fill"
attributeType="XML" attributeType="XML"
from={this.state.prevColorSelected.value} from={prevColorSelected.value}
to={this.state.colorSelected.value} to={colorSelected.value}
begin="indefinite" begin="indefinite"
dur={TRANSITION_DURATION} dur={TRANSITION_DURATION}
repeatCount="0" repeatCount="0"