img.height) {
- scale = this.refs.costumeCanvas.width / img.width;
+ scale = this.canvas.width / img.width;
} else {
- scale = this.refs.costumeCanvas.height / img.height;
+ scale = this.canvas.height / img.height;
}
+
// Rotate by the Scratch-value direction.
const angle = (-90 + this.props.direction) * Math.PI / 180;
+
// Rotation origin point will be center of the canvas.
- const contextTranslateX = this.refs.costumeCanvas.width / 2;
- const contextTranslateY = this.refs.costumeCanvas.height / 2;
+ const contextTranslateX = this.canvas.width / 2;
+ const contextTranslateY = this.canvas.height / 2;
+
// First, clear the canvas.
context.clearRect(0, 0,
- this.refs.costumeCanvas.width, this.refs.costumeCanvas.height);
+ this.canvas.width, this.canvas.height);
+
// Translate the context to the center of the canvas,
// then rotate canvas drawing by `angle`.
context.translate(contextTranslateX, contextTranslateY);
context.rotate(angle);
context.drawImage(img,
0, 0, img.width, img.height,
- -(scale * img.width / 2), -(scale * img.height / 2),
+ -(scale * img.width / 2), -(scale * img.height / 2),
scale * img.width,
scale * img.height);
+
// Reset the canvas rotation and translation to 0, (0, 0).
context.rotate(-angle);
context.translate(-contextTranslateX, -contextTranslateY);
@@ -72,8 +80,8 @@ class CostumeCanvas extends React.Component {
url: url
}, (err, response, body) => {
if (!err) {
- svgToImage(body, (err, img) => {
- if (!err) {
+ svgToImage(body, (svgErr, img) => {
+ if (!svgErr) {
this.img = img;
this.draw();
}
@@ -84,7 +92,7 @@ class CostumeCanvas extends React.Component {
} else {
// Raster graphics: create Image and draw it.
- let img = new Image();
+ const img = new Image();
img.src = url;
img.onload = () => {
this.img = img;
@@ -93,11 +101,13 @@ class CostumeCanvas extends React.Component {
}
}
render () {
- return
+ );
}
}
@@ -108,10 +118,10 @@ CostumeCanvas.defaultProps = {
};
CostumeCanvas.propTypes = {
- url: React.PropTypes.string,
- width: React.PropTypes.number,
+ direction: React.PropTypes.number,
height: React.PropTypes.number,
- direction: React.PropTypes.number
+ url: React.PropTypes.string,
+ width: React.PropTypes.number
};
module.exports = CostumeCanvas;
diff --git a/src/components/green-flag.js b/src/components/green-flag.jsx
similarity index 100%
rename from src/components/green-flag.js
rename to src/components/green-flag.jsx
diff --git a/src/components/gui.js b/src/components/gui.jsx
similarity index 100%
rename from src/components/gui.js
rename to src/components/gui.jsx
diff --git a/src/components/library-item.js b/src/components/library-item.jsx
similarity index 62%
rename from src/components/library-item.js
rename to src/components/library-item.jsx
index 39f65596a34..307bd97866f 100644
--- a/src/components/library-item.js
+++ b/src/components/library-item.jsx
@@ -1,13 +1,26 @@
+const bindAll = require('lodash.bindall');
const React = require('react');
+const stylePropType = require('react-style-proptype');
-const CostumeCanvas = require('./costume-canvas');
+const CostumeCanvas = require('./costume-canvas.jsx');
class LibraryItem extends React.Component {
+ constructor (props) {
+ super(props);
+ bindAll(this, ['handleClick']);
+ }
+ handleClick (e) {
+ this.props.onSelect(this.props.id);
+ e.preventDefault();
+ }
render () {
- let style = (this.props.selected) ?
+ const style = (this.props.selected) ?
this.props.selectedGridTileStyle : this.props.gridTileStyle;
return (
-
this.props.onSelect(this.props.id)}>
+
@@ -37,13 +50,13 @@ LibraryItem.defaultProps = {
};
LibraryItem.propTypes = {
- name: React.PropTypes.string,
+ gridTileStyle: stylePropType,
iconURL: React.PropTypes.string,
- gridTileStyle: React.PropTypes.object,
- selectedGridTileStyle: React.PropTypes.object,
- selected: React.PropTypes.bool,
+ id: React.PropTypes.number,
+ name: React.PropTypes.string,
onSelect: React.PropTypes.func,
- id: React.PropTypes.number
+ selected: React.PropTypes.bool,
+ selectedGridTileStyle: stylePropType
};
module.exports = LibraryItem;
diff --git a/src/components/library.js b/src/components/library.js
deleted file mode 100644
index f23f4b8267d..00000000000
--- a/src/components/library.js
+++ /dev/null
@@ -1,69 +0,0 @@
-const bindAll = require('lodash.bindall');
-const React = require('react');
-
-const LibraryItem = require('./library-item');
-const ModalComponent = require('./modal');
-
-class LibraryComponent extends React.Component {
- constructor (props) {
- super(props);
- bindAll(this, ['onSelect']);
- this.state = {selectedItem: null};
- }
- onSelect (id) {
- if (this.state.selectedItem == id) {
- // Double select: select as the library's value.
- this.props.onRequestClose();
- this.props.onItemSelected(this.props.data[id]);
- }
- this.setState({selectedItem: id});
- }
- render () {
- let itemId = 0;
- let gridItems = this.props.data.map((dataItem) => {
- let id = itemId;
- itemId++;
- const scratchURL = (dataItem.md5) ? 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' +
- dataItem.md5 + '/get/' : dataItem.rawURL;
- return
;
- });
-
- const scrollGridStyle = {
- overflow: 'scroll',
- position: 'absolute',
- top: '70px',
- bottom: '20px',
- left: '30px',
- right: '30px'
- };
-
- return (
-
- {this.props.title}
-
- {gridItems}
-
-
- );
- }
-}
-
-LibraryComponent.propTypes = {
- title: React.PropTypes.string,
- data: React.PropTypes.array,
- visible: React.PropTypes.bool,
- onRequestClose: React.PropTypes.func,
- onItemSelected: React.PropTypes.func
-};
-
-module.exports = LibraryComponent;
diff --git a/src/components/library.jsx b/src/components/library.jsx
new file mode 100644
index 00000000000..cc50b43eb02
--- /dev/null
+++ b/src/components/library.jsx
@@ -0,0 +1,74 @@
+const bindAll = require('lodash.bindall');
+const React = require('react');
+
+const LibraryItem = require('./library-item.jsx');
+const ModalComponent = require('./modal.jsx');
+
+class LibraryComponent extends React.Component {
+ constructor (props) {
+ super(props);
+ bindAll(this, ['handleSelect']);
+ this.state = {selectedItem: null};
+ }
+ handleSelect (id) {
+ if (this.state.selectedItem === id) {
+ // Double select: select as the library's value.
+ this.props.onRequestClose();
+ this.props.onItemSelected(this.props.data[id]);
+ }
+ this.setState({selectedItem: id});
+ }
+ render () {
+ const scrollGridStyle = {
+ overflow: 'scroll',
+ position: 'absolute',
+ top: '70px',
+ bottom: '20px',
+ left: '30px',
+ right: '30px'
+ };
+ return (
+
+ {this.props.title}
+
+ {this.props.data.map((dataItem, itemId) => {
+ const scratchURL = dataItem.md5 ?
+ `https://cdn.assets.scratch.mit.edu/internalapi/asset/${dataItem.md5}/get/` :
+ dataItem.rawURL;
+ return (
+
+ );
+ })}
+
+
+ );
+ }
+}
+
+LibraryComponent.propTypes = {
+ data: React.PropTypes.arrayOf(
+ /* eslint-disable react/no-unused-prop-types, lines-around-comment */
+ React.PropTypes.shape({
+ md5: React.PropTypes.string,
+ name: React.PropTypes.string,
+ rawURL: React.PropTypes.string,
+ })
+ /* eslint-enable react/no-unused-prop-types, lines-around-comment */
+ ),
+ onItemSelected: React.PropTypes.func,
+ onRequestClose: React.PropTypes.func,
+ title: React.PropTypes.string,
+ visible: React.PropTypes.bool
+};
+
+module.exports = LibraryComponent;
diff --git a/src/components/modal.js b/src/components/modal.jsx
similarity index 88%
rename from src/components/modal.js
rename to src/components/modal.jsx
index a2c25714964..9a6e58cc686 100644
--- a/src/components/modal.js
+++ b/src/components/modal.jsx
@@ -1,20 +1,21 @@
const React = require('react');
const ReactModal = require('react-modal');
+const stylePropType = require('react-style-proptype');
class ModalComponent extends React.Component {
render () {
return (
(this.modal = m)}
+ style={this.props.modalStyle}
onRequestClose={this.props.onRequestClose}
>
- x
+ {'x'}
{this.props.children}
@@ -61,8 +62,8 @@ ModalComponent.defaultProps = {
ModalComponent.propTypes = {
children: React.PropTypes.node,
- modalStyle: React.PropTypes.object,
- closeButtonStyle: React.PropTypes.object,
+ closeButtonStyle: stylePropType,
+ modalStyle: stylePropType,
onRequestClose: React.PropTypes.func,
visible: React.PropTypes.bool
};
diff --git a/src/components/sprite-selector.js b/src/components/sprite-selector.jsx
similarity index 85%
rename from src/components/sprite-selector.js
rename to src/components/sprite-selector.jsx
index da00622bf8f..fd2807c2218 100644
--- a/src/components/sprite-selector.js
+++ b/src/components/sprite-selector.jsx
@@ -26,7 +26,10 @@ class SpriteSelectorComponent extends React.Component {
onChange={onChange}
>
{sprites.map(sprite => (
-
))}
@@ -43,16 +46,16 @@ class SpriteSelectorComponent extends React.Component {
SpriteSelectorComponent.propTypes = {
onChange: React.PropTypes.func,
+ openNewBackdrop: React.PropTypes.func,
+ openNewCostume: React.PropTypes.func,
+ openNewSprite: React.PropTypes.func,
sprites: React.PropTypes.arrayOf(
React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string
})
),
- value: React.PropTypes.arrayOf(React.PropTypes.string),
- openNewSprite: React.PropTypes.func,
- openNewCostume: React.PropTypes.func,
- openNewBackdrop: React.PropTypes.func
+ value: React.PropTypes.arrayOf(React.PropTypes.string)
};
module.exports = SpriteSelectorComponent;
diff --git a/src/components/stage.js b/src/components/stage.jsx
similarity index 88%
rename from src/components/stage.js
rename to src/components/stage.jsx
index 89cfa4d1562..9f4f3a4584e 100644
--- a/src/components/stage.js
+++ b/src/components/stage.jsx
@@ -27,12 +27,12 @@ class StageComponent extends React.Component {
StageComponent.propTypes = {
canvasRef: React.PropTypes.func,
- width: React.PropTypes.number,
- height: React.PropTypes.number
+ height: React.PropTypes.number,
+ width: React.PropTypes.number
};
StageComponent.defaultProps = {
- canvasRef: function () {},
+ canvasRef: () => {},
width: 480,
height: 360
};
diff --git a/src/components/stop-all.js b/src/components/stop-all.jsx
similarity index 100%
rename from src/components/stop-all.js
rename to src/components/stop-all.jsx
diff --git a/src/containers/backdrop-library.js b/src/containers/backdrop-library.jsx
similarity index 60%
rename from src/containers/backdrop-library.js
rename to src/containers/backdrop-library.jsx
index bcac13b5237..ace824bead4 100644
--- a/src/containers/backdrop-library.js
+++ b/src/containers/backdrop-library.jsx
@@ -3,13 +3,13 @@ const React = require('react');
const VM = require('scratch-vm');
const MediaLibrary = require('../lib/media-library');
-const LibaryComponent = require('../components/library');
+const LibaryComponent = require('../components/library.jsx');
class BackdropLibrary extends React.Component {
constructor (props) {
super(props);
- bindAll(this, ['setData', 'selectItem']);
+ bindAll(this, ['setData', 'handleItemSelect']);
this.state = {backdropData: []};
}
componentWillReceiveProps (nextProps) {
@@ -20,9 +20,9 @@ class BackdropLibrary extends React.Component {
setData (data) {
this.setState({backdropData: data});
}
- selectItem (item) {
- var vmBackdrop = {
- skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' + item.md5 + '/get/',
+ handleItemSelect (item) {
+ const vmBackdrop = {
+ skin: `https://cdn.assets.scratch.mit.edu/internalapi/asset/${item.md5}/get/`,
name: item.name,
rotationCenterX: item.info[0],
rotationCenterY: item.info[1]
@@ -33,21 +33,23 @@ class BackdropLibrary extends React.Component {
this.props.vm.addBackdrop(vmBackdrop);
}
render () {
- return
;
+ return (
+
+ );
}
}
BackdropLibrary.propTypes = {
- vm: React.PropTypes.instanceOf(VM).isRequired,
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
+ onRequestClose: React.PropTypes.func,
visible: React.PropTypes.bool,
- onRequestClose: React.PropTypes.func
+ vm: React.PropTypes.instanceOf(VM).isRequired
};
module.exports = BackdropLibrary;
diff --git a/src/containers/blocks.js b/src/containers/blocks.jsx
similarity index 91%
rename from src/containers/blocks.js
rename to src/containers/blocks.jsx
index c9f07ce1386..a5977a9f76c 100644
--- a/src/containers/blocks.js
+++ b/src/containers/blocks.jsx
@@ -4,7 +4,7 @@ const React = require('react');
const ScratchBlocks = require('scratch-blocks');
const VM = require('scratch-vm');
-const BlocksComponent = require('../components/blocks');
+const BlocksComponent = require('../components/blocks.jsx');
class Blocks extends React.Component {
constructor (props) {
@@ -21,7 +21,7 @@ class Blocks extends React.Component {
]);
}
componentDidMount () {
- let workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options);
+ const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options);
this.workspace = ScratchBlocks.inject(this.blocks, workspaceConfig);
this.attachVM();
}
@@ -31,9 +31,10 @@ class Blocks extends React.Component {
}
attachVM () {
this.workspace.addChangeListener(this.props.vm.blockListener);
- this.workspace.getFlyout().getWorkspace().addChangeListener(
- this.props.vm.flyoutBlockListener
- );
+ this.workspace
+ .getFlyout()
+ .getWorkspace()
+ .addChangeListener(this.props.vm.flyoutBlockListener);
this.props.vm.on('STACK_GLOW_ON', this.onStackGlowOn);
this.props.vm.on('STACK_GLOW_OFF', this.onStackGlowOff);
this.props.vm.on('BLOCK_GLOW_ON', this.onBlockGlowOn);
@@ -79,7 +80,7 @@ class Blocks extends React.Component {
} = this.props;
return (
this.blocks = c}
+ componentRef={c => (this.blocks = c)}
{...props}
/>
);
diff --git a/src/containers/costume-library.js b/src/containers/costume-library.jsx
similarity index 60%
rename from src/containers/costume-library.js
rename to src/containers/costume-library.jsx
index 091a736ffbb..07a09011f87 100644
--- a/src/containers/costume-library.js
+++ b/src/containers/costume-library.jsx
@@ -3,13 +3,13 @@ const React = require('react');
const VM = require('scratch-vm');
const MediaLibrary = require('../lib/media-library');
-const LibaryComponent = require('../components/library');
+const LibaryComponent = require('../components/library.jsx');
class CostumeLibrary extends React.Component {
constructor (props) {
super(props);
- bindAll(this, ['setData', 'selectItem']);
+ bindAll(this, ['setData', 'handleItemSelected']);
this.state = {costumeData: []};
}
componentWillReceiveProps (nextProps) {
@@ -20,9 +20,9 @@ class CostumeLibrary extends React.Component {
setData (data) {
this.setState({costumeData: data});
}
- selectItem (item) {
- var vmCostume = {
- skin: 'https://cdn.assets.scratch.mit.edu/internalapi/asset/' + item.md5 + '/get/',
+ handleItemSelected (item) {
+ const vmCostume = {
+ skin: `https://cdn.assets.scratch.mit.edu/internalapi/asset/$(item.md5)/get/`,
name: item.name,
rotationCenterX: item.info[0],
rotationCenterY: item.info[1]
@@ -33,21 +33,23 @@ class CostumeLibrary extends React.Component {
this.props.vm.addCostume(vmCostume);
}
render () {
- return ;
+ return (
+
+ );
}
}
CostumeLibrary.propTypes = {
- vm: React.PropTypes.instanceOf(VM).isRequired,
mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
+ onRequestClose: React.PropTypes.func,
visible: React.PropTypes.bool,
- onRequestClose: React.PropTypes.func
+ vm: React.PropTypes.instanceOf(VM).isRequired
};
module.exports = CostumeLibrary;
diff --git a/src/containers/green-flag.js b/src/containers/green-flag.jsx
similarity index 68%
rename from src/containers/green-flag.js
rename to src/containers/green-flag.jsx
index 233313b7950..0d8cd2f8609 100644
--- a/src/containers/green-flag.js
+++ b/src/containers/green-flag.jsx
@@ -1,14 +1,16 @@
const bindAll = require('lodash.bindall');
const React = require('react');
-const GreenFlagComponent = require('../components/green-flag');
+const VM = require('scratch-vm');
+
+const GreenFlagComponent = require('../components/green-flag.jsx');
class GreenFlag extends React.Component {
constructor (props) {
super(props);
- bindAll(this, ['onClick']);
+ bindAll(this, ['handleClick']);
}
- onClick (e) {
+ handleClick (e) {
e.preventDefault();
this.props.vm.greenFlag();
}
@@ -19,7 +21,7 @@ class GreenFlag extends React.Component {
} = this.props;
return (
);
@@ -27,7 +29,7 @@ class GreenFlag extends React.Component {
}
GreenFlag.propTypes = {
- vm: React.PropTypes.object
+ vm: React.PropTypes.instanceOf(VM)
};
module.exports = GreenFlag;
diff --git a/src/containers/gui.js b/src/containers/gui.jsx
similarity index 58%
rename from src/containers/gui.js
rename to src/containers/gui.jsx
index 0ab742034fa..ffde713512d 100644
--- a/src/containers/gui.js
+++ b/src/containers/gui.jsx
@@ -5,17 +5,18 @@ const VM = require('scratch-vm');
const VMManager = require('../lib/vm-manager');
const MediaLibrary = require('../lib/media-library');
+const shapeFromPropTypes = require('../lib/shape-from-prop-types');
-const Blocks = require('./blocks');
-const GUIComponent = require('../components/gui');
-const GreenFlag = require('./green-flag');
-const SpriteSelector = require('./sprite-selector');
-const Stage = require('./stage');
-const StopAll = require('./stop-all');
+const Blocks = require('./blocks.jsx');
+const GUIComponent = require('../components/gui.jsx');
+const GreenFlag = require('./green-flag.jsx');
+const SpriteSelector = require('./sprite-selector.jsx');
+const Stage = require('./stage.jsx');
+const StopAll = require('./stop-all.jsx');
-const SpriteLibrary = require('./sprite-library');
-const CostumeLibrary = require('./costume-library');
-const BackdropLibrary = require('./backdrop-library');
+const SpriteLibrary = require('./sprite-library.jsx');
+const CostumeLibrary = require('./costume-library.jsx');
+const BackdropLibrary = require('./backdrop-library.jsx');
class GUI extends React.Component {
constructor (props) {
@@ -30,15 +31,15 @@ class GUI extends React.Component {
this.props.vm.loadProject(this.props.projectData);
this.props.vm.start();
}
- componentWillUnmount () {
- this.vmManager.detachKeyboardEvents();
- this.props.vm.stopAll();
- }
componentWillReceiveProps (nextProps) {
if (this.props.projectData !== nextProps.projectData) {
this.props.vm.loadProject(nextProps.projectData);
}
}
+ componentWillUnmount () {
+ this.vmManager.detachKeyboardEvents();
+ this.props.vm.stopAll();
+ }
openModal (modalName) {
this.setState({currentModal: modalName});
}
@@ -60,30 +61,30 @@ class GUI extends React.Component {
vm,
...guiProps
} = this.props;
+ backdropLibraryProps = defaultsDeep({}, backdropLibraryProps, {
+ mediaLibrary: this.mediaLibrary,
+ onRequestClose: this.closeModal,
+ visible: this.state.currentModal === 'backdrop-library'
+ });
blocksProps = defaultsDeep({}, blocksProps, {
options: {
- media: basePath + 'static/blocks-media/'
+ media: `${basePath}static/blocks-media/`
}
});
- spriteSelectorProps = defaultsDeep({}, spriteSelectorProps, {
- openNewBackdrop: () => this.openModal('backdrop-library'),
- openNewCostume: () => this.openModal('costume-library'),
- openNewSprite: () => this.openModal('sprite-library')
- });
- spriteLibraryProps = defaultsDeep({}, spriteLibraryProps, {
- mediaLibrary: this.mediaLibrary,
- onRequestClose: this.closeModal,
- visible: this.state.currentModal == 'sprite-library'
- });
costumeLibraryProps = defaultsDeep({}, costumeLibraryProps, {
mediaLibrary: this.mediaLibrary,
onRequestClose: this.closeModal,
- visible: this.state.currentModal == 'costume-library'
+ visible: this.state.currentModal === 'costume-library'
});
- backdropLibraryProps = defaultsDeep({}, backdropLibraryProps, {
+ spriteLibraryProps = defaultsDeep({}, spriteLibraryProps, {
mediaLibrary: this.mediaLibrary,
onRequestClose: this.closeModal,
- visible: this.state.currentModal == 'backdrop-library'
+ visible: this.state.currentModal === 'sprite-library'
+ });
+ spriteSelectorProps = defaultsDeep({}, spriteSelectorProps, {
+ openNewBackdrop: () => this.openModal('backdrop-library'),
+ openNewCostume: () => this.openModal('costume-library'),
+ openNewSprite: () => this.openModal('sprite-library')
});
if (this.props.children) {
return (
@@ -91,36 +92,37 @@ class GUI extends React.Component {
{this.props.children}
);
- } else {
- return (
-
-
-
-
-
-
-
-
-
-
- );
}
+ /* eslint-disable react/jsx-max-props-per-line, lines-around-comment */
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+ /* eslint-enable react/jsx-max-props-per-line, lines-around-comment */
}
}
GUI.propTypes = {
- backdropLibraryProps: React.PropTypes.object,
+ backdropLibraryProps: shapeFromPropTypes(BackdropLibrary.propTypes, {omit: ['vm']}),
basePath: React.PropTypes.string,
- blocksProps: React.PropTypes.object,
- costumeLibraryProps: React.PropTypes.object,
+ blocksProps: shapeFromPropTypes(Blocks.propTypes, {omit: ['vm']}),
children: React.PropTypes.node,
- greenFlagProps: React.PropTypes.object,
+ costumeLibraryProps: shapeFromPropTypes(CostumeLibrary.propTypes, {omit: ['vm']}),
+ greenFlagProps: shapeFromPropTypes(GreenFlag.propTypes, {omit: ['vm']}),
projectData: React.PropTypes.string,
- spriteLibraryProps: React.PropTypes.object,
- spriteSelectorProps: React.PropTypes.object,
- stageProps: React.PropTypes.object,
- stopAllProps: React.PropTypes.object,
- vm: React.PropTypes.object,
+ spriteLibraryProps: shapeFromPropTypes(SpriteLibrary.propTypes, {omit: ['vm']}),
+ spriteSelectorProps: shapeFromPropTypes(SpriteSelector.propTypes, {omit: ['vm']}),
+ stageProps: shapeFromPropTypes(Stage.propTypes, {omit: ['vm']}),
+ stopAllProps: shapeFromPropTypes(StopAll.propTypes, {omit: ['vm']}),
+ vm: React.PropTypes.instanceOf(VM),
};
GUI.defaultProps = {
diff --git a/src/containers/sprite-library.js b/src/containers/sprite-library.js
deleted file mode 100644
index 602fb177609..00000000000
--- a/src/containers/sprite-library.js
+++ /dev/null
@@ -1,61 +0,0 @@
-const bindAll = require('lodash.bindall');
-const React = require('react');
-const VM = require('scratch-vm');
-const MediaLibrary = require('../lib/media-library');
-
-const LibaryComponent = require('../components/library');
-
-class SpriteLibrary extends React.Component {
- constructor (props) {
- super(props);
- bindAll(this, ['setData', 'selectItem', 'setSpriteData']);
- this.state = {data: [], spriteData: {}};
- }
- componentWillReceiveProps (nextProps) {
- if (nextProps.visible && this.state.data.length === 0) {
- this.props.mediaLibrary.getMediaLibrary('sprite', this.setData);
- }
- }
- setData (data) {
- this.setState({data: data});
- for (let sprite of data) {
- this.props.mediaLibrary.getSprite(sprite.md5, this.setSpriteData);
- }
- }
- setSpriteData (md5, data) {
- let spriteData = this.state.spriteData;
- spriteData[md5] = data;
- this.setState({spriteData: spriteData});
- }
- selectItem (item) {
- var spriteData = JSON.stringify(this.state.spriteData[item.json]);
- this.props.vm.addSprite2(spriteData);
- }
- render () {
- let libraryData = Object.keys(this.state.spriteData).map((libraryKey) => {
- let libraryItem = this.state.spriteData[libraryKey];
- return {
- name: libraryItem.objName,
- md5: libraryItem.costumes[0].baseLayerMD5,
- json: libraryKey
- };
- });
- return ;
- }
-}
-
-SpriteLibrary.propTypes = {
- vm: React.PropTypes.instanceOf(VM).isRequired,
- mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
- visible: React.PropTypes.bool,
- onRequestClose: React.PropTypes.func
-};
-
-module.exports = SpriteLibrary;
diff --git a/src/containers/sprite-library.jsx b/src/containers/sprite-library.jsx
new file mode 100644
index 00000000000..9f2cb0a67cd
--- /dev/null
+++ b/src/containers/sprite-library.jsx
@@ -0,0 +1,62 @@
+const bindAll = require('lodash.bindall');
+const React = require('react');
+const VM = require('scratch-vm');
+const MediaLibrary = require('../lib/media-library');
+
+const LibaryComponent = require('../components/library.jsx');
+
+class SpriteLibrary extends React.Component {
+ constructor (props) {
+ super(props);
+ bindAll(this, ['setData', 'handleItemSelect', 'setSpriteData']);
+ this.state = {data: [], spriteData: {}};
+ }
+ componentWillReceiveProps (nextProps) {
+ if (nextProps.visible && this.state.data.length === 0) {
+ this.props.mediaLibrary.getMediaLibrary('sprite', this.setData);
+ }
+ }
+ setData (data) {
+ this.setState({data: data});
+ for (const sprite of data) {
+ this.props.mediaLibrary.getSprite(sprite.md5, this.setSpriteData);
+ }
+ }
+ setSpriteData (md5, data) {
+ this.setState({
+ spriteData: Object.assign({}, this.state.spriteData, {[md5]: data})
+ });
+ }
+ handleItemSelect (item) {
+ const spriteData = JSON.stringify(this.state.spriteData[item.json]);
+ this.props.vm.addSprite2(spriteData);
+ }
+ render () {
+ return (
+ {
+ const libraryItem = this.state.spriteData[libraryKey];
+ return {
+ name: libraryItem.objName,
+ md5: libraryItem.costumes[0].baseLayerMD5,
+ json: libraryKey
+ };
+ })}
+ mediaLibrary={this.props.mediaLibrary}
+ title="Sprite Library"
+ visible={this.props.visible}
+ onItemSelected={this.handleItemSelect}
+ onRequestClose={this.props.onRequestClose}
+ />
+ );
+ }
+}
+
+SpriteLibrary.propTypes = {
+ mediaLibrary: React.PropTypes.instanceOf(MediaLibrary),
+ onRequestClose: React.PropTypes.func,
+ visible: React.PropTypes.bool,
+ vm: React.PropTypes.instanceOf(VM).isRequired
+};
+
+module.exports = SpriteLibrary;
diff --git a/src/containers/sprite-selector.js b/src/containers/sprite-selector.jsx
similarity index 85%
rename from src/containers/sprite-selector.js
rename to src/containers/sprite-selector.jsx
index c30ac713784..52beebd1c47 100644
--- a/src/containers/sprite-selector.js
+++ b/src/containers/sprite-selector.jsx
@@ -1,12 +1,13 @@
const bindAll = require('lodash.bindall');
const React = require('react');
+const VM = require('scratch-vm');
-const SpriteSelectorComponent = require('../components/sprite-selector');
+const SpriteSelectorComponent = require('../components/sprite-selector.jsx');
class SpriteSelector extends React.Component {
constructor (props) {
super(props);
- bindAll(this, ['onChange', 'targetsUpdate']);
+ bindAll(this, ['handleChange', 'targetsUpdate']);
this.state = {
targets: {
targetList: []
@@ -16,7 +17,7 @@ class SpriteSelector extends React.Component {
componentDidMount () {
this.props.vm.on('targetsUpdate', this.targetsUpdate);
}
- onChange (event) {
+ handleChange (event) {
this.props.vm.setEditingTarget(event.target.value);
}
targetsUpdate (data) {
@@ -32,17 +33,17 @@ class SpriteSelector extends React.Component {
} = this.props;
return (
(
{
id: target[0],
name: target[1]
}
))}
+ value={this.state.targets.editingTarget && [this.state.targets.editingTarget]}
+ onChange={this.handleChange}
{...props}
/>
);
@@ -50,10 +51,10 @@ class SpriteSelector extends React.Component {
}
SpriteSelector.propTypes = {
- vm: React.PropTypes.object.isRequired,
- openNewSprite: React.PropTypes.func,
+ openNewBackdrop: React.PropTypes.func,
openNewCostume: React.PropTypes.func,
- openNewBackdrop: React.PropTypes.func
+ openNewSprite: React.PropTypes.func,
+ vm: React.PropTypes.instanceOf(VM)
};
module.exports = SpriteSelector;
diff --git a/src/containers/stage.js b/src/containers/stage.jsx
similarity index 88%
rename from src/containers/stage.js
rename to src/containers/stage.jsx
index 3a195ccf77a..b65ea90cb68 100644
--- a/src/containers/stage.js
+++ b/src/containers/stage.jsx
@@ -3,7 +3,7 @@ const React = require('react');
const Renderer = require('scratch-render');
const VM = require('scratch-vm');
-const StageComponent = require('../components/stage');
+const StageComponent = require('../components/stage.jsx');
class Stage extends React.Component {
constructor (props) {
@@ -40,8 +40,8 @@ class Stage extends React.Component {
canvas.removeEventListener('mousedown', this.onMouseDown);
}
onMouseMove (e) {
- let rect = this.canvas.getBoundingClientRect();
- let coordinates = {
+ const rect = this.canvas.getBoundingClientRect();
+ const coordinates = {
x: e.clientX - rect.left,
y: e.clientY - rect.top,
canvasWidth: rect.width,
@@ -50,8 +50,8 @@ class Stage extends React.Component {
this.props.vm.postIOData('mouse', coordinates);
}
onMouseUp (e) {
- let rect = this.canvas.getBoundingClientRect();
- let data = {
+ const rect = this.canvas.getBoundingClientRect();
+ const data = {
isDown: false,
x: e.clientX - rect.left,
y: e.clientY - rect.top,
@@ -62,8 +62,8 @@ class Stage extends React.Component {
e.preventDefault();
}
onMouseDown (e) {
- let rect = this.canvas.getBoundingClientRect();
- let data = {
+ const rect = this.canvas.getBoundingClientRect();
+ const data = {
isDown: true,
x: e.clientX - rect.left,
y: e.clientY - rect.top,
@@ -90,7 +90,7 @@ class Stage extends React.Component {
} = this.props;
return (
this.canvas = canvas}
+ canvasRef={canvas => (this.canvas = canvas)}
{...props}
/>
);
diff --git a/src/containers/stop-all.js b/src/containers/stop-all.jsx
similarity index 68%
rename from src/containers/stop-all.js
rename to src/containers/stop-all.jsx
index 9b4f0f95d41..2f504b7eab5 100644
--- a/src/containers/stop-all.js
+++ b/src/containers/stop-all.jsx
@@ -1,14 +1,15 @@
const bindAll = require('lodash.bindall');
const React = require('react');
+const VM = require('scratch-vm');
-const StopAllComponent = require('../components/stop-all');
+const StopAllComponent = require('../components/stop-all.jsx');
class StopAll extends React.Component {
constructor (props) {
super(props);
- bindAll(this, ['onClick']);
+ bindAll(this, ['handleClick']);
}
- onClick (e) {
+ handleClick (e) {
e.preventDefault();
this.props.vm.stopAll();
}
@@ -19,7 +20,7 @@ class StopAll extends React.Component {
} = this.props;
return (
);
@@ -27,7 +28,7 @@ class StopAll extends React.Component {
}
StopAll.propTypes = {
- vm: React.PropTypes.object
+ vm: React.PropTypes.instanceOf(VM)
};
module.exports = StopAll;
diff --git a/src/index.js b/src/index.jsx
similarity index 94%
rename from src/index.js
rename to src/index.jsx
index 573f3a98388..7f2d8c07319 100644
--- a/src/index.js
+++ b/src/index.jsx
@@ -1,6 +1,6 @@
const React = require('react');
const ReactDOM = require('react-dom');
-const GUI = require('./containers/gui');
+const GUI = require('./containers/gui.jsx');
const log = require('./lib/log');
const ProjectLoader = require('./lib/project-loader');
@@ -25,7 +25,7 @@ class App extends React.Component {
return location.hash.substring(1);
}
updateProject () {
- let projectId = this.fetchProjectId();
+ const projectId = this.fetchProjectId();
if (projectId !== this.state.projectId) {
if (projectId.length < 1) {
return this.setState({
diff --git a/src/lib/log.js b/src/lib/log.js
index 9a364044f21..ab38732b175 100644
--- a/src/lib/log.js
+++ b/src/lib/log.js
@@ -1,4 +1,4 @@
-var minilog = require('minilog');
+const minilog = require('minilog');
minilog.enable();
-module.exports = minilog('www');
+module.exports = minilog('gui');
diff --git a/src/lib/media-library.js b/src/lib/media-library.js
index 6f33b25c919..6e2d122495e 100644
--- a/src/lib/media-library.js
+++ b/src/lib/media-library.js
@@ -3,9 +3,9 @@ const xhr = require('xhr');
const LIBRARY_PREFIX = 'https://cdn.scratch.mit.edu/scratchr2/static/' +
'__8d9c95eb5aa1272a311775ca32568417__/medialibraries/';
const LIBRARY_URL = {
- sprite: LIBRARY_PREFIX + 'spriteLibrary.json',
- costume: LIBRARY_PREFIX + 'costumeLibrary.json',
- backdrop: LIBRARY_PREFIX + 'backdropLibrary.json'
+ sprite: `${LIBRARY_PREFIX}spriteLibrary.json`,
+ costume: `${LIBRARY_PREFIX}costumeLibrary.json`,
+ backdrop: `${LIBRARY_PREFIX}backdropLibrary.json`
};
const SPRITE_OBJECT_PREFIX = 'https://cdn.assets.scratch.mit.edu/internalapi/asset/';
const SPRITE_OBJECT_SUFFIX = '/get/';
@@ -44,7 +44,7 @@ class MediaLibrary {
url: LIBRARY_URL[libraryType]
}, (err, response, body) => {
if (!err) {
- let data = JSON.parse(body);
+ const data = JSON.parse(body);
this._libraryData[libraryType] = data;
callback(this._libraryData[libraryType]);
}
@@ -68,7 +68,7 @@ class MediaLibrary {
url: SPRITE_OBJECT_PREFIX + url + SPRITE_OBJECT_SUFFIX
}, (err, response, body) => {
if (!err) {
- let data = JSON.parse(body);
+ const data = JSON.parse(body);
this._spriteData[url] = data;
callback(url, data);
}
diff --git a/src/lib/shape-from-prop-types.js b/src/lib/shape-from-prop-types.js
new file mode 100644
index 00000000000..2d2415e1c84
--- /dev/null
+++ b/src/lib/shape-from-prop-types.js
@@ -0,0 +1,13 @@
+const React = require('react');
+
+module.exports = function shapeFromPropTypes (propTypes, opts) {
+ opts = Object.assign({}, opts, {omit: []});
+ const shape = Object
+ .keys(propTypes)
+ .filter(key => opts.omit.indexOf(key) !== -1)
+ .reduce((newPropTypes, key) => {
+ newPropTypes[key] = propTypes[key];
+ return newPropTypes;
+ }, {});
+ return React.PropTypes.shape(shape);
+};
diff --git a/src/lib/vm-manager.js b/src/lib/vm-manager.js
index db521c99f50..8da19206226 100644
--- a/src/lib/vm-manager.js
+++ b/src/lib/vm-manager.js
@@ -21,7 +21,7 @@ class VMManager {
}
onKeyDown (e) {
// Don't capture keys intended for Blockly inputs.
- if (e.target != document && e.target != document.body) {
+ if (e.target !== document && e.target !== document.body) {
return;
}
this.vm.postIOData('keyboard', {
@@ -37,8 +37,9 @@ class VMManager {
keyCode: e.keyCode,
isDown: false
});
+
// E.g., prevent scroll.
- if (e.target != document && e.target != document.body) {
+ if (e.target !== document && e.target !== document.body) {
e.preventDefault();
}
}
diff --git a/webpack.config.js b/webpack.config.js
index 324f7c57b39..67a39f865db 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -2,10 +2,11 @@ var path = require('path');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var webpack = require('webpack');
+
module.exports = {
entry: {
vendor: ['react', 'react-dom'],
- gui: './src/index.js'
+ gui: './src/index.jsx'
},
output: {
path: path.resolve(__dirname, 'build'),
@@ -17,7 +18,7 @@ module.exports = {
ReactDOM: 'react-dom'
},
loaders: [{
- test: /\.js$/,
+ test: /\.jsx?$/,
loader: 'babel-loader',
include: path.resolve(__dirname, 'src'),
query: {
@@ -45,7 +46,7 @@ module.exports = {
from: 'node_modules/scratch-blocks/media',
to: 'static/blocks-media'
}])
- ].concat(process.env.NODE_ENV == 'production' ? [
+ ].concat(process.env.NODE_ENV === 'production' ? [
new webpack.optimize.UglifyJsPlugin({
include: /\.min\.js$/,
minimize: true,