scratch-paint 4.0.21 → 4.0.23
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.
- package/.github/workflows/deploy.yml +3 -3
- package/.github/workflows/update-l10n.yml +2 -2
- package/.nvmrc +1 -1
- package/dist/scratch-paint.js +108 -122
- package/dist/scratch-paint.js.map +1 -1
- package/eslint.config.mjs +61 -0
- package/package.json +6 -8
- package/scripts/build-i18n-source.js +1 -1
- package/src/components/paint-editor/paint-editor.jsx +2 -2
- package/src/containers/mode-tools.jsx +3 -3
- package/src/helper/bit-tools/brush-tool.js +1 -1
- package/src/helper/bit-tools/fill-tool.js +1 -1
- package/src/helper/bit-tools/line-tool.js +3 -3
- package/src/helper/bit-tools/oval-tool.js +1 -1
- package/src/helper/bit-tools/rect-tool.js +1 -1
- package/src/helper/bit-tools/select-tool.js +2 -2
- package/src/helper/bitmap.js +13 -15
- package/src/helper/blob-tools/broad-brush-helper.js +1 -2
- package/src/helper/blob-tools/segment-brush-helper.js +4 -5
- package/src/helper/group.js +14 -16
- package/src/helper/hover.js +1 -1
- package/src/helper/layer.js +5 -5
- package/src/helper/math.js +1 -1
- package/src/helper/selection-tools/bounding-box-tool.js +5 -5
- package/src/helper/selection-tools/handle-tool.js +2 -2
- package/src/helper/selection-tools/move-tool.js +3 -3
- package/src/helper/selection-tools/nudge-tool.js +2 -2
- package/src/helper/selection-tools/point-tool.js +1 -1
- package/src/helper/selection-tools/reshape-tool.js +7 -7
- package/src/helper/selection-tools/rotate-tool.js +1 -1
- package/src/helper/selection-tools/scale-tool.js +3 -3
- package/src/helper/selection-tools/select-tool.js +3 -3
- package/src/helper/selection.js +19 -19
- package/src/helper/snapping.js +2 -2
- package/src/helper/style-path.js +8 -8
- package/src/helper/tools/fill-tool.js +1 -1
- package/src/helper/tools/oval-tool.js +1 -1
- package/src/helper/tools/rect-tool.js +1 -1
- package/src/helper/tools/rounded-rect-tool.js +2 -2
- package/src/helper/tools/text-tool.js +4 -4
- package/src/helper/view.js +9 -10
- package/src/playground/playground.jsx +28 -25
- package/src/playground/reducers/intl.js +1 -2
- package/src/reducers/cursor.js +1 -1
- package/src/reducers/hover.js +1 -1
- package/src/reducers/layout.js +1 -1
- package/src/reducers/selected-items.js +1 -1
- package/src/reducers/text-edit-target.js +1 -1
- package/src/reducers/undo.js +2 -2
- package/src/reducers/view-bounds.js +1 -1
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -3
- package/src/.eslintrc.js +0 -24
- package/tmp.js +0 -0
|
@@ -7,7 +7,7 @@ class PointTool {
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
9
9
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
10
|
-
* @param {!
|
|
10
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
11
11
|
*/
|
|
12
12
|
constructor (setSelectedItems, clearSelectedItems, onUpdateImage) {
|
|
13
13
|
/**
|
|
@@ -56,8 +56,8 @@ class ReshapeTool extends paper.Tool {
|
|
|
56
56
|
* @param {function} clearHoveredItem Callback to clear the hovered item
|
|
57
57
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
58
58
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
59
|
-
* @param {!
|
|
60
|
-
* @param {!
|
|
59
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
60
|
+
* @param {!Function} switchToTextTool A callback to call to switch to the text tool
|
|
61
61
|
*/
|
|
62
62
|
constructor (setHoveredItem, clearHoveredItem, setSelectedItems, clearSelectedItems, onUpdateImage,
|
|
63
63
|
switchToTextTool) {
|
|
@@ -95,7 +95,7 @@ class ReshapeTool extends paper.Tool {
|
|
|
95
95
|
* Returns the hit options for segments to use when conducting hit tests. Segments are only visible
|
|
96
96
|
* when the shape is selected. Segments take precedence, since they are always over curves and need
|
|
97
97
|
* to be grabbable. (Segments are the little circles)
|
|
98
|
-
* @
|
|
98
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
99
99
|
*/
|
|
100
100
|
getSelectedSegmentHitOptions () {
|
|
101
101
|
const hitOptions = {
|
|
@@ -114,7 +114,7 @@ class ReshapeTool extends paper.Tool {
|
|
|
114
114
|
* Returns the hit options for handles to use when conducting hit tests. Handles need to be done
|
|
115
115
|
* separately because we want to ignore hidden handles, but we don't want hidden handles to negate
|
|
116
116
|
* legitimate hits on other things (like if the handle is over part of the fill). (Handles are the diamonds)
|
|
117
|
-
* @
|
|
117
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
118
118
|
*/
|
|
119
119
|
getHandleHitOptions () {
|
|
120
120
|
const hitOptions = {
|
|
@@ -135,7 +135,7 @@ class ReshapeTool extends paper.Tool {
|
|
|
135
135
|
/**
|
|
136
136
|
* Returns the hit options for curves of selected objects, which take precedence over
|
|
137
137
|
* unselected things and fills.
|
|
138
|
-
* @
|
|
138
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
139
139
|
*/
|
|
140
140
|
getSelectedStrokeHitOptions () {
|
|
141
141
|
const hitOptions = {
|
|
@@ -159,7 +159,7 @@ class ReshapeTool extends paper.Tool {
|
|
|
159
159
|
* Returns the hit options for fills and unselected strokes/curves to use when conducting hit tests.
|
|
160
160
|
* @param {boolean} preselectedOnly True if we should only return results that are already
|
|
161
161
|
* selected.
|
|
162
|
-
* @
|
|
162
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
163
163
|
*/
|
|
164
164
|
getUnselectedAndFillHitOptions () {
|
|
165
165
|
const hitOptions = {
|
|
@@ -187,7 +187,7 @@ class ReshapeTool extends paper.Tool {
|
|
|
187
187
|
/**
|
|
188
188
|
* Given the point at which the mouse is, return the prioritized hit result, or null if nothing was hit.
|
|
189
189
|
* @param {paper.Point} point Point to hit test on canvas
|
|
190
|
-
* @
|
|
190
|
+
* @returns {?paper.HitResult} hitResult
|
|
191
191
|
*/
|
|
192
192
|
getHitResult (point) {
|
|
193
193
|
// Prefer hits on segments to other types of hits, since segments always overlap curves.
|
|
@@ -5,7 +5,7 @@ import paper from '@scratch/paper';
|
|
|
5
5
|
*/
|
|
6
6
|
class RotateTool {
|
|
7
7
|
/**
|
|
8
|
-
* @param {!
|
|
8
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
9
9
|
*/
|
|
10
10
|
constructor (onUpdateImage) {
|
|
11
11
|
this.rotItems = [];
|
|
@@ -12,7 +12,7 @@ const MIN_SCALE_FACTOR = 0.0001;
|
|
|
12
12
|
class ScaleTool {
|
|
13
13
|
/**
|
|
14
14
|
* @param {Mode} mode Paint editor mode
|
|
15
|
-
* @param {!
|
|
15
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
16
16
|
*/
|
|
17
17
|
constructor (mode, onUpdateImage) {
|
|
18
18
|
this.isBitmap = mode in BitmapModes;
|
|
@@ -150,7 +150,7 @@ class ScaleTool {
|
|
|
150
150
|
}
|
|
151
151
|
this.boundsPath.remove();
|
|
152
152
|
this.boundsPath = null;
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
// mark text items as scaled (for later use on font size calc)
|
|
155
155
|
for (let i = 0; i < this.itemGroup.children.length; i++) {
|
|
156
156
|
const child = this.itemGroup.children[i];
|
|
@@ -169,7 +169,7 @@ class ScaleTool {
|
|
|
169
169
|
this.itemGroup.layer.addChildren(this.itemGroup.children);
|
|
170
170
|
}
|
|
171
171
|
this.itemGroup.remove();
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
this.onUpdateImage();
|
|
174
174
|
this.active = false;
|
|
175
175
|
}
|
|
@@ -29,8 +29,8 @@ class SelectTool extends paper.Tool {
|
|
|
29
29
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
30
30
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
31
31
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
32
|
-
* @param {!
|
|
33
|
-
* @param {!
|
|
32
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
33
|
+
* @param {!Function} switchToTextTool A callback to call to switch to the text tool
|
|
34
34
|
*/
|
|
35
35
|
constructor (setHoveredItem, clearHoveredItem, setSelectedItems, clearSelectedItems, setCursor, onUpdateImage,
|
|
36
36
|
switchToTextTool) {
|
|
@@ -86,7 +86,7 @@ class SelectTool extends paper.Tool {
|
|
|
86
86
|
* Returns the hit options to use when conducting hit tests.
|
|
87
87
|
* @param {boolean} preselectedOnly True if we should only return results that are already
|
|
88
88
|
* selected.
|
|
89
|
-
* @
|
|
89
|
+
* @returns {object} See paper.Item.hitTest for definition of options
|
|
90
90
|
*/
|
|
91
91
|
getHitOptions (preselectedOnly) {
|
|
92
92
|
// Tolerance needs to be scaled when the view is zoomed in in order to represent the same
|
package/src/helper/selection.js
CHANGED
|
@@ -9,7 +9,7 @@ import {sortItemsByZIndex} from './math';
|
|
|
9
9
|
/**
|
|
10
10
|
* Wrapper for paper.project.getItems that excludes our helper items
|
|
11
11
|
* @param {?object} options See paper.js docs for paper.Item.getItems
|
|
12
|
-
* @
|
|
12
|
+
* @returns {Array<paper.Item>} items that match options
|
|
13
13
|
*/
|
|
14
14
|
const getItems = function (options) {
|
|
15
15
|
const newMatcher = function (item) {
|
|
@@ -27,7 +27,7 @@ const getItems = function (options) {
|
|
|
27
27
|
/**
|
|
28
28
|
* @param {boolean} includeGuides True if guide layer items like the bounding box should
|
|
29
29
|
* be included in the returned items.
|
|
30
|
-
* @
|
|
30
|
+
* @returns {Array<paper.item>} all top-level (direct descendants of a paper.Layer) items
|
|
31
31
|
*/
|
|
32
32
|
const getAllRootItems = function (includeGuides) {
|
|
33
33
|
includeGuides = includeGuides || false;
|
|
@@ -45,7 +45,7 @@ const getAllRootItems = function (includeGuides) {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* @
|
|
48
|
+
* @returns {Array<paper.item>} all top-level (direct descendants of a paper.Layer) items
|
|
49
49
|
* that aren't guide items or helper items.
|
|
50
50
|
*/
|
|
51
51
|
const getAllSelectableRootItems = function () {
|
|
@@ -98,7 +98,7 @@ const _setGroupSelection = function (root, selected, fullySelected) {
|
|
|
98
98
|
const setItemSelection = function (item, state, fullySelected) {
|
|
99
99
|
const parentGroup = getItemsGroup(item);
|
|
100
100
|
const itemsCompoundPath = getItemsCompoundPath(item);
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
// if selection is in a group, select group
|
|
103
103
|
if (parentGroup) {
|
|
104
104
|
// do it recursive
|
|
@@ -111,32 +111,32 @@ const setItemSelection = function (item, state, fullySelected) {
|
|
|
111
111
|
}
|
|
112
112
|
_setGroupSelection(item, state, fullySelected);
|
|
113
113
|
}
|
|
114
|
-
|
|
114
|
+
|
|
115
115
|
};
|
|
116
116
|
|
|
117
|
-
/** @
|
|
117
|
+
/** @returns {boolean} true if anything was selected */
|
|
118
118
|
const selectAllItems = function () {
|
|
119
119
|
const items = getAllSelectableRootItems();
|
|
120
120
|
if (items.length === 0) return false;
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
for (let i = 0; i < items.length; i++) {
|
|
123
123
|
setItemSelection(items[i], true);
|
|
124
124
|
}
|
|
125
125
|
return true;
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
-
/** @
|
|
128
|
+
/** @returns {boolean} true if anything was selected */
|
|
129
129
|
const selectAllSegments = function () {
|
|
130
130
|
const items = getAllSelectableRootItems();
|
|
131
131
|
if (items.length === 0) return false;
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
for (let i = 0; i < items.length; i++) {
|
|
134
134
|
selectItemSegments(items[i], true);
|
|
135
135
|
}
|
|
136
136
|
return true;
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
/** @param {!
|
|
139
|
+
/** @param {!Function} dispatchClearSelect Function to update the Redux select state */
|
|
140
140
|
const clearSelection = function (dispatchClearSelect) {
|
|
141
141
|
paper.project.deselectAll();
|
|
142
142
|
dispatchClearSelect();
|
|
@@ -146,7 +146,7 @@ const clearSelection = function (dispatchClearSelect) {
|
|
|
146
146
|
* This gets all selected non-grouped items and groups
|
|
147
147
|
* (alternative to paper.project.selectedItems, which includes
|
|
148
148
|
* group children in addition to the group)
|
|
149
|
-
* @
|
|
149
|
+
* @returns {Array<paper.Item>} in increasing Z order.
|
|
150
150
|
*/
|
|
151
151
|
const getSelectedRootItems = function () {
|
|
152
152
|
const allItems = getAllSelectableRootItems();
|
|
@@ -174,7 +174,7 @@ const getSelectedRootItems = function () {
|
|
|
174
174
|
/**
|
|
175
175
|
* This gets all selected items that are as deeply nested as possible. Does not
|
|
176
176
|
* return the parent groups.
|
|
177
|
-
* @
|
|
177
|
+
* @returns {Array<paper.Item>} in increasing Z order.
|
|
178
178
|
*/
|
|
179
179
|
const getSelectedLeafItems = function () {
|
|
180
180
|
const allItems = paper.project.selectedItems;
|
|
@@ -192,7 +192,7 @@ const getSelectedLeafItems = function () {
|
|
|
192
192
|
|
|
193
193
|
/**
|
|
194
194
|
* This gets all selected path segments.
|
|
195
|
-
* @
|
|
195
|
+
* @returns {Array<paper.Segment>} selected segments
|
|
196
196
|
*/
|
|
197
197
|
const getSelectedSegments = function () {
|
|
198
198
|
const selected = getSelectedLeafItems();
|
|
@@ -225,7 +225,7 @@ const _deleteItemSelection = function (items, onUpdateImage) {
|
|
|
225
225
|
// Return true if anything was removed
|
|
226
226
|
const _removeSelectedSegments = function (items, onUpdateImage) {
|
|
227
227
|
const segmentsToRemove = [];
|
|
228
|
-
|
|
228
|
+
|
|
229
229
|
for (let i = 0; i < items.length; i++) {
|
|
230
230
|
if (!items[i].segments) continue;
|
|
231
231
|
const segments = items[i].segments;
|
|
@@ -236,7 +236,7 @@ const _removeSelectedSegments = function (items, onUpdateImage) {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
}
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
let removedSegments = false;
|
|
241
241
|
for (let i = 0; i < segmentsToRemove.length; i++) {
|
|
242
242
|
const seg = segmentsToRemove[i];
|
|
@@ -295,7 +295,7 @@ const _checkBoundsItem = function (selectionRect, item, event) {
|
|
|
295
295
|
}
|
|
296
296
|
itemBounds.remove();
|
|
297
297
|
return true;
|
|
298
|
-
|
|
298
|
+
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
301
|
|
|
@@ -305,7 +305,7 @@ const _checkBoundsItem = function (selectionRect, item, event) {
|
|
|
305
305
|
const _handleRectangularSelectionItems = function (item, event, rect, mode, root) {
|
|
306
306
|
if (isPathItem(item)) {
|
|
307
307
|
let segmentMode = false;
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
// first round checks for segments inside the selectionRect
|
|
310
310
|
for (let j = 0; j < item.segments.length; j++) {
|
|
311
311
|
const seg = item.segments[j];
|
|
@@ -373,7 +373,7 @@ const _handleRectangularSelectionItems = function (item, event, rect, mode, root
|
|
|
373
373
|
const _rectangularSelectionGroupLoop = function (group, rect, root, event, mode) {
|
|
374
374
|
for (let i = 0; i < group.children.length; i++) {
|
|
375
375
|
const child = group.children[i];
|
|
376
|
-
|
|
376
|
+
|
|
377
377
|
if (isGroup(child) || isCompoundPathItem(child)) {
|
|
378
378
|
_rectangularSelectionGroupLoop(child, rect, root, event, mode);
|
|
379
379
|
} else {
|
|
@@ -393,7 +393,7 @@ const _rectangularSelectionGroupLoop = function (group, rect, root, event, mode)
|
|
|
393
393
|
*/
|
|
394
394
|
const processRectangularSelection = function (event, rect, mode) {
|
|
395
395
|
const allItems = getAllSelectableRootItems();
|
|
396
|
-
|
|
396
|
+
|
|
397
397
|
for (let i = 0; i < allItems.length; i++) {
|
|
398
398
|
const item = allItems[i];
|
|
399
399
|
if (mode === Modes.RESHAPE && isPGTextItem(getRootItem(item))) {
|
package/src/helper/snapping.js
CHANGED
|
@@ -5,7 +5,7 @@ import {getItems} from './selection';
|
|
|
5
5
|
* @param {paper.Point} point1 point 1
|
|
6
6
|
* @param {paper.Point} point2 point 2
|
|
7
7
|
* @param {number} tolerance Distance allowed between points that are "touching"
|
|
8
|
-
* @
|
|
8
|
+
* @returns {boolean} true if points are within the tolerance distance.
|
|
9
9
|
*/
|
|
10
10
|
const touching = function (point1, point2, tolerance) {
|
|
11
11
|
return point1.getDistance(point2, true) < Math.pow(tolerance / paper.view.zoom, 2);
|
|
@@ -16,7 +16,7 @@ const touching = function (point1, point2, tolerance) {
|
|
|
16
16
|
* @param {!number} tolerance Distance within which it counts as a hit
|
|
17
17
|
* @param {?paper.Path} excludePath Path to exclude from hit test, if any. For instance, you
|
|
18
18
|
* are drawing a line and don't want it to snap to its own start point.
|
|
19
|
-
* @
|
|
19
|
+
* @returns {object} data about the end point of an unclosed path, if any such point is within the
|
|
20
20
|
* tolerance distance of the given point, or null if none exists.
|
|
21
21
|
*/
|
|
22
22
|
const endPointHit = function (point, tolerance, excludePath) {
|
package/src/helper/style-path.js
CHANGED
|
@@ -37,7 +37,7 @@ const _getColorStateListeners = function (textEditTargetId) {
|
|
|
37
37
|
* in order to form a smooth gradient, otherwise it fades through black. This
|
|
38
38
|
* function gets the transparent color for a given color string.
|
|
39
39
|
* @param {?string} colorToMatch CSS string of other color of gradient, or null for transparent
|
|
40
|
-
* @
|
|
40
|
+
* @returns {string} CSS string for matching color of transparent
|
|
41
41
|
*/
|
|
42
42
|
const getColorStringForTransparent = function (colorToMatch) {
|
|
43
43
|
const color = new paper.Color(colorToMatch);
|
|
@@ -48,7 +48,7 @@ const getColorStringForTransparent = function (colorToMatch) {
|
|
|
48
48
|
/**
|
|
49
49
|
* Generate a color that contrasts well with the passed-in color.
|
|
50
50
|
* @param {string} firstColor The "primary" color
|
|
51
|
-
* @
|
|
51
|
+
* @returns {string} CSS string for generated color
|
|
52
52
|
*/
|
|
53
53
|
const generateSecondaryColor = function (firstColor) {
|
|
54
54
|
if (firstColor === MIXED) return null;
|
|
@@ -83,7 +83,7 @@ const generateSecondaryColor = function (firstColor) {
|
|
|
83
83
|
* @param {?paper.Point} [radialCenter] Where the center of a radial gradient should be, if the gradient is radial.
|
|
84
84
|
* Defaults to center of bounds.
|
|
85
85
|
* @param {number} [minSize] The minimum width/height of the gradient object.
|
|
86
|
-
* @
|
|
86
|
+
* @returns {paper.Color} Color object with gradient, may be null or color string if the gradient type is solid
|
|
87
87
|
*/
|
|
88
88
|
const createGradientObject = function (color1, color2, gradientType, bounds, radialCenter, minSize) {
|
|
89
89
|
if (gradientType === GradientTypes.SOLID) return color1;
|
|
@@ -156,7 +156,7 @@ const createGradientObject = function (color1, color2, gradientType, bounds, rad
|
|
|
156
156
|
* When changing the color in this case, the solid gradient should override the existing gradient on the item.
|
|
157
157
|
* @param {?boolean} applyToStroke True if changing the selection's stroke, false if changing its fill.
|
|
158
158
|
* @param {?string} textEditTargetId paper.Item.id of text editing target, if any
|
|
159
|
-
* @
|
|
159
|
+
* @returns {boolean} Whether the color application actually changed visibly.
|
|
160
160
|
*/
|
|
161
161
|
const applyColorToSelection = function (
|
|
162
162
|
colorString,
|
|
@@ -213,7 +213,7 @@ const applyColorToSelection = function (
|
|
|
213
213
|
* Called to swap gradient colors
|
|
214
214
|
* @param {?boolean} applyToStroke True if changing the selection's stroke, false if changing its fill.
|
|
215
215
|
* @param {?string} textEditTargetId paper.Item.id of text editing target, if any
|
|
216
|
-
* @
|
|
216
|
+
* @returns {boolean} Whether the color application actually changed visibly.
|
|
217
217
|
*/
|
|
218
218
|
const swapColorsInSelection = function (applyToStroke, textEditTargetId) {
|
|
219
219
|
const items = _getColorStateListeners(textEditTargetId);
|
|
@@ -247,7 +247,7 @@ const swapColorsInSelection = function (applyToStroke, textEditTargetId) {
|
|
|
247
247
|
* @param {GradientType} gradientType gradient type
|
|
248
248
|
* @param {?boolean} applyToStroke True if changing the selection's stroke, false if changing its fill.
|
|
249
249
|
* @param {?string} textEditTargetId paper.Item.id of text editing target, if any
|
|
250
|
-
* @
|
|
250
|
+
* @returns {boolean} Whether the color application actually changed visibly.
|
|
251
251
|
*/
|
|
252
252
|
const applyGradientTypeToSelection = function (gradientType, applyToStroke, textEditTargetId) {
|
|
253
253
|
const items = _getColorStateListeners(textEditTargetId);
|
|
@@ -367,7 +367,7 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text
|
|
|
367
367
|
* Called when setting stroke width
|
|
368
368
|
* @param {number} value New stroke width
|
|
369
369
|
* @param {?string} textEditTargetId paper.Item.id of text editing target, if any
|
|
370
|
-
* @
|
|
370
|
+
* @returns {boolean} Whether the color application actually changed visibly.
|
|
371
371
|
*/
|
|
372
372
|
const applyStrokeWidthToSelection = function (value, textEditTargetId) {
|
|
373
373
|
let changed = false;
|
|
@@ -417,7 +417,7 @@ const _colorStateFromGradient = gradient => {
|
|
|
417
417
|
* Get state of colors and stroke width for selection
|
|
418
418
|
* @param {!Array<paper.Item>} selectedItems Selected paper items
|
|
419
419
|
* @param {?boolean} bitmapMode True if the item is being selected in bitmap mode
|
|
420
|
-
* @
|
|
420
|
+
* @returns {?object} Object of strokeColor, strokeWidth, fillColor, thickness of the selection.
|
|
421
421
|
* Gives MIXED when there are mixed values for a color, and null for transparent.
|
|
422
422
|
* Gives null when there are mixed values for stroke width.
|
|
423
423
|
* Thickness is line thickness, used in the bitmap editor
|
|
@@ -11,7 +11,7 @@ class FillTool extends paper.Tool {
|
|
|
11
11
|
/**
|
|
12
12
|
* @param {function} setHoveredItem Callback to set the hovered item
|
|
13
13
|
* @param {function} clearHoveredItem Callback to clear the hovered item
|
|
14
|
-
* @param {!
|
|
14
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
15
15
|
*/
|
|
16
16
|
constructor (setHoveredItem, clearHoveredItem, onUpdateImage) {
|
|
17
17
|
super();
|
|
@@ -17,7 +17,7 @@ class OvalTool extends paper.Tool {
|
|
|
17
17
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
18
18
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
19
19
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
20
|
-
* @param {!
|
|
20
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
21
21
|
*/
|
|
22
22
|
constructor (setSelectedItems, clearSelectedItems, setCursor, onUpdateImage) {
|
|
23
23
|
super();
|
|
@@ -17,7 +17,7 @@ class RectTool extends paper.Tool {
|
|
|
17
17
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
18
18
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
19
19
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
20
|
-
* @param {!
|
|
20
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
21
21
|
*/
|
|
22
22
|
constructor (setSelectedItems, clearSelectedItems, setCursor, onUpdateImage) {
|
|
23
23
|
super();
|
|
@@ -10,7 +10,7 @@ class RoundedRectTool extends paper.Tool {
|
|
|
10
10
|
* @param {function} clearHoveredItem Callback to clear the hovered item
|
|
11
11
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
12
12
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
13
|
-
* @param {!
|
|
13
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
14
14
|
*/
|
|
15
15
|
constructor (setHoveredItem, clearHoveredItem, setSelectedItems, clearSelectedItems, onUpdateImage) {
|
|
16
16
|
super();
|
|
@@ -20,7 +20,7 @@ class RoundedRectTool extends paper.Tool {
|
|
|
20
20
|
this.clearSelectedItems = clearSelectedItems;
|
|
21
21
|
this.onUpdateImage = onUpdateImage;
|
|
22
22
|
this.prevHoveredItemId = null;
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
// We have to set these functions instead of just declaring them because
|
|
25
25
|
// paper.js tools hook up the listeners in the setter functions.
|
|
26
26
|
this.onMouseDown = this.handleMouseDown;
|
|
@@ -36,9 +36,9 @@ class TextTool extends paper.Tool {
|
|
|
36
36
|
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
|
|
37
37
|
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
|
|
38
38
|
* @param {function} setCursor Callback to set the visible mouse cursor
|
|
39
|
-
* @param {!
|
|
40
|
-
* @param {!
|
|
41
|
-
* @param {!
|
|
39
|
+
* @param {!Function} onUpdateImage A callback to call when the image visibly changes
|
|
40
|
+
* @param {!Function} setTextEditTarget Call to set text editing target whenever text editing is active
|
|
41
|
+
* @param {!Function} changeFont Call to change the font in the dropdown
|
|
42
42
|
* @param {?boolean} isBitmap True if text should be rasterized once it's deselected
|
|
43
43
|
*/
|
|
44
44
|
constructor (textAreaElement, setSelectedItems, clearSelectedItems, setCursor, onUpdateImage, setTextEditTarget,
|
|
@@ -173,7 +173,7 @@ class TextTool extends paper.Tool {
|
|
|
173
173
|
calculated.append(viewMtx);
|
|
174
174
|
calculated.append(textBoxMtx);
|
|
175
175
|
this.element.style.transform = `matrix(${calculated.a}, ${calculated.b}, ${calculated.c}, ${calculated.d},
|
|
176
|
-
|
|
176
|
+
${calculated.tx}, ${calculated.ty})`;
|
|
177
177
|
}
|
|
178
178
|
setColorState (colorState) {
|
|
179
179
|
this.colorState = colorState;
|
package/src/helper/view.js
CHANGED
|
@@ -31,16 +31,15 @@ let _workspaceBounds = ART_BOARD_BOUNDS;
|
|
|
31
31
|
const getWorkspaceBounds = () => _workspaceBounds;
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* The workspace bounds define the areas that the scroll bars can access.
|
|
35
|
-
* They include at minimum the artboard, and extend to a bit beyond the
|
|
36
|
-
* farthest item off
|
|
37
|
-
* "lost" off the edge)
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
*/
|
|
34
|
+
* The workspace bounds define the areas that the scroll bars can access.
|
|
35
|
+
* They include at minimum the artboard, and extend to a bit beyond the
|
|
36
|
+
* farthest item off the edge in any given direction (so items can't be
|
|
37
|
+
* "lost" off the edge)
|
|
38
|
+
* @param {boolean} clipEmpty Clip empty space from bounds, even if it
|
|
39
|
+
* means discontinuously jumping the viewport. This should probably be
|
|
40
|
+
* false unless the viewport is going to move discontinuously anyway
|
|
41
|
+
* (such as in a zoom button click)
|
|
42
|
+
*/
|
|
44
43
|
const setWorkspaceBounds = clipEmpty => {
|
|
45
44
|
const items = getAllRootItems();
|
|
46
45
|
// Include the artboard and what's visible in the viewport
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console, no-alert */
|
|
1
2
|
import bindAll from 'lodash.bindall';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import ReactDOM from 'react-dom';
|
|
@@ -9,7 +10,7 @@ import {intlInitialState, IntlProvider} from './reducers/intl.js';
|
|
|
9
10
|
import styles from './playground.css';
|
|
10
11
|
// scratch-render-fonts is a playground-only dep. Fonts are expected to be imported
|
|
11
12
|
// as a peer dependency, otherwise there will be two copies of them.
|
|
12
|
-
import {FONTS} from 'scratch-render-fonts';
|
|
13
|
+
import {FONTS as _FONTS} from 'scratch-render-fonts';
|
|
13
14
|
|
|
14
15
|
const appTarget = document.createElement('div');
|
|
15
16
|
appTarget.setAttribute('class', styles.playgroundContainer);
|
|
@@ -39,7 +40,7 @@ class Playground extends React.Component {
|
|
|
39
40
|
]);
|
|
40
41
|
// Append ?dir=rtl to URL to get RTL layout
|
|
41
42
|
const match = location.search.match(/dir=([^&]+)/);
|
|
42
|
-
const rtl = match && match[1]
|
|
43
|
+
const rtl = match && match[1] === 'rtl';
|
|
43
44
|
this.id = 0;
|
|
44
45
|
this.state = {
|
|
45
46
|
name: 'meow',
|
|
@@ -48,7 +49,7 @@ class Playground extends React.Component {
|
|
|
48
49
|
imageFormat: 'svg', // 'svg', 'png', or 'jpg'
|
|
49
50
|
image: svgString, // svg string or data URI
|
|
50
51
|
imageId: this.id, // If this changes, the paint editor will reload
|
|
51
|
-
rtl: rtl
|
|
52
|
+
rtl: rtl
|
|
52
53
|
};
|
|
53
54
|
this.reusableCanvas = document.createElement('canvas');
|
|
54
55
|
}
|
|
@@ -111,7 +112,7 @@ class Playground extends React.Component {
|
|
|
111
112
|
}
|
|
112
113
|
document.body.removeChild(downloadLink);
|
|
113
114
|
}
|
|
114
|
-
b64toByteArray (b64Data, sliceSize=512) {
|
|
115
|
+
b64toByteArray (b64Data, sliceSize = 512) {
|
|
115
116
|
// Remove header
|
|
116
117
|
b64Data = b64Data.substring(b64Data.indexOf('base64,') + 7);
|
|
117
118
|
|
|
@@ -126,45 +127,46 @@ class Playground extends React.Component {
|
|
|
126
127
|
byteNumbers[i] = slice.charCodeAt(i);
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
131
|
+
byteArrays.push(byteArray);
|
|
132
|
+
}
|
|
132
133
|
|
|
133
|
-
|
|
134
|
+
return byteArrays;
|
|
134
135
|
}
|
|
135
|
-
uploadImage() {
|
|
136
|
+
uploadImage () {
|
|
136
137
|
document.getElementById(styles.fileInput).click();
|
|
137
138
|
}
|
|
138
|
-
onUploadImage(event) {
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
onUploadImage (event) {
|
|
140
|
+
const file = event.target.files[0];
|
|
141
|
+
const type = file.type === 'image/svg+xml' ? 'svg' :
|
|
141
142
|
file.type === 'image/png' ? 'png' :
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
file.type === 'image/jpg' ? 'jpg' :
|
|
144
|
+
file.type === 'image/jpeg' ? 'jpg' :
|
|
145
|
+
null;
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
const reader = new FileReader();
|
|
147
148
|
if (type === 'svg') {
|
|
148
|
-
reader.readAsText(file,'UTF-8');
|
|
149
|
+
reader.readAsText(file, 'UTF-8');
|
|
149
150
|
} else if (type === 'png' || type === 'jpg'){
|
|
150
151
|
reader.readAsDataURL(file);
|
|
151
152
|
} else {
|
|
152
|
-
alert(
|
|
153
|
+
alert(`Couldn't read file type: ${file.type}`);
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
const that = this;
|
|
156
157
|
reader.onload = readerEvent => {
|
|
157
|
-
|
|
158
|
+
const content = readerEvent.target.result; // this is the content!
|
|
158
159
|
|
|
159
160
|
that.setState({
|
|
160
161
|
image: content,
|
|
161
|
-
name: file.name.split('.').slice(0, -1)
|
|
162
|
+
name: file.name.split('.').slice(0, -1)
|
|
163
|
+
.join('.'),
|
|
162
164
|
imageId: ++that.id,
|
|
163
165
|
imageFormat: type,
|
|
164
|
-
rotationCenterX:
|
|
165
|
-
rotationCenterY:
|
|
166
|
+
rotationCenterX: void 0,
|
|
167
|
+
rotationCenterY: void 0
|
|
166
168
|
});
|
|
167
|
-
|
|
169
|
+
};
|
|
168
170
|
}
|
|
169
171
|
render () {
|
|
170
172
|
return (
|
|
@@ -174,7 +176,8 @@ class Playground extends React.Component {
|
|
|
174
176
|
onUpdateName={this.handleUpdateName}
|
|
175
177
|
onUpdateImage={this.handleUpdateImage}
|
|
176
178
|
/>
|
|
177
|
-
|
|
179
|
+
{/* eslint-disable react/jsx-max-props-per-line, react/jsx-handler-names */}
|
|
180
|
+
<button className={styles.playgroundButton} onClick={this.uploadImage}>Upload</button>
|
|
178
181
|
<input id={styles.fileInput} type="file" name="name" onChange={this.onUploadImage} />
|
|
179
182
|
<button className={styles.playgroundButton} onClick={this.downloadImage}>Download</button>
|
|
180
183
|
</div>
|
|
@@ -190,4 +193,4 @@ root.render(
|
|
|
190
193
|
<Playground />
|
|
191
194
|
</IntlProvider>
|
|
192
195
|
</Provider>
|
|
193
|
-
);
|
|
196
|
+
);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {updateIntl as superUpdateIntl} from 'react-intl-redux';
|
|
2
|
-
import {IntlProvider, intlReducer} from 'react-intl-redux';
|
|
1
|
+
import {updateIntl as superUpdateIntl, IntlProvider, intlReducer} from 'react-intl-redux';
|
|
3
2
|
|
|
4
3
|
import paintMessages from 'scratch-l10n/locales/paint-editor-msgs';
|
|
5
4
|
|
package/src/reducers/cursor.js
CHANGED
|
@@ -30,7 +30,7 @@ const reducer = function (state, action) {
|
|
|
30
30
|
/**
|
|
31
31
|
* Set the mouse cursor state to the given string
|
|
32
32
|
* @param {string} cursorString The CSS cursor string.
|
|
33
|
-
* @
|
|
33
|
+
* @returns {object} Redux action to change the cursor.
|
|
34
34
|
*/
|
|
35
35
|
const setCursor = function (cursorString) {
|
|
36
36
|
return {
|
package/src/reducers/hover.js
CHANGED
|
@@ -24,7 +24,7 @@ const reducer = function (state, action) {
|
|
|
24
24
|
/**
|
|
25
25
|
* Set the hovered item state to the given item ID
|
|
26
26
|
* @param {number} hoveredItemId The paper.Item ID of the hover indicator item.
|
|
27
|
-
* @
|
|
27
|
+
* @returns {object} Redux action to change the hovered item.
|
|
28
28
|
*/
|
|
29
29
|
const setHoveredItem = function (hoveredItemId) {
|
|
30
30
|
return {
|
package/src/reducers/layout.js
CHANGED
|
@@ -22,7 +22,7 @@ const reducer = function (state, action) {
|
|
|
22
22
|
/**
|
|
23
23
|
* Change the layout to the new layout
|
|
24
24
|
* @param {string} layout either 'ltr' or 'rtl'
|
|
25
|
-
* @
|
|
25
|
+
* @returns {object} Redux action to change the selected items.
|
|
26
26
|
*/
|
|
27
27
|
const setLayout = function (layout) {
|
|
28
28
|
return {
|
|
@@ -33,7 +33,7 @@ const reducer = function (state, action) {
|
|
|
33
33
|
* Set the selected item state to the given array of items
|
|
34
34
|
* @param {Array<paper.Item>} selectedItems from paper.project.selectedItems
|
|
35
35
|
* @param {?boolean} bitmapMode True if the items are being selected in bitmap mode
|
|
36
|
-
* @
|
|
36
|
+
* @returns {object} Redux action to change the selected items.
|
|
37
37
|
*/
|
|
38
38
|
const setSelectedItems = function (selectedItems, bitmapMode) {
|
|
39
39
|
return {
|
|
@@ -25,7 +25,7 @@ const reducer = function (state, action) {
|
|
|
25
25
|
* Set the currently-being-edited text field to the given item ID
|
|
26
26
|
* @param {?number} textEditTargetId The paper.Item ID of the active text field.
|
|
27
27
|
* Leave empty if there is no text editing target.
|
|
28
|
-
* @
|
|
28
|
+
* @returns {object} Redux action to change the text edit target.
|
|
29
29
|
*/
|
|
30
30
|
const setTextEditTarget = function (textEditTargetId) {
|
|
31
31
|
return {
|