diff --git a/src/components/blocks/blocks.css b/src/components/blocks/blocks.css index 3d00662496..657bdf9be0 100644 --- a/src/components/blocks/blocks.css +++ b/src/components/blocks/blocks.css @@ -1,7 +1,7 @@ -.blocks { +.blocks :global(.injectionDiv){ position: absolute; - top: 40px; - right: 500px; + top: 0; + right: 0; bottom: 0; left: 0; } diff --git a/src/components/blocks/blocks.jsx b/src/components/blocks/blocks.jsx index fa00102abe..786d060c11 100644 --- a/src/components/blocks/blocks.jsx +++ b/src/components/blocks/blocks.jsx @@ -1,25 +1,21 @@ const React = require('react'); - +const Box = require('../box/box.jsx'); const styles = require('./blocks.css'); -class BlocksComponent extends React.Component { - render () { - const { - componentRef, - ...props - } = this.props; - return ( -
- ); - } -} - +const BlocksComponent = props => { + const { + componentRef, + ...componentProps + } = props; + return ( + + ); +}; BlocksComponent.propTypes = { componentRef: React.PropTypes.func }; - module.exports = BlocksComponent; diff --git a/src/components/box/box.css b/src/components/box/box.css new file mode 100644 index 0000000000..9581e0c423 --- /dev/null +++ b/src/components/box/box.css @@ -0,0 +1,4 @@ +.box { + display: flex; + position: relative; +} diff --git a/src/components/box/box.jsx b/src/components/box/box.jsx new file mode 100644 index 0000000000..7afee654d8 --- /dev/null +++ b/src/components/box/box.jsx @@ -0,0 +1,119 @@ +const classNames = require('classnames'); +const React = require('react'); +const stylePropType = require('react-style-proptype'); +const styles = require('./box.css'); + +const getRandomColor = (function () { + // In "DEBUG" mode this is used to output a random background color for each + // box. The function gives the same "random" set for each seed, allowing re- + // renders of the same content to give the same random display. + const random = (function (seed) { + let mW = seed; + let mZ = 987654321; + const mask = 0xffffffff; + return function () { + mZ = ((36969 * (mZ & 65535)) + (mZ >> 16)) & mask; + mW = ((18000 * (mW & 65535)) + (mW >> 16)) & mask; + let result = ((mZ << 16) + mW) & mask; + result /= 4294967296; + return result + 1; + }; + }(601)); + return function () { + const r = Math.max(parseInt(random() * 100, 10) % 256, 1); + const g = Math.max(parseInt(random() * 100, 10) % 256, 1); + const b = Math.max(parseInt(random() * 100, 10) % 256, 1); + return `rgb(${r},${g},${b})`; + }; +}()); + +const Box = props => { + const { + alignContent, + alignItems, + alignSelf, + basis, + children, + className, + componentRef, + direction, + element, + grow, + height, + justifyContent, + width, + wrap, + shrink, + style, + ...componentProps + } = props; + return React.createElement(element, { + className: classNames(styles.box, className), + ref: componentRef, + style: Object.assign( + { + alignContent: alignContent, + alignItems: alignItems, + alignSelf: alignSelf, + flexBasis: basis, + flexDirection: direction, + flexGrow: grow, + flexShrink: shrink, + flexWrap: wrap, + justifyContent: justifyContent, + width: width, + height: height + }, + process.env.DEBUG ? { + backgroundColor: getRandomColor(), + outline: `1px solid black` + } : {}, + style + ), + ...componentProps + }, children); +}; +Box.propTypes = { + alignContent: React.PropTypes.oneOf([ + 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'stretch' + ]), + alignItems: React.PropTypes.oneOf([ + 'flex-start', 'flex-end', 'center', 'baseline', 'stretch' + ]), + alignSelf: React.PropTypes.oneOf([ + 'auto', 'flex-start', 'flex-end', 'center', 'baseline', 'stretch' + ]), + basis: React.PropTypes.oneOfType([ + React.PropTypes.number, + React.PropTypes.oneOf(['auto']) + ]), + children: React.PropTypes.node, + className: React.PropTypes.string, + componentRef: React.PropTypes.func, + direction: React.PropTypes.oneOf([ + 'row', 'row-reverse', 'column', 'column-reverse' + ]), + element: React.PropTypes.string, + grow: React.PropTypes.number, + height: React.PropTypes.oneOfType([ + React.PropTypes.number, + React.PropTypes.string + ]), + justifyContent: React.PropTypes.oneOf([ + 'flex-start', 'flex-end', 'center', 'space-between', 'space-around' + ]), + shrink: React.PropTypes.number, + style: stylePropType, + width: React.PropTypes.oneOfType([ + React.PropTypes.number, + React.PropTypes.string + ]), + wrap: React.PropTypes.oneOf([ + 'nowrap', 'wrap', 'wrap-reverse' + ]) +}; +Box.defaultProps = { + element: 'div', + style: {} +}; +module.exports = Box; diff --git a/src/components/green-flag/green-flag.css b/src/components/green-flag/green-flag.css index b8000e4827..1931b2d218 100644 --- a/src/components/green-flag/green-flag.css +++ b/src/components/green-flag/green-flag.css @@ -1,11 +1,7 @@ .green-flag { - position: absolute; - top: 8px; - right: calc(480px - 16px); width: 16px; height: 16px; } - -.active { +.green-flag.is-active { filter: saturate(200%) brightness(150%); } diff --git a/src/components/green-flag/green-flag.jsx b/src/components/green-flag/green-flag.jsx index f1b24b1516..a5642641a8 100644 --- a/src/components/green-flag/green-flag.jsx +++ b/src/components/green-flag/green-flag.jsx @@ -15,7 +15,7 @@ const GreenFlagComponent = function (props) { ); }; - GreenFlagComponent.propTypes = { active: React.PropTypes.bool, onClick: React.PropTypes.func, title: React.PropTypes.string }; - GreenFlagComponent.defaultProps = { active: false, title: 'Go' }; - module.exports = GreenFlagComponent; diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css deleted file mode 100644 index 78b6f009ac..0000000000 --- a/src/components/gui/gui.css +++ /dev/null @@ -1,7 +0,0 @@ -.gui { - position: absolute; - top: 0; - right: 4px; - bottom: 0; - left: 4px; -} diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 31e5e6ae2d..c929d9b4ee 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -2,7 +2,6 @@ const defaultsDeep = require('lodash.defaultsdeep'); const React = require('react'); const VM = require('scratch-vm'); -const MediaLibrary = require('../../lib/media-library'); const shapeFromPropTypes = require('../../lib/shape-from-prop-types'); const Blocks = require('../../containers/blocks.jsx'); @@ -11,7 +10,7 @@ const TargetPane = require('../../containers/target-pane.jsx'); const Stage = require('../../containers/stage.jsx'); const StopAll = require('../../containers/stop-all.jsx'); -const styles = require('./gui.css'); +const Box = require('../box/box.jsx'); const GUIComponent = props => { let { @@ -19,7 +18,6 @@ const GUIComponent = props => { blocksProps, children, greenFlagProps, - mediaLibrary, targetPaneProps, stageProps, stopAllProps, @@ -32,59 +30,88 @@ const GUIComponent = props => { }); if (children) { return ( -
+ {children} -
+
); } return ( -
- - - - - -
+ + + + + + + + + + + + + + ); }; - GUIComponent.propTypes = { basePath: React.PropTypes.string, blocksProps: shapeFromPropTypes(Blocks.propTypes, {omit: ['vm']}), children: React.PropTypes.node, greenFlagProps: shapeFromPropTypes(GreenFlag.propTypes, {omit: ['vm']}), - mediaLibrary: React.PropTypes.instanceOf(MediaLibrary), stageProps: shapeFromPropTypes(Stage.propTypes, {omit: ['vm']}), stopAllProps: shapeFromPropTypes(StopAll.propTypes, {omit: ['vm']}), targetPaneProps: shapeFromPropTypes(TargetPane.propTypes, {omit: ['vm']}), vm: React.PropTypes.instanceOf(VM) }; - GUIComponent.defaultProps = { basePath: '/', blocksProps: {}, greenFlagProps: {}, - mediaLibrary: new MediaLibrary(), targetPaneProps: {}, stageProps: {}, stopAllProps: {}, vm: new VM() }; - module.exports = GUIComponent; diff --git a/src/components/library-item/library-item.css b/src/components/library-item/library-item.css index ab33428357..4d90f61478 100644 --- a/src/components/library-item/library-item.css +++ b/src/components/library-item/library-item.css @@ -1,10 +1,6 @@ .library-item { - float: left; - width: 140px; - margin-left: 5px; - margin-right: 5px; - text-align: center; cursor: pointer; + text-align: center; } .library-item.is-selected { background: #aaa; diff --git a/src/components/library-item/library-item.jsx b/src/components/library-item/library-item.jsx index 641f989da0..3e47a2beec 100644 --- a/src/components/library-item/library-item.jsx +++ b/src/components/library-item/library-item.jsx @@ -2,6 +2,7 @@ const classNames = require('classnames'); const bindAll = require('lodash.bindall'); const React = require('react'); +const Box = require('../box/box.jsx'); const CostumeCanvas = require('../costume-canvas/costume-canvas.jsx'); const styles = require('./library-item.css'); @@ -16,16 +17,20 @@ class LibraryItem extends React.Component { } render () { return ( -

{this.props.name}

-
+
); } } diff --git a/src/components/library/library.css b/src/components/library/library.css index 02101f2239..6fee04d977 100644 --- a/src/components/library/library.css +++ b/src/components/library/library.css @@ -1,8 +1,3 @@ .library-scroll-grid { - overflow: scroll; - position: absolute; - top: 70px; - bottom: 20px; - left: 30px; - right: 30px; + overflow-y: auto; } diff --git a/src/components/library/library.jsx b/src/components/library/library.jsx index 043ece7291..35374d7e03 100644 --- a/src/components/library/library.jsx +++ b/src/components/library/library.jsx @@ -1,6 +1,7 @@ const bindAll = require('lodash.bindall'); const React = require('react'); +const Box = require('../box/box.jsx'); const LibraryItem = require('../library-item/library-item.jsx'); const ModalComponent = require('../modal/modal.jsx'); @@ -27,7 +28,12 @@ class LibraryComponent extends React.Component { onRequestClose={this.props.onRequestClose} >

{this.props.title}

-
+ {this.props.data.map((dataItem, itemId) => { const scratchURL = dataItem.md5 ? `https://cdn.assets.scratch.mit.edu/internalapi/asset/${dataItem.md5}/get/` : @@ -43,7 +49,7 @@ class LibraryComponent extends React.Component { /> ); })} -
+ ); } diff --git a/src/components/modal/modal.css b/src/components/modal/modal.css index b9cb8527b1..b050f13eb0 100644 --- a/src/components/modal/modal.css +++ b/src/components/modal/modal.css @@ -10,7 +10,7 @@ .modal-content { outline: none; position: absolute; - overflow: visible; + overflow: hidden; -webkit-overflow-scrolling: 'touch'; border: 1px solid #ccc; border-radius: 6px; @@ -21,6 +21,11 @@ left: 5%; background: #fcfcfc; } +.modal-children { + overflow: hidden; + height: 100%; + z-index: 0; +} .modal-close-button { color: rgb(255, 255, 255); background: rgb(50, 50, 50); @@ -32,5 +37,6 @@ position: absolute; right: 3px; top: 3px; - cursor: pointer + cursor: pointer; + z-index: 1; } diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index 3c36ba5092..f41b61f1bf 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,6 +1,8 @@ const React = require('react'); const ReactModal = require('react-modal'); +const Box = require('../box/box.jsx'); + const styles = require('./modal.css'); class ModalComponent extends React.Component { @@ -19,7 +21,12 @@ class ModalComponent extends React.Component { > {'x'}
- {this.props.children} + + {this.props.children} + ); } diff --git a/src/components/sprite-selector-item/sprite-selector-item.jsx b/src/components/sprite-selector-item/sprite-selector-item.jsx index a7de0d93c8..ebcdd423b0 100644 --- a/src/components/sprite-selector-item/sprite-selector-item.jsx +++ b/src/components/sprite-selector-item/sprite-selector-item.jsx @@ -1,11 +1,12 @@ const classNames = require('classnames'); const React = require('react'); +const Box = require('../box/box.jsx'); const CostumeCanvas = require('../costume-canvas/costume-canvas.jsx'); const styles = require('./sprite-selector-item.css'); const SpriteSelectorItem = props => ( -
( /> ) : null}
{props.name}
-
+ ); SpriteSelectorItem.propTypes = { diff --git a/src/components/sprite-selector/sprite-selector.css b/src/components/sprite-selector/sprite-selector.css deleted file mode 100644 index 1eadc56d50..0000000000 --- a/src/components/sprite-selector/sprite-selector.css +++ /dev/null @@ -1,3 +0,0 @@ -.sprite-selector { - width: 400px; -} diff --git a/src/components/sprite-selector/sprite-selector.jsx b/src/components/sprite-selector/sprite-selector.jsx index 770e7ca6ff..694a490fc5 100644 --- a/src/components/sprite-selector/sprite-selector.jsx +++ b/src/components/sprite-selector/sprite-selector.jsx @@ -1,9 +1,8 @@ const React = require('react'); +const Box = require('../box/box.jsx'); const SpriteSelectorItem = require('../../containers/sprite-selector-item.jsx'); -const styles = require('./sprite-selector.css'); - const SpriteSelectorComponent = function (props) { const { onSelectSprite, @@ -12,8 +11,11 @@ const SpriteSelectorComponent = function (props) { ...componentProps } = props; return ( -
{Object.keys(sprites) @@ -30,7 +32,7 @@ const SpriteSelectorComponent = function (props) { /> )) } -
+ ); }; diff --git a/src/components/stage-selector/stage-selector.css b/src/components/stage-selector/stage-selector.css index 0981e0ebee..e3cf8de6dc 100644 --- a/src/components/stage-selector/stage-selector.css +++ b/src/components/stage-selector/stage-selector.css @@ -1,10 +1,5 @@ .stage-selector { - position: absolute; - top: 0; - right: 0; - width: 72px; - border: 1px solid; - border-color: transparent; + text-align: center; } .stage-selector.is-selected { border-color: black; diff --git a/src/components/stage-selector/stage-selector.jsx b/src/components/stage-selector/stage-selector.jsx index db6b93e97c..e97cb38c3c 100644 --- a/src/components/stage-selector/stage-selector.jsx +++ b/src/components/stage-selector/stage-selector.jsx @@ -1,36 +1,47 @@ const classNames = require('classnames'); const React = require('react'); +const Box = require('../box/box.jsx'); const CostumeCanvas = require('../costume-canvas/costume-canvas.jsx'); const styles = require('./stage-selector.css'); -const StageSelector = props => ( -
-
Stage
-
Backgrounds
-
{props.backdropCount}
-
- {props.url ? ( - - ) : null} -
-); - +const StageSelector = props => { + const { + backdropCount, + selected, + url, + onClick, + ...componentProps + } = props; + return ( + +
Stage
+
Backgrounds
+
{backdropCount}
+
+ {url ? ( + + ) : null} +
+ ); +}; StageSelector.propTypes = { backdropCount: React.PropTypes.number, onClick: React.PropTypes.func, selected: React.PropTypes.bool, url: React.PropTypes.string }; - module.exports = StageSelector; diff --git a/src/components/stage/stage.css b/src/components/stage/stage.css deleted file mode 100644 index 60d9f9a102..0000000000 --- a/src/components/stage/stage.css +++ /dev/null @@ -1,5 +0,0 @@ -.stage { - position: absolute; - top: 40px; - right: 0; -} diff --git a/src/components/stage/stage.jsx b/src/components/stage/stage.jsx index daf447999b..3607b52049 100644 --- a/src/components/stage/stage.jsx +++ b/src/components/stage/stage.jsx @@ -1,39 +1,32 @@ const React = require('react'); -const styles = require('./stage.css'); - -class StageComponent extends React.Component { - render () { - const { - canvasRef, - width, - height, - ...props - } = this.props; - return ( - - ); - } -} +const Box = require('../box/box.jsx'); +const StageComponent = props => { + const { + canvasRef, + width, + height, + ...boxProps + } = props; + return ( + + ); +}; StageComponent.propTypes = { canvasRef: React.PropTypes.func, height: React.PropTypes.number, width: React.PropTypes.number }; - StageComponent.defaultProps = { canvasRef: () => {}, width: 480, height: 360 }; - module.exports = StageComponent; diff --git a/src/components/stop-all/stop-all.css b/src/components/stop-all/stop-all.css index ff44af122d..2273916989 100644 --- a/src/components/stop-all/stop-all.css +++ b/src/components/stop-all/stop-all.css @@ -1,11 +1,7 @@ .stop-all { - position: absolute; - top: 8px; - right: calc(480px - 16px - 12px - 16px); width: 16px; height: 16px; } - -.active { +.stop-all.is-active { filter: saturate(200%) brightness(150%); } diff --git a/src/components/stop-all/stop-all.jsx b/src/components/stop-all/stop-all.jsx index 8d0d8ccfb0..1c009de44b 100644 --- a/src/components/stop-all/stop-all.jsx +++ b/src/components/stop-all/stop-all.jsx @@ -15,7 +15,7 @@ const StopAllComponent = function (props) { - - -

- - {editingTarget === stage.id ? ( - - ) : ( - - )} - - - + + -

- +
+ + {stage.id && } + + + {editingTarget === stage.id ? ( + + ) : ( + + )} + + + + + + ); }; const spriteShape = React.PropTypes.shape({ @@ -113,4 +132,8 @@ TargetPane.propTypes = { vm: React.PropTypes.instanceOf(VM) }; +TargetPane.defaultProps = { + mediaLibrary: new MediaLibrary() +}; + module.exports = TargetPane; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000000..9a68223269 --- /dev/null +++ b/src/index.css @@ -0,0 +1,7 @@ +:global(html), +:global(body), +.app { + width: 100%; + height: 100%; + margin: 0; +} diff --git a/src/index.jsx b/src/index.jsx index 393cb95dee..a91c27b1d1 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -8,6 +8,8 @@ const log = require('./lib/log'); const ProjectLoader = require('./lib/project-loader'); const reducer = require('./reducers/gui'); +const styles = require('./index.css'); + class App extends React.Component { constructor (props) { super(props); @@ -59,6 +61,7 @@ App.propTypes = { }; const appTarget = document.createElement('div'); +appTarget.className = styles.app; document.body.appendChild(appTarget); const store = createStore( reducer, diff --git a/webpack.config.js b/webpack.config.js index 3f5e688029..39376b7dff 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -36,6 +36,7 @@ module.exports = { loader: 'css', query: { modules: true, + importLoaders: 1, localIdentName: '[name]_[local]_[hash:base64:5]', camelCase: true } @@ -52,10 +53,15 @@ module.exports = { loader: 'json-loader' }] }, - postcss: [autoprefixer], + postcss: [ + autoprefixer({ + browsers: ['last 3 versions', 'Safari >= 8', 'iOS >= 8'] + }) + ], plugins: [ new webpack.DefinePlugin({ - 'process.env.BASE_PATH': '"' + (process.env.BASE_PATH || '/') + '"' + 'process.env.BASE_PATH': '"' + (process.env.BASE_PATH || '/') + '"', + 'process.env.DEBUG': Boolean(process.env.DEBUG) }), new webpack.optimize.CommonsChunkPlugin({ name: 'lib',