refactor: [UEPR-55] updated react-intl from v2 to v6

This commit is contained in:
MiroslavDionisiev 2024-09-20 15:39:22 +03:00
parent 5f12985de8
commit fed5087e9d
13 changed files with 476 additions and 343 deletions
package-lock.jsonpackage.json
src
components
color-picker
coming-soon
fixed-tools
mode-tools
paint-editor
tool-select-base
containers
lib
playground/reducers
test/__mocks__
webpack.config.js

206
package-lock.json generated
View file

@ -54,7 +54,7 @@
"raf": "3.4.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-intl": "2.9.0",
"react-intl": "^6.6.8",
"react-intl-redux": "2.4.1",
"react-popover": "0.5.10",
"react-redux": "5.1.2",
@ -83,7 +83,7 @@
"peerDependencies": {
"react": "^16",
"react-dom": "^16",
"react-intl": "^2",
"react-intl": "^6",
"react-intl-redux": "^0.7 || ^2.0.0",
"react-popover": "^0.5",
"react-redux": "^5",
@ -2829,6 +2829,100 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/@formatjs/ecma402-abstract": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.0.0.tgz",
"integrity": "sha512-rRqXOqdFmk7RYvj4khklyqzcfQl9vEL/usogncBHRZfZBDOwMGuSRNFl02fu5KGHXdbinju+YXyuR+Nk8xlr/g==",
"dev": true,
"dependencies": {
"@formatjs/intl-localematcher": "0.5.4",
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/fast-memoize": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.0.tgz",
"integrity": "sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==",
"dev": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/icu-messageformat-parser": {
"version": "2.7.8",
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.8.tgz",
"integrity": "sha512-nBZJYmhpcSX0WeJ5SDYUkZ42AgR3xiyhNCsQweFx3cz/ULJjym8bHAzWKvG5e2+1XO98dBYC0fWeeAECAVSwLA==",
"dev": true,
"dependencies": {
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/icu-skeleton-parser": "1.8.2",
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/icu-skeleton-parser": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.2.tgz",
"integrity": "sha512-k4ERKgw7aKGWJZgTarIcNEmvyTVD9FYh0mTrrBMHZ1b8hUu6iOJ4SzsZlo3UNAvHYa+PnvntIwRPt1/vy4nA9Q==",
"dev": true,
"dependencies": {
"@formatjs/ecma402-abstract": "2.0.0",
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/intl": {
"version": "2.10.4",
"resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.4.tgz",
"integrity": "sha512-56483O+HVcL0c7VucAS2tyH020mt9XTozZO67cwtGg0a7KWDukS/FzW3OnvaHmTHDuYsoPIzO+ZHVfU6fT/bJw==",
"dev": true,
"dependencies": {
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/fast-memoize": "2.2.0",
"@formatjs/icu-messageformat-parser": "2.7.8",
"@formatjs/intl-displaynames": "6.6.8",
"@formatjs/intl-listformat": "7.5.7",
"intl-messageformat": "10.5.14",
"tslib": "^2.4.0"
},
"peerDependencies": {
"typescript": "^4.7 || 5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@formatjs/intl-displaynames": {
"version": "6.6.8",
"resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.6.8.tgz",
"integrity": "sha512-Lgx6n5KxN16B3Pb05z3NLEBQkGoXnGjkTBNCZI+Cn17YjHJ3fhCeEJJUqRlIZmJdmaXQhjcQVDp6WIiNeRYT5g==",
"dev": true,
"dependencies": {
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/intl-localematcher": "0.5.4",
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/intl-listformat": {
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.5.7.tgz",
"integrity": "sha512-MG2TSChQJQT9f7Rlv+eXwUFiG24mKSzmF144PLb8m8OixyXqn4+YWU+5wZracZGCgVTVmx8viCf7IH3QXoiB2g==",
"dev": true,
"dependencies": {
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/intl-localematcher": "0.5.4",
"tslib": "^2.4.0"
}
},
"node_modules/@formatjs/intl-localematcher": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.4.tgz",
"integrity": "sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==",
"dev": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.14",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
@ -5482,6 +5576,16 @@
"@types/node": "*"
}
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
"dev": true,
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@ -5565,6 +5669,22 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.3.6",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.6.tgz",
"integrity": "sha512-CnGaRYNu2iZlkGXGrOYtdg5mLK8neySj0woZ4e2wF/eli2E6Sazmq5X+Nrj6OBrrFVQfJWTUFeqAzoRhWQXYvg==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@ -9183,6 +9303,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
},
"node_modules/cyclist": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz",
@ -14965,21 +15091,16 @@
"node": ">= 0.10"
}
},
"node_modules/intl-format-cache": {
"version": "2.2.9",
"resolved": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-2.2.9.tgz",
"integrity": "sha512-Zv/u8wRpekckv0cLkwpVdABYST4hZNTDaX7reFetrYTJwxExR2VyTqQm+l0WmL0Qo8Mjb9Tf33qnfj0T7pjxdQ==",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/intl-messageformat": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-2.2.0.tgz",
"integrity": "sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw==",
"version": "10.5.14",
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
"integrity": "sha512-IjC6sI0X7YRjjyVH9aUgdftcmZK7WXdHeil4KwbjDnRWjnVitKpAx3rr6t6di1joFp5188VqKcobOPA6mCLG/w==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"intl-messageformat-parser": "1.4.0"
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/fast-memoize": "2.2.0",
"@formatjs/icu-messageformat-parser": "2.7.8",
"tslib": "^2.4.0"
}
},
"node_modules/intl-messageformat-parser": {
@ -14990,25 +15111,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/intl-messageformat/node_modules/intl-messageformat-parser": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz",
"integrity": "sha512-/XkqFHKezO6UcF4Av2/Lzfrez18R0jyw7kRFhSeB/YRakdrgSc9QfFZUwNJI9swMwMoNPygK1ArC5wdFSjPw+A==",
"deprecated": "We've written a new parser that's 6x faster and is backwards compatible. Please use @formatjs/icu-messageformat-parser",
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/intl-relativeformat": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-2.2.0.tgz",
"integrity": "sha512-4bV/7kSKaPEmu6ArxXf9xjv1ny74Zkwuey8Pm01NH4zggPP7JHwg2STk8Y3JdspCKRDriwIyLRfEXnj2ZLr4Bw==",
"deprecated": "This package has been deprecated, please see migration guide at 'https://github.com/formatjs/formatjs/tree/master/packages/intl-relativeformat#migration-guide'",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"intl-messageformat": "^2.0.0"
}
},
"node_modules/into-stream": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz",
@ -26408,21 +26510,30 @@
}
},
"node_modules/react-intl": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.9.0.tgz",
"integrity": "sha512-27jnDlb/d2A7mSJwrbOBnUgD+rPep+abmoJE511Tf8BnoONIAUehy/U1zZCHGO17mnOwMWxqN4qC0nW11cD6rA==",
"version": "6.6.8",
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.6.8.tgz",
"integrity": "sha512-M0pkhzcgV31h++2901BiRXWl69hp2zPyLxRrSwRjd1ErXbNoubz/f4M6DrRTd4OiSUrT4ajRQzrmtS5plG4FtA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"hoist-non-react-statics": "^3.3.0",
"intl-format-cache": "^2.0.5",
"intl-messageformat": "^2.1.0",
"intl-relativeformat": "^2.1.0",
"invariant": "^2.1.1"
"@formatjs/ecma402-abstract": "2.0.0",
"@formatjs/icu-messageformat-parser": "2.7.8",
"@formatjs/intl": "2.10.4",
"@formatjs/intl-displaynames": "6.6.8",
"@formatjs/intl-listformat": "7.5.7",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/react": "16 || 17 || 18",
"hoist-non-react-statics": "^3.3.2",
"intl-messageformat": "10.5.14",
"tslib": "^2.4.0"
},
"peerDependencies": {
"prop-types": "^15.5.4",
"react": "^0.14.9 || ^15.0.0 || ^16.0.0"
"react": "^16.6.0 || 17 || 18",
"typescript": "^4.7 || 5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/react-intl-redux": {
@ -26430,7 +26541,6 @@
"resolved": "https://registry.npmjs.org/react-intl-redux/-/react-intl-redux-2.4.1.tgz",
"integrity": "sha512-EYTNmHJTnTam4phQj1nTdJvcdVjz+F56nLl6JtpqWsKzG5ZnQh/hoqLLJUjP0dgeNKSESIcjhYsTyBWDUwjo0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.17.9",
"prop-types": "^15.8.1"
@ -31912,6 +32022,12 @@
"node": ">=4"
}
},
"node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true
},
"node_modules/tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",

View file

@ -35,7 +35,7 @@
"peerDependencies": {
"react": "^16",
"react-dom": "^16",
"react-intl": "^2",
"react-intl": "^6",
"react-intl-redux": "^0.7 || ^2.0.0",
"react-popover": "^0.5",
"react-redux": "^5",
@ -81,7 +81,7 @@
"raf": "3.4.1",
"react": "16.14.0",
"react-dom": "16.14.0",
"react-intl": "2.9.0",
"react-intl": "^6.6.8",
"react-intl-redux": "2.4.1",
"react-popover": "0.5.10",
"react-redux": "5.1.2",
@ -121,7 +121,10 @@
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test/__mocks__/fileMock.js",
"\\.(css|less)$": "<rootDir>/test/__mocks__/styleMock.js"
}
},
"transformIgnorePatterns": [
"/node_modules/(?!intl-messageformat|intl-messageformat-parser).+\\.js$"
]
},
"jest-junit": {
"outputDirectory": "./test/results"

View file

@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl';
import {defineMessages, FormattedMessage, injectIntl} from 'react-intl';
import intlShape from '../../lib/intl-shape.js';
import classNames from 'classnames';
import parseColor from 'parse-color';

View file

@ -4,7 +4,8 @@ See #13 */
import bindAll from 'lodash.bindall';
import classNames from 'classnames';
import {defineMessages, injectIntl, intlShape, FormattedMessage} from 'react-intl';
import {defineMessages, injectIntl, FormattedMessage} from 'react-intl';
import intlShape from '../../lib/intl-shape.js';
import PropTypes from 'prop-types';
import React from 'react';
import ReactTooltip from 'react-tooltip';

View file

@ -11,7 +11,7 @@ import BufferedInputHOC from '../forms/buffered-input-hoc.jsx';
import Button from '../button/button.jsx';
import ButtonGroup from '../button-group/button-group.jsx';
import Dropdown from '../dropdown/dropdown.jsx';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {defineMessages, useIntl} from 'react-intl';
import Formats, {isVector} from '../../lib/format';
import Input from '../forms/input.jsx';
import InputGroup from '../input-group/input-group.jsx';
@ -87,13 +87,14 @@ const messages = defineMessages({
const FixedToolsComponent = props => {
const redoDisabled = !props.canRedo();
const undoDisabled = !props.canUndo();
const intl = useIntl();
return (
<div className={styles.row}>
{/* Name field */}
<InputGroup>
<MediaQuery minWidth={layout.fullSizeEditorMinWidth}>
<Label text={props.intl.formatMessage(messages.costume)}>
<Label text={intl.formatMessage(messages.costume)}>
<BufferedInput
className={styles.costumeInput}
type="text"
@ -128,7 +129,7 @@ const FixedToolsComponent = props => {
onClick={props.onUndo}
>
<img
alt={props.intl.formatMessage(messages.undo)}
alt={intl.formatMessage(messages.undo)}
className={classNames(
styles.buttonGroupButtonIcon,
styles.undoIcon
@ -150,7 +151,7 @@ const FixedToolsComponent = props => {
onClick={props.onRedo}
>
<img
alt={props.intl.formatMessage(messages.redo)}
alt={intl.formatMessage(messages.redo)}
className={styles.buttonGroupButtonIcon}
draggable={false}
src={redoIcon}
@ -164,16 +165,16 @@ const FixedToolsComponent = props => {
<InputGroup className={styles.modDashedBorder}>
<LabeledIconButton
disabled={!shouldShowGroup()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={groupIcon}
title={props.intl.formatMessage(messages.group)}
title={intl.formatMessage(messages.group)}
onClick={props.onGroup}
/>
<LabeledIconButton
disabled={!shouldShowUngroup()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={ungroupIcon}
title={props.intl.formatMessage(messages.ungroup)}
title={intl.formatMessage(messages.ungroup)}
onClick={props.onUngroup}
/>
</InputGroup> : null
@ -184,16 +185,16 @@ const FixedToolsComponent = props => {
<InputGroup className={styles.modDashedBorder}>
<LabeledIconButton
disabled={!shouldShowBringForward()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={sendForwardIcon}
title={props.intl.formatMessage(messages.forward)}
title={intl.formatMessage(messages.forward)}
onClick={props.onSendForward}
/>
<LabeledIconButton
disabled={!shouldShowSendBackward()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={sendBackwardIcon}
title={props.intl.formatMessage(messages.backward)}
title={intl.formatMessage(messages.backward)}
onClick={props.onSendBackward}
/>
</InputGroup> : null
@ -204,16 +205,16 @@ const FixedToolsComponent = props => {
<InputGroup className={styles.row}>
<LabeledIconButton
disabled={!shouldShowBringForward()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={sendFrontIcon}
title={props.intl.formatMessage(messages.front)}
title={intl.formatMessage(messages.front)}
onClick={props.onSendToFront}
/>
<LabeledIconButton
disabled={!shouldShowSendBackward()}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={sendBackIcon}
title={props.intl.formatMessage(messages.back)}
title={intl.formatMessage(messages.back)}
onClick={props.onSendToBack}
/>
</InputGroup>
@ -252,7 +253,7 @@ const FixedToolsComponent = props => {
draggable={false}
src={sendFrontIcon}
/>
<span>{props.intl.formatMessage(messages.front)}</span>
<span>{intl.formatMessage(messages.front)}</span>
</Button>
<Button
className={classNames(styles.modMenuItem, {
@ -266,7 +267,7 @@ const FixedToolsComponent = props => {
draggable={false}
src={sendBackIcon}
/>
<span>{props.intl.formatMessage(messages.back)}</span>
<span>{intl.formatMessage(messages.back)}</span>
</Button>
{/* To be rotation point */}
@ -285,7 +286,7 @@ const FixedToolsComponent = props => {
}
tipSize={.01}
>
{props.intl.formatMessage(messages.more)}
{intl.formatMessage(messages.more)}
</Dropdown>
</InputGroup>
</MediaQuery> : null
@ -298,7 +299,6 @@ FixedToolsComponent.propTypes = {
canRedo: PropTypes.func.isRequired,
canUndo: PropTypes.func.isRequired,
format: PropTypes.oneOf(Object.keys(Formats)),
intl: intlShape,
name: PropTypes.string,
onGroup: PropTypes.func.isRequired,
onRedo: PropTypes.func.isRequired,
@ -321,4 +321,4 @@ const mapStateToProps = state => ({
export default connect(
mapStateToProps
)(injectIntl(FixedToolsComponent));
)(FixedToolsComponent);

View file

@ -12,7 +12,7 @@ import {setShapesFilled} from '../../reducers/fill-bitmap-shapes';
import FontDropdown from '../../containers/font-dropdown.jsx';
import LiveInputHOC from '../forms/live-input-hoc.jsx';
import Label from '../forms/label.jsx';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {defineMessages, useIntl} from 'react-intl';
import Input from '../forms/input.jsx';
import InputGroup from '../input-group/input-group.jsx';
import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
@ -43,6 +43,7 @@ import {MAX_STROKE_WIDTH} from '../../reducers/stroke-width';
const LiveInput = LiveInputHOC(Input);
const ModeToolsComponent = props => {
const intl = useIntl();
const messages = defineMessages({
brushSize: {
defaultMessage: 'Size',
@ -122,7 +123,7 @@ const ModeToolsComponent = props => {
<div className={classNames(props.className, styles.modeTools)}>
<div>
<img
alt={props.intl.formatMessage(currentMessage)}
alt={intl.formatMessage(currentMessage)}
className={styles.modeToolsIcon}
draggable={false}
src={currentIcon}
@ -151,7 +152,7 @@ const ModeToolsComponent = props => {
<div className={classNames(props.className, styles.modeTools)}>
<div>
<img
alt={props.intl.formatMessage(messages.eraserSize)}
alt={intl.formatMessage(messages.eraserSize)}
className={styles.modeToolsIcon}
draggable={false}
src={currentIcon}
@ -175,24 +176,24 @@ const ModeToolsComponent = props => {
<InputGroup className={classNames(styles.modDashedBorder, styles.modLabeledIconHeight)}>
<LabeledIconButton
disabled={!props.hasSelectedUncurvedPoints}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={curvedPointIcon}
title={props.intl.formatMessage(messages.curved)}
title={intl.formatMessage(messages.curved)}
onClick={props.onCurvePoints}
/>
<LabeledIconButton
disabled={!props.hasSelectedUnpointedPoints}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={straightPointIcon}
title={props.intl.formatMessage(messages.pointed)}
title={intl.formatMessage(messages.pointed)}
onClick={props.onPointPoints}
/>
</InputGroup>
<InputGroup className={classNames(styles.modLabeledIconHeight)}>
<LabeledIconButton
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={deleteIcon}
title={props.intl.formatMessage(messages.delete)}
title={intl.formatMessage(messages.delete)}
onClick={props.onDelete}
/>
</InputGroup>
@ -205,38 +206,38 @@ const ModeToolsComponent = props => {
<div className={classNames(props.className, styles.modeTools)}>
<InputGroup className={classNames(styles.modDashedBorder, styles.modLabeledIconHeight)}>
<LabeledIconButton
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={copyIcon}
title={props.intl.formatMessage(messages.copy)}
title={intl.formatMessage(messages.copy)}
onClick={props.onCopyToClipboard}
/>
<LabeledIconButton
disabled={!(props.clipboardItems.length > 0)}
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={pasteIcon}
title={props.intl.formatMessage(messages.paste)}
title={intl.formatMessage(messages.paste)}
onClick={props.onPasteFromClipboard}
/>
</InputGroup>
<InputGroup className={classNames(styles.modDashedBorder, styles.modLabeledIconHeight)}>
<LabeledIconButton
hideLabel={hideLabel(props.intl.locale)}
hideLabel={hideLabel(intl.locale)}
imgSrc={deleteIcon}
title={props.intl.formatMessage(messages.delete)}
title={intl.formatMessage(messages.delete)}
onClick={props.onDelete}
/>
</InputGroup>
<InputGroup className={classNames(styles.modLabeledIconHeight)}>
<LabeledIconButton
hideLabel={props.intl.locale !== 'en'}
hideLabel={intl.locale !== 'en'}
imgSrc={flipHorizontalIcon}
title={props.intl.formatMessage(messages.flipHorizontal)}
title={intl.formatMessage(messages.flipHorizontal)}
onClick={props.onFlipHorizontal}
/>
<LabeledIconButton
hideLabel={props.intl.locale !== 'en'}
hideLabel={intl.locale !== 'en'}
imgSrc={flipVerticalIcon}
title={props.intl.formatMessage(messages.flipVertical)}
title={intl.formatMessage(messages.flipVertical)}
onClick={props.onFlipVertical}
/>
</InputGroup>
@ -266,7 +267,7 @@ const ModeToolsComponent = props => {
<LabeledIconButton
highlighted={props.fillBitmapShapes}
imgSrc={fillIcon}
title={props.intl.formatMessage(messages.filled)}
title={intl.formatMessage(messages.filled)}
onClick={props.onFillShapes}
/>
</InputGroup>
@ -274,13 +275,13 @@ const ModeToolsComponent = props => {
<LabeledIconButton
highlighted={!props.fillBitmapShapes}
imgSrc={outlineIcon}
title={props.intl.formatMessage(messages.outlined)}
title={intl.formatMessage(messages.outlined)}
onClick={props.onOutlineShapes}
/>
</InputGroup>
{props.fillBitmapShapes ? null : (
<InputGroup>
<Label text={props.intl.formatMessage(messages.thickness)}>
<Label text={intl.formatMessage(messages.thickness)}>
<LiveInput
range
small
@ -315,7 +316,6 @@ ModeToolsComponent.propTypes = {
format: PropTypes.oneOf(Object.keys(Formats)),
hasSelectedUncurvedPoints: PropTypes.bool,
hasSelectedUnpointedPoints: PropTypes.bool,
intl: intlShape.isRequired,
mode: PropTypes.string.isRequired,
onBitBrushSliderChange: PropTypes.func.isRequired,
onBitEraserSliderChange: PropTypes.func.isRequired,
@ -367,4 +367,4 @@ const mapDispatchToProps = dispatch => ({
export default connect(
mapStateToProps,
mapDispatchToProps
)(injectIntl(ModeToolsComponent));
)(ModeToolsComponent);

View file

@ -1,6 +1,6 @@
import paper from '@scratch/paper';
import classNames from 'classnames';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import {defineMessages, useIntl} from 'react-intl';
import React from 'react';
import PropTypes from 'prop-types';
@ -55,56 +55,29 @@ const messages = defineMessages({
}
});
const PaintEditorComponent = props => (
<div
className={styles.editorContainer}
dir={props.rtl ? 'rtl' : 'ltr'}
>
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
<div className={styles.editorContainerTop}>
{/* First row */}
<div className={styles.row}>
<FixedToolsContainer
canRedo={props.canRedo}
canUndo={props.canUndo}
name={props.name}
onRedo={props.onRedo}
onUndo={props.onUndo}
onUpdateImage={props.onUpdateImage}
onUpdateName={props.onUpdateName}
/>
</div>
{/* Second Row */}
{isVector(props.format) ?
const PaintEditorComponent = props => {
const intl = useIntl();
return (
<div
className={styles.editorContainer}
dir={props.rtl ? 'rtl' : 'ltr'}
>
{props.canvas !== null ? ( // eslint-disable-line no-negated-condition
<div className={styles.editorContainerTop}>
{/* First row */}
<div className={styles.row}>
<InputGroup
className={classNames(
styles.row,
styles.modDashedBorder,
styles.modLabeledIconHeight
)}
>
{/* fill */}
<FillColorIndicatorComponent
className={styles.modMarginAfter}
onUpdateImage={props.onUpdateImage}
/>
{/* stroke */}
<StrokeColorIndicatorComponent
onUpdateImage={props.onUpdateImage}
/>
{/* stroke width */}
<StrokeWidthIndicatorComponent
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
<InputGroup className={styles.modModeTools}>
<ModeToolsContainer
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
</div> :
isBitmap(props.format) ?
<FixedToolsContainer
canRedo={props.canRedo}
canUndo={props.canUndo}
name={props.name}
onRedo={props.onRedo}
onUndo={props.onUndo}
onUpdateImage={props.onUpdateImage}
onUpdateName={props.onUpdateName}
/>
</div>
{/* Second Row */}
{isVector(props.format) ?
<div className={styles.row}>
<InputGroup
className={classNames(
@ -118,136 +91,151 @@ const PaintEditorComponent = props => (
className={styles.modMarginAfter}
onUpdateImage={props.onUpdateImage}
/>
{/* stroke */}
<StrokeColorIndicatorComponent
onUpdateImage={props.onUpdateImage}
/>
{/* stroke width */}
<StrokeWidthIndicatorComponent
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
<InputGroup className={styles.modModeTools}>
<ModeToolsContainer
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
</div> : null
}
</div>
) : null}
<div className={styles.topAlignRow}>
{/* Modes */}
{props.canvas !== null && isVector(props.format) ? ( // eslint-disable-line no-negated-condition
<div className={styles.modeSelector}>
<SelectMode
onUpdateImage={props.onUpdateImage}
/>
<ReshapeMode
onUpdateImage={props.onUpdateImage}
/>
<BrushMode
onUpdateImage={props.onUpdateImage}
/>
<EraserMode
onUpdateImage={props.onUpdateImage}
/>
<FillMode
onUpdateImage={props.onUpdateImage}
/>
<TextMode
textArea={props.textArea}
onUpdateImage={props.onUpdateImage}
/>
<LineMode
onUpdateImage={props.onUpdateImage}
/>
<OvalMode
onUpdateImage={props.onUpdateImage}
/>
<RectMode
onUpdateImage={props.onUpdateImage}
/>
</div>
) : null}
{props.canvas !== null && isBitmap(props.format) ? ( // eslint-disable-line no-negated-condition
<div className={styles.modeSelector}>
<BitBrushMode
onUpdateImage={props.onUpdateImage}
/>
<BitLineMode
onUpdateImage={props.onUpdateImage}
/>
<BitOvalMode
onUpdateImage={props.onUpdateImage}
/>
<BitRectMode
onUpdateImage={props.onUpdateImage}
/>
<TextMode
isBitmap
textArea={props.textArea}
onUpdateImage={props.onUpdateImage}
/>
<BitFillMode
onUpdateImage={props.onUpdateImage}
/>
<BitEraserMode
onUpdateImage={props.onUpdateImage}
/>
<BitSelectMode
onUpdateImage={props.onUpdateImage}
/>
</div>
) : null}
<div className={styles.controlsContainer}>
{/* Canvas */}
<ScrollableCanvas
canvas={props.canvas}
hideScrollbars={props.isEyeDropping}
style={styles.canvasContainer}
>
<PaperCanvas
canvasRef={props.setCanvas}
image={props.image}
imageFormat={props.imageFormat}
imageId={props.imageId}
rotationCenterX={props.rotationCenterX}
rotationCenterY={props.rotationCenterY}
zoomLevelId={props.zoomLevelId}
onUpdateImage={props.onUpdateImage}
/>
<textarea
className={styles.textArea}
ref={props.setTextArea}
spellCheck={false}
/>
{props.isEyeDropping &&
props.colorInfo !== null &&
!props.colorInfo.hideLoupe ? (
<Box className={styles.colorPickerWrapper}>
<Loupe
colorInfo={props.colorInfo}
pixelRatio={paper.project.view.pixelRatio}
/>
</Box>
) : null
}
</ScrollableCanvas>
<div className={styles.canvasControls}>
{isVector(props.format) ?
<Button
className={styles.bitmapButton}
onClick={props.onSwitchToBitmap}
>
<img
className={styles.bitmapButtonIcon}
draggable={false}
src={bitmapIcon}
/>
<span className={styles.buttonText}>
{props.intl.formatMessage(messages.bitmap)}
</span>
</Button> :
</div> :
isBitmap(props.format) ?
<div className={styles.row}>
<InputGroup
className={classNames(
styles.row,
styles.modDashedBorder,
styles.modLabeledIconHeight
)}
>
{/* fill */}
<FillColorIndicatorComponent
className={styles.modMarginAfter}
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
<InputGroup className={styles.modModeTools}>
<ModeToolsContainer
onUpdateImage={props.onUpdateImage}
/>
</InputGroup>
</div> : null
}
</div>
) : null}
<div className={styles.topAlignRow}>
{/* Modes */}
{props.canvas !== null && isVector(props.format) ? ( // eslint-disable-line no-negated-condition
<div className={styles.modeSelector}>
<SelectMode
onUpdateImage={props.onUpdateImage}
/>
<ReshapeMode
onUpdateImage={props.onUpdateImage}
/>
<BrushMode
onUpdateImage={props.onUpdateImage}
/>
<EraserMode
onUpdateImage={props.onUpdateImage}
/>
<FillMode
onUpdateImage={props.onUpdateImage}
/>
<TextMode
textArea={props.textArea}
onUpdateImage={props.onUpdateImage}
/>
<LineMode
onUpdateImage={props.onUpdateImage}
/>
<OvalMode
onUpdateImage={props.onUpdateImage}
/>
<RectMode
onUpdateImage={props.onUpdateImage}
/>
</div>
) : null}
{props.canvas !== null && isBitmap(props.format) ? ( // eslint-disable-line no-negated-condition
<div className={styles.modeSelector}>
<BitBrushMode
onUpdateImage={props.onUpdateImage}
/>
<BitLineMode
onUpdateImage={props.onUpdateImage}
/>
<BitOvalMode
onUpdateImage={props.onUpdateImage}
/>
<BitRectMode
onUpdateImage={props.onUpdateImage}
/>
<TextMode
isBitmap
textArea={props.textArea}
onUpdateImage={props.onUpdateImage}
/>
<BitFillMode
onUpdateImage={props.onUpdateImage}
/>
<BitEraserMode
onUpdateImage={props.onUpdateImage}
/>
<BitSelectMode
onUpdateImage={props.onUpdateImage}
/>
</div>
) : null}
<div className={styles.controlsContainer}>
{/* Canvas */}
<ScrollableCanvas
canvas={props.canvas}
hideScrollbars={props.isEyeDropping}
style={styles.canvasContainer}
>
<PaperCanvas
canvasRef={props.setCanvas}
image={props.image}
imageFormat={props.imageFormat}
imageId={props.imageId}
rotationCenterX={props.rotationCenterX}
rotationCenterY={props.rotationCenterY}
zoomLevelId={props.zoomLevelId}
onUpdateImage={props.onUpdateImage}
/>
<textarea
className={styles.textArea}
ref={props.setTextArea}
spellCheck={false}
/>
{props.isEyeDropping &&
props.colorInfo !== null &&
!props.colorInfo.hideLoupe ? (
<Box className={styles.colorPickerWrapper}>
<Loupe
colorInfo={props.colorInfo}
pixelRatio={paper.project.view.pixelRatio}
/>
</Box>
) : null
}
</ScrollableCanvas>
<div className={styles.canvasControls}>
{isVector(props.format) ?
<Button
className={styles.bitmapButton}
onClick={props.onSwitchToVector}
onClick={props.onSwitchToBitmap}
>
<img
className={styles.bitmapButtonIcon}
@ -255,53 +243,68 @@ const PaintEditorComponent = props => (
src={bitmapIcon}
/>
<span className={styles.buttonText}>
{props.intl.formatMessage(messages.vector)}
{intl.formatMessage(messages.bitmap)}
</span>
</Button> : null
}
{/* Zoom controls */}
<InputGroup className={styles.zoomControls}>
<ButtonGroup>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomOut}
>
<img
alt="Zoom Out"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomOutIcon}
/>
</Button>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomReset}
>
<img
alt="Zoom Reset"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomResetIcon}
/>
</Button>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomIn}
>
<img
alt="Zoom In"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomInIcon}
/>
</Button>
</ButtonGroup>
</InputGroup>
</Button> :
isBitmap(props.format) ?
<Button
className={styles.bitmapButton}
onClick={props.onSwitchToVector}
>
<img
className={styles.bitmapButtonIcon}
draggable={false}
src={bitmapIcon}
/>
<span className={styles.buttonText}>
{intl.formatMessage(messages.vector)}
</span>
</Button> : null
}
{/* Zoom controls */}
<InputGroup className={styles.zoomControls}>
<ButtonGroup>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomOut}
>
<img
alt="Zoom Out"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomOutIcon}
/>
</Button>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomReset}
>
<img
alt="Zoom Reset"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomResetIcon}
/>
</Button>
<Button
className={styles.buttonGroupButton}
onClick={props.onZoomIn}
>
<img
alt="Zoom In"
className={styles.buttonGroupButtonIcon}
draggable={false}
src={zoomInIcon}
/>
</Button>
</ButtonGroup>
</InputGroup>
</div>
</div>
</div>
</div>
</div>
);
);
};
PaintEditorComponent.propTypes = {
canRedo: PropTypes.func.isRequired,
@ -315,7 +318,6 @@ PaintEditorComponent.propTypes = {
]),
imageFormat: PropTypes.string,
imageId: PropTypes.string,
intl: intlShape,
isEyeDropping: PropTypes.bool,
name: PropTypes.string,
onRedo: PropTypes.func.isRequired,
@ -336,4 +338,4 @@ PaintEditorComponent.propTypes = {
zoomLevelId: PropTypes.string
};
export default injectIntl(PaintEditorComponent);
export default PaintEditorComponent;

View file

@ -1,31 +1,34 @@
import classNames from 'classnames';
import React from 'react';
import PropTypes from 'prop-types';
import {injectIntl, intlShape} from 'react-intl';
import {useIntl} 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.modToolSelect, {
[styles.isSelected]: props.isSelected
})
}
disabled={props.disabled}
title={props.intl.formatMessage(props.imgDescriptor)}
onClick={props.onMouseDown}
>
<img
alt={props.intl.formatMessage(props.imgDescriptor)}
className={styles.toolSelectIcon}
draggable={false}
src={props.imgSrc}
/>
</Button>
);
const ToolSelectComponent = props => {
const intl = useIntl();
return (
<Button
className={
classNames(props.className, styles.modToolSelect, {
[styles.isSelected]: props.isSelected
})
}
disabled={props.disabled}
title={intl.formatMessage(props.imgDescriptor)}
onClick={props.onMouseDown}
>
<img
alt={intl.formatMessage(props.imgDescriptor)}
className={styles.toolSelectIcon}
draggable={false}
src={props.imgSrc}
/>
</Button>
);
};
ToolSelectComponent.propTypes = {
className: PropTypes.string,
@ -36,9 +39,8 @@ ToolSelectComponent.propTypes = {
id: PropTypes.string
}).isRequired,
imgSrc: PropTypes.string.isRequired,
intl: intlShape.isRequired,
isSelected: PropTypes.bool.isRequired,
onMouseDown: PropTypes.func.isRequired
};
export default injectIntl(ToolSelectComponent);
export default ToolSelectComponent;

View file

@ -2,7 +2,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import bindAll from 'lodash.bindall';
import parseColor from 'parse-color';
import {injectIntl, intlShape} from 'react-intl';
import {injectIntl} from 'react-intl';
import intlShape from '../lib/intl-shape.js';
import {getSelectedLeafItems} from '../helper/selection';
import Formats, {isBitmap} from '../lib/format';

10
src/lib/intl-shape.js Normal file
View file

@ -0,0 +1,10 @@
import PropTypes from 'prop-types';
// intlShape was removed in react-intl@3 and replaced with a TypeScript interface.
// These are some of the commonly used properties from the intl object.
const intlShape = PropTypes.shape({
locale: PropTypes.string.isRequired,
formatMessage: PropTypes.func.isRequired
});
export default intlShape;

View file

@ -1,15 +1,8 @@
import {addLocaleData} from 'react-intl';
import {updateIntl as superUpdateIntl} from 'react-intl-redux';
import {IntlProvider, intlReducer} from 'react-intl-redux';
import localeData from 'scratch-l10n';
import paintMessages from 'scratch-l10n/locales/paint-editor-msgs';
Object.keys(localeData).forEach(locale => {
// TODO: will need to handle locales not in the default intl - see www/custom-locales
addLocaleData(localeData[locale].localeData);
});
const intlInitialState = {
intl: {
defaultLocale: 'en',

View file

@ -11,7 +11,6 @@ const intl = {
formatRelative: ({defaultMessage}) => defaultMessage,
formatNumber: ({defaultMessage}) => defaultMessage,
formatPlural: ({defaultMessage}) => defaultMessage,
formatHTMLMessage: ({defaultMessage}) => defaultMessage,
now: () => 0
};

View file

@ -17,7 +17,12 @@ const base = {
rules: [{
test: /\.jsx?$/,
loader: 'babel-loader',
include: path.resolve(__dirname, 'src'),
include: [
path.resolve(__dirname, 'src'),
path.join(__dirname, 'node_modules/react-intl'),
path.join(__dirname, 'node_modules/intl-messageformat'),
path.join(__dirname, 'node_modules/intl-messageformat-parser')
],
options: {
plugins: ['transform-object-rest-spread'],
presets: [