mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2025-06-12 05:02:54 -04:00
refactor: [UEPR-55] updated react-intl from v2 to v6
This commit is contained in:
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
206
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
10
src/lib/intl-shape.js
Normal 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;
|
|
@ -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',
|
||||
|
|
1
test/__mocks__/react-intl.js
vendored
1
test/__mocks__/react-intl.js
vendored
|
@ -11,7 +11,6 @@ const intl = {
|
|||
formatRelative: ({defaultMessage}) => defaultMessage,
|
||||
formatNumber: ({defaultMessage}) => defaultMessage,
|
||||
formatPlural: ({defaultMessage}) => defaultMessage,
|
||||
formatHTMLMessage: ({defaultMessage}) => defaultMessage,
|
||||
now: () => 0
|
||||
};
|
||||
|
||||
|
|
|
@ -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: [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue