scratch-paint 3.0.339 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import paper from '@scratch/paper';
2
2
  import classNames from 'classnames';
3
- import {defineMessages, injectIntl, intlShape} from 'react-intl';
3
+ import {defineMessages, useIntl} from 'react-intl';
4
4
  import React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
 
@@ -55,56 +55,29 @@ const messages = defineMessages({
55
55
  }
56
56
  });
57
57
 
58
- const PaintEditorComponent = props => (
59
- <div
60
- className={styles.editorContainer}
61
- dir={props.rtl ? 'rtl' : 'ltr'}
62
- >
63
- {props.canvas !== null ? ( // eslint-disable-line no-negated-condition
64
- <div className={styles.editorContainerTop}>
65
- {/* First row */}
66
- <div className={styles.row}>
67
- <FixedToolsContainer
68
- canRedo={props.canRedo}
69
- canUndo={props.canUndo}
70
- name={props.name}
71
- onRedo={props.onRedo}
72
- onUndo={props.onUndo}
73
- onUpdateImage={props.onUpdateImage}
74
- onUpdateName={props.onUpdateName}
75
- />
76
- </div>
77
- {/* Second Row */}
78
- {isVector(props.format) ?
58
+ const PaintEditorComponent = props => {
59
+ const intl = useIntl();
60
+ return (
61
+ <div
62
+ className={styles.editorContainer}
63
+ dir={props.rtl ? 'rtl' : 'ltr'}
64
+ >
65
+ {props.canvas !== null ? ( // eslint-disable-line no-negated-condition
66
+ <div className={styles.editorContainerTop}>
67
+ {/* First row */}
79
68
  <div className={styles.row}>
80
- <InputGroup
81
- className={classNames(
82
- styles.row,
83
- styles.modDashedBorder,
84
- styles.modLabeledIconHeight
85
- )}
86
- >
87
- {/* fill */}
88
- <FillColorIndicatorComponent
89
- className={styles.modMarginAfter}
90
- onUpdateImage={props.onUpdateImage}
91
- />
92
- {/* stroke */}
93
- <StrokeColorIndicatorComponent
94
- onUpdateImage={props.onUpdateImage}
95
- />
96
- {/* stroke width */}
97
- <StrokeWidthIndicatorComponent
98
- onUpdateImage={props.onUpdateImage}
99
- />
100
- </InputGroup>
101
- <InputGroup className={styles.modModeTools}>
102
- <ModeToolsContainer
103
- onUpdateImage={props.onUpdateImage}
104
- />
105
- </InputGroup>
106
- </div> :
107
- isBitmap(props.format) ?
69
+ <FixedToolsContainer
70
+ canRedo={props.canRedo}
71
+ canUndo={props.canUndo}
72
+ name={props.name}
73
+ onRedo={props.onRedo}
74
+ onUndo={props.onUndo}
75
+ onUpdateImage={props.onUpdateImage}
76
+ onUpdateName={props.onUpdateName}
77
+ />
78
+ </div>
79
+ {/* Second Row */}
80
+ {isVector(props.format) ?
108
81
  <div className={styles.row}>
109
82
  <InputGroup
110
83
  className={classNames(
@@ -118,136 +91,151 @@ const PaintEditorComponent = props => (
118
91
  className={styles.modMarginAfter}
119
92
  onUpdateImage={props.onUpdateImage}
120
93
  />
94
+ {/* stroke */}
95
+ <StrokeColorIndicatorComponent
96
+ onUpdateImage={props.onUpdateImage}
97
+ />
98
+ {/* stroke width */}
99
+ <StrokeWidthIndicatorComponent
100
+ onUpdateImage={props.onUpdateImage}
101
+ />
121
102
  </InputGroup>
122
103
  <InputGroup className={styles.modModeTools}>
123
104
  <ModeToolsContainer
124
105
  onUpdateImage={props.onUpdateImage}
125
106
  />
126
107
  </InputGroup>
127
- </div> : null
128
- }
129
- </div>
130
- ) : null}
131
-
132
- <div className={styles.topAlignRow}>
133
- {/* Modes */}
134
- {props.canvas !== null && isVector(props.format) ? ( // eslint-disable-line no-negated-condition
135
- <div className={styles.modeSelector}>
136
- <SelectMode
137
- onUpdateImage={props.onUpdateImage}
138
- />
139
- <ReshapeMode
140
- onUpdateImage={props.onUpdateImage}
141
- />
142
- <BrushMode
143
- onUpdateImage={props.onUpdateImage}
144
- />
145
- <EraserMode
146
- onUpdateImage={props.onUpdateImage}
147
- />
148
- <FillMode
149
- onUpdateImage={props.onUpdateImage}
150
- />
151
- <TextMode
152
- textArea={props.textArea}
153
- onUpdateImage={props.onUpdateImage}
154
- />
155
- <LineMode
156
- onUpdateImage={props.onUpdateImage}
157
- />
158
- <OvalMode
159
- onUpdateImage={props.onUpdateImage}
160
- />
161
- <RectMode
162
- onUpdateImage={props.onUpdateImage}
163
- />
108
+ </div> :
109
+ isBitmap(props.format) ?
110
+ <div className={styles.row}>
111
+ <InputGroup
112
+ className={classNames(
113
+ styles.row,
114
+ styles.modDashedBorder,
115
+ styles.modLabeledIconHeight
116
+ )}
117
+ >
118
+ {/* fill */}
119
+ <FillColorIndicatorComponent
120
+ className={styles.modMarginAfter}
121
+ onUpdateImage={props.onUpdateImage}
122
+ />
123
+ </InputGroup>
124
+ <InputGroup className={styles.modModeTools}>
125
+ <ModeToolsContainer
126
+ onUpdateImage={props.onUpdateImage}
127
+ />
128
+ </InputGroup>
129
+ </div> : null
130
+ }
164
131
  </div>
165
132
  ) : null}
166
133
 
167
- {props.canvas !== null && isBitmap(props.format) ? ( // eslint-disable-line no-negated-condition
168
- <div className={styles.modeSelector}>
169
- <BitBrushMode
170
- onUpdateImage={props.onUpdateImage}
171
- />
172
- <BitLineMode
173
- onUpdateImage={props.onUpdateImage}
174
- />
175
- <BitOvalMode
176
- onUpdateImage={props.onUpdateImage}
177
- />
178
- <BitRectMode
179
- onUpdateImage={props.onUpdateImage}
180
- />
181
- <TextMode
182
- isBitmap
183
- textArea={props.textArea}
184
- onUpdateImage={props.onUpdateImage}
185
- />
186
- <BitFillMode
187
- onUpdateImage={props.onUpdateImage}
188
- />
189
- <BitEraserMode
190
- onUpdateImage={props.onUpdateImage}
191
- />
192
- <BitSelectMode
193
- onUpdateImage={props.onUpdateImage}
194
- />
195
- </div>
196
- ) : null}
134
+ <div className={styles.topAlignRow}>
135
+ {/* Modes */}
136
+ {props.canvas !== null && isVector(props.format) ? ( // eslint-disable-line no-negated-condition
137
+ <div className={styles.modeSelector}>
138
+ <SelectMode
139
+ onUpdateImage={props.onUpdateImage}
140
+ />
141
+ <ReshapeMode
142
+ onUpdateImage={props.onUpdateImage}
143
+ />
144
+ <BrushMode
145
+ onUpdateImage={props.onUpdateImage}
146
+ />
147
+ <EraserMode
148
+ onUpdateImage={props.onUpdateImage}
149
+ />
150
+ <FillMode
151
+ onUpdateImage={props.onUpdateImage}
152
+ />
153
+ <TextMode
154
+ textArea={props.textArea}
155
+ onUpdateImage={props.onUpdateImage}
156
+ />
157
+ <LineMode
158
+ onUpdateImage={props.onUpdateImage}
159
+ />
160
+ <OvalMode
161
+ onUpdateImage={props.onUpdateImage}
162
+ />
163
+ <RectMode
164
+ onUpdateImage={props.onUpdateImage}
165
+ />
166
+ </div>
167
+ ) : null}
197
168
 
198
- <div className={styles.controlsContainer}>
199
- {/* Canvas */}
200
- <ScrollableCanvas
201
- canvas={props.canvas}
202
- hideScrollbars={props.isEyeDropping}
203
- style={styles.canvasContainer}
204
- >
205
- <PaperCanvas
206
- canvasRef={props.setCanvas}
207
- image={props.image}
208
- imageFormat={props.imageFormat}
209
- imageId={props.imageId}
210
- rotationCenterX={props.rotationCenterX}
211
- rotationCenterY={props.rotationCenterY}
212
- zoomLevelId={props.zoomLevelId}
213
- onUpdateImage={props.onUpdateImage}
214
- />
215
- <textarea
216
- className={styles.textArea}
217
- ref={props.setTextArea}
218
- spellCheck={false}
219
- />
220
- {props.isEyeDropping &&
221
- props.colorInfo !== null &&
222
- !props.colorInfo.hideLoupe ? (
223
- <Box className={styles.colorPickerWrapper}>
224
- <Loupe
225
- colorInfo={props.colorInfo}
226
- pixelRatio={paper.project.view.pixelRatio}
227
- />
228
- </Box>
229
- ) : null
230
- }
231
- </ScrollableCanvas>
232
- <div className={styles.canvasControls}>
233
- {isVector(props.format) ?
234
- <Button
235
- className={styles.bitmapButton}
236
- onClick={props.onSwitchToBitmap}
237
- >
238
- <img
239
- className={styles.bitmapButtonIcon}
240
- draggable={false}
241
- src={bitmapIcon}
242
- />
243
- <span className={styles.buttonText}>
244
- {props.intl.formatMessage(messages.bitmap)}
245
- </span>
246
- </Button> :
247
- isBitmap(props.format) ?
169
+ {props.canvas !== null && isBitmap(props.format) ? ( // eslint-disable-line no-negated-condition
170
+ <div className={styles.modeSelector}>
171
+ <BitBrushMode
172
+ onUpdateImage={props.onUpdateImage}
173
+ />
174
+ <BitLineMode
175
+ onUpdateImage={props.onUpdateImage}
176
+ />
177
+ <BitOvalMode
178
+ onUpdateImage={props.onUpdateImage}
179
+ />
180
+ <BitRectMode
181
+ onUpdateImage={props.onUpdateImage}
182
+ />
183
+ <TextMode
184
+ isBitmap
185
+ textArea={props.textArea}
186
+ onUpdateImage={props.onUpdateImage}
187
+ />
188
+ <BitFillMode
189
+ onUpdateImage={props.onUpdateImage}
190
+ />
191
+ <BitEraserMode
192
+ onUpdateImage={props.onUpdateImage}
193
+ />
194
+ <BitSelectMode
195
+ onUpdateImage={props.onUpdateImage}
196
+ />
197
+ </div>
198
+ ) : null}
199
+
200
+ <div className={styles.controlsContainer}>
201
+ {/* Canvas */}
202
+ <ScrollableCanvas
203
+ canvas={props.canvas}
204
+ hideScrollbars={props.isEyeDropping}
205
+ style={styles.canvasContainer}
206
+ >
207
+ <PaperCanvas
208
+ canvasRef={props.setCanvas}
209
+ image={props.image}
210
+ imageFormat={props.imageFormat}
211
+ imageId={props.imageId}
212
+ rotationCenterX={props.rotationCenterX}
213
+ rotationCenterY={props.rotationCenterY}
214
+ zoomLevelId={props.zoomLevelId}
215
+ onUpdateImage={props.onUpdateImage}
216
+ />
217
+ <textarea
218
+ className={styles.textArea}
219
+ ref={props.setTextArea}
220
+ spellCheck={false}
221
+ />
222
+ {props.isEyeDropping &&
223
+ props.colorInfo !== null &&
224
+ !props.colorInfo.hideLoupe ? (
225
+ <Box className={styles.colorPickerWrapper}>
226
+ <Loupe
227
+ colorInfo={props.colorInfo}
228
+ pixelRatio={paper.project.view.pixelRatio}
229
+ />
230
+ </Box>
231
+ ) : null
232
+ }
233
+ </ScrollableCanvas>
234
+ <div className={styles.canvasControls}>
235
+ {isVector(props.format) ?
248
236
  <Button
249
237
  className={styles.bitmapButton}
250
- onClick={props.onSwitchToVector}
238
+ onClick={props.onSwitchToBitmap}
251
239
  >
252
240
  <img
253
241
  className={styles.bitmapButtonIcon}
@@ -255,53 +243,68 @@ const PaintEditorComponent = props => (
255
243
  src={bitmapIcon}
256
244
  />
257
245
  <span className={styles.buttonText}>
258
- {props.intl.formatMessage(messages.vector)}
246
+ {intl.formatMessage(messages.bitmap)}
259
247
  </span>
260
- </Button> : null
261
- }
262
- {/* Zoom controls */}
263
- <InputGroup className={styles.zoomControls}>
264
- <ButtonGroup>
265
- <Button
266
- className={styles.buttonGroupButton}
267
- onClick={props.onZoomOut}
268
- >
269
- <img
270
- alt="Zoom Out"
271
- className={styles.buttonGroupButtonIcon}
272
- draggable={false}
273
- src={zoomOutIcon}
274
- />
275
- </Button>
276
- <Button
277
- className={styles.buttonGroupButton}
278
- onClick={props.onZoomReset}
279
- >
280
- <img
281
- alt="Zoom Reset"
282
- className={styles.buttonGroupButtonIcon}
283
- draggable={false}
284
- src={zoomResetIcon}
285
- />
286
- </Button>
287
- <Button
288
- className={styles.buttonGroupButton}
289
- onClick={props.onZoomIn}
290
- >
291
- <img
292
- alt="Zoom In"
293
- className={styles.buttonGroupButtonIcon}
294
- draggable={false}
295
- src={zoomInIcon}
296
- />
297
- </Button>
298
- </ButtonGroup>
299
- </InputGroup>
248
+ </Button> :
249
+ isBitmap(props.format) ?
250
+ <Button
251
+ className={styles.bitmapButton}
252
+ onClick={props.onSwitchToVector}
253
+ >
254
+ <img
255
+ className={styles.bitmapButtonIcon}
256
+ draggable={false}
257
+ src={bitmapIcon}
258
+ />
259
+ <span className={styles.buttonText}>
260
+ {intl.formatMessage(messages.vector)}
261
+ </span>
262
+ </Button> : null
263
+ }
264
+ {/* Zoom controls */}
265
+ <InputGroup className={styles.zoomControls}>
266
+ <ButtonGroup>
267
+ <Button
268
+ className={styles.buttonGroupButton}
269
+ onClick={props.onZoomOut}
270
+ >
271
+ <img
272
+ alt="Zoom Out"
273
+ className={styles.buttonGroupButtonIcon}
274
+ draggable={false}
275
+ src={zoomOutIcon}
276
+ />
277
+ </Button>
278
+ <Button
279
+ className={styles.buttonGroupButton}
280
+ onClick={props.onZoomReset}
281
+ >
282
+ <img
283
+ alt="Zoom Reset"
284
+ className={styles.buttonGroupButtonIcon}
285
+ draggable={false}
286
+ src={zoomResetIcon}
287
+ />
288
+ </Button>
289
+ <Button
290
+ className={styles.buttonGroupButton}
291
+ onClick={props.onZoomIn}
292
+ >
293
+ <img
294
+ alt="Zoom In"
295
+ className={styles.buttonGroupButtonIcon}
296
+ draggable={false}
297
+ src={zoomInIcon}
298
+ />
299
+ </Button>
300
+ </ButtonGroup>
301
+ </InputGroup>
302
+ </div>
300
303
  </div>
301
304
  </div>
302
305
  </div>
303
- </div>
304
- );
306
+ );
307
+ };
305
308
 
306
309
  PaintEditorComponent.propTypes = {
307
310
  canRedo: PropTypes.func.isRequired,
@@ -315,7 +318,6 @@ PaintEditorComponent.propTypes = {
315
318
  ]),
316
319
  imageFormat: PropTypes.string,
317
320
  imageId: PropTypes.string,
318
- intl: intlShape,
319
321
  isEyeDropping: PropTypes.bool,
320
322
  name: PropTypes.string,
321
323
  onRedo: PropTypes.func.isRequired,
@@ -336,4 +338,4 @@ PaintEditorComponent.propTypes = {
336
338
  zoomLevelId: PropTypes.string
337
339
  };
338
340
 
339
- export default injectIntl(PaintEditorComponent);
341
+ export default PaintEditorComponent;
@@ -1,31 +1,34 @@
1
1
  import classNames from 'classnames';
2
2
  import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import {injectIntl, intlShape} from 'react-intl';
4
+ import {useIntl} from 'react-intl';
5
5
 
6
6
  import Button from '../button/button.jsx';
7
7
 
8
8
  import styles from './tool-select-base.css';
9
9
 
10
- const ToolSelectComponent = props => (
11
- <Button
12
- className={
13
- classNames(props.className, styles.modToolSelect, {
14
- [styles.isSelected]: props.isSelected
15
- })
16
- }
17
- disabled={props.disabled}
18
- title={props.intl.formatMessage(props.imgDescriptor)}
19
- onClick={props.onMouseDown}
20
- >
21
- <img
22
- alt={props.intl.formatMessage(props.imgDescriptor)}
23
- className={styles.toolSelectIcon}
24
- draggable={false}
25
- src={props.imgSrc}
26
- />
27
- </Button>
28
- );
10
+ const ToolSelectComponent = props => {
11
+ const intl = useIntl();
12
+ return (
13
+ <Button
14
+ className={
15
+ classNames(props.className, styles.modToolSelect, {
16
+ [styles.isSelected]: props.isSelected
17
+ })
18
+ }
19
+ disabled={props.disabled}
20
+ title={intl.formatMessage(props.imgDescriptor)}
21
+ onClick={props.onMouseDown}
22
+ >
23
+ <img
24
+ alt={intl.formatMessage(props.imgDescriptor)}
25
+ className={styles.toolSelectIcon}
26
+ draggable={false}
27
+ src={props.imgSrc}
28
+ />
29
+ </Button>
30
+ );
31
+ };
29
32
 
30
33
  ToolSelectComponent.propTypes = {
31
34
  className: PropTypes.string,
@@ -36,9 +39,8 @@ ToolSelectComponent.propTypes = {
36
39
  id: PropTypes.string
37
40
  }).isRequired,
38
41
  imgSrc: PropTypes.string.isRequired,
39
- intl: intlShape.isRequired,
40
42
  isSelected: PropTypes.bool.isRequired,
41
43
  onMouseDown: PropTypes.func.isRequired
42
44
  };
43
45
 
44
- export default injectIntl(ToolSelectComponent);
46
+ export default ToolSelectComponent;
@@ -2,7 +2,8 @@ import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import bindAll from 'lodash.bindall';
4
4
  import parseColor from 'parse-color';
5
- import {injectIntl, intlShape} from 'react-intl';
5
+ import {injectIntl} from 'react-intl';
6
+ import intlShape from '../lib/intl-shape.js';
6
7
 
7
8
  import {getSelectedLeafItems} from '../helper/selection';
8
9
  import Formats, {isBitmap} from '../lib/format';
@@ -0,0 +1,10 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ // intlShape was removed in react-intl@3 and replaced with a TypeScript interface.
4
+ // These are some of the commonly used properties from the intl object.
5
+ const intlShape = PropTypes.shape({
6
+ locale: PropTypes.string.isRequired,
7
+ formatMessage: PropTypes.func.isRequired
8
+ });
9
+
10
+ export default intlShape;
@@ -182,10 +182,12 @@ class Playground extends React.Component {
182
182
  }
183
183
 
184
184
  }
185
- ReactDOM.render((
185
+
186
+ const root = ReactDOM.createRoot(appTarget);
187
+ root.render(
186
188
  <Provider store={store}>
187
189
  <IntlProvider>
188
190
  <Playground />
189
191
  </IntlProvider>
190
192
  </Provider>
191
- ), appTarget);
193
+ );
@@ -1,15 +1,8 @@
1
- import {addLocaleData} from 'react-intl';
2
1
  import {updateIntl as superUpdateIntl} from 'react-intl-redux';
3
2
  import {IntlProvider, intlReducer} from 'react-intl-redux';
4
3
 
5
- import localeData from 'scratch-l10n';
6
4
  import paintMessages from 'scratch-l10n/locales/paint-editor-msgs';
7
5
 
8
- Object.keys(localeData).forEach(locale => {
9
- // TODO: will need to handle locales not in the default intl - see www/custom-locales
10
- addLocaleData(localeData[locale].localeData);
11
- });
12
-
13
6
  const intlInitialState = {
14
7
  intl: {
15
8
  defaultLocale: 'en',
package/webpack.config.js CHANGED
@@ -17,7 +17,12 @@ const base = {
17
17
  rules: [{
18
18
  test: /\.jsx?$/,
19
19
  loader: 'babel-loader',
20
- include: path.resolve(__dirname, 'src'),
20
+ include: [
21
+ path.resolve(__dirname, 'src'),
22
+ path.join(__dirname, 'node_modules/react-intl'),
23
+ path.join(__dirname, 'node_modules/intl-messageformat'),
24
+ path.join(__dirname, 'node_modules/intl-messageformat-parser')
25
+ ],
21
26
  options: {
22
27
  plugins: ['transform-object-rest-spread'],
23
28
  presets: [