Merge pull request #366 from paulkaplan/feature/click-to-add
Single-click to add from libraries + hover sounds
This commit is contained in:
commit
488ba96a18
7 files changed
+56
-41
No files matched your search
@@ -27,12 +27,6 @@
|
||||
transform: scale(1.02, 1.02);
|
||||
}
|
||||
|
||||
.library-item.is-selected {
|
||||
border-width: 2px;
|
||||
border-color: #1dacf4;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
|
||||
.library-item-image-container {
|
||||
height: 100px;
|
||||
}
|
||||
@@ -47,12 +41,12 @@
|
||||
margin: 0.25rem 0;
|
||||
text-align: center;
|
||||
|
||||
/*
|
||||
/*
|
||||
For truncating overflowing text gracefully
|
||||
Min-width is for a bug: https://css-tricks.com/flexbox-truncated-text
|
||||
*/
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
const classNames = require('classnames');
|
||||
const bindAll = require('lodash.bindall');
|
||||
const PropTypes = require('prop-types');
|
||||
const React = require('react');
|
||||
@@ -9,20 +8,29 @@ const styles = require('./library-item.css');
|
||||
class LibraryItem extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['handleClick']);
|
||||
bindAll(this, [
|
||||
'handleClick',
|
||||
'handleMouseEnter',
|
||||
'handleMouseLeave'
|
||||
]);
|
||||
}
|
||||
handleClick (e) {
|
||||
this.props.onSelect(this.props.id);
|
||||
e.preventDefault();
|
||||
}
|
||||
handleMouseEnter () {
|
||||
this.props.onMouseEnter(this.props.id);
|
||||
}
|
||||
handleMouseLeave () {
|
||||
this.props.onMouseLeave(this.props.id);
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<Box
|
||||
className={classNames({
|
||||
[styles.libraryItem]: true,
|
||||
[styles.isSelected]: this.props.selected
|
||||
})}
|
||||
className={styles.libraryItem}
|
||||
onClick={this.handleClick}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
>
|
||||
<Box className={styles.libraryItemImageContainer}>
|
||||
<img
|
||||
@@ -40,8 +48,9 @@ LibraryItem.propTypes = {
|
||||
iconURL: PropTypes.string.isRequired,
|
||||
id: PropTypes.number.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
selected: PropTypes.bool.isRequired
|
||||
onMouseEnter: PropTypes.func.isRequired,
|
||||
onMouseLeave: PropTypes.func.isRequired,
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
module.exports = LibraryItem;
|
||||
@@ -10,20 +10,21 @@ const styles = require('./library.css');
|
||||
class LibraryComponent extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, ['handleSelect']);
|
||||
this.state = {selectedItem: null};
|
||||
bindAll(this, [
|
||||
'handleSelect',
|
||||
'handleMouseEnter',
|
||||
'handleMouseLeave'
|
||||
]);
|
||||
}
|
||||
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]);
|
||||
} else {
|
||||
if (this.props.onItemChosen) {
|
||||
this.props.onItemChosen(this.props.data[id]);
|
||||
}
|
||||
}
|
||||
this.setState({selectedItem: id});
|
||||
this.props.onRequestClose();
|
||||
this.props.onItemSelected(this.props.data[id]);
|
||||
}
|
||||
handleMouseEnter (id) {
|
||||
if (this.props.onItemMouseEnter) this.props.onItemMouseEnter(this.props.data[id]);
|
||||
}
|
||||
handleMouseLeave (id) {
|
||||
if (this.props.onItemMouseLeave) this.props.onItemMouseLeave(this.props.data[id]);
|
||||
}
|
||||
render () {
|
||||
if (!this.props.visible) return null;
|
||||
@@ -45,7 +46,8 @@ class LibraryComponent extends React.Component {
|
||||
id={itemId}
|
||||
key={`item_${itemId}`}
|
||||
name={dataItem.name}
|
||||
selected={this.state.selectedItem === itemId}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
onSelect={this.handleSelect}
|
||||
/>
|
||||
);
|
||||
@@ -67,7 +69,8 @@ LibraryComponent.propTypes = {
|
||||
})
|
||||
/* eslint-enable react/no-unused-prop-types, lines-around-comment */
|
||||
),
|
||||
onItemChosen: PropTypes.func,
|
||||
onItemMouseEnter: PropTypes.func,
|
||||
onItemMouseLeave: PropTypes.func,
|
||||
onItemSelected: PropTypes.func,
|
||||
onRequestClose: PropTypes.func,
|
||||
title: PropTypes.string.isRequired,
|
||||
|
||||
@@ -4,7 +4,7 @@ const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const backdropLibraryContent = require('../lib/libraries/backdrops.json');
|
||||
const LibaryComponent = require('../components/library/library.jsx');
|
||||
const LibraryComponent = require('../components/library/library.jsx');
|
||||
|
||||
|
||||
class BackdropLibrary extends React.Component {
|
||||
@@ -26,7 +26,7 @@ class BackdropLibrary extends React.Component {
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<LibaryComponent
|
||||
<LibraryComponent
|
||||
data={backdropLibraryContent}
|
||||
title="Backdrop Library"
|
||||
visible={this.props.visible}
|
||||
|
||||
@@ -4,7 +4,7 @@ const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
|
||||
const costumeLibraryContent = require('../lib/libraries/costumes.json');
|
||||
const LibaryComponent = require('../components/library/library.jsx');
|
||||
const LibraryComponent = require('../components/library/library.jsx');
|
||||
|
||||
|
||||
class CostumeLibrary extends React.Component {
|
||||
@@ -26,7 +26,7 @@ class CostumeLibrary extends React.Component {
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<LibaryComponent
|
||||
<LibraryComponent
|
||||
data={costumeLibraryContent}
|
||||
title="Costume Library"
|
||||
visible={this.props.visible}
|
||||
|
||||
@@ -3,7 +3,7 @@ const PropTypes = require('prop-types');
|
||||
const React = require('react');
|
||||
const VM = require('scratch-vm');
|
||||
const AudioEngine = require('scratch-audio');
|
||||
const LibaryComponent = require('../components/library/library.jsx');
|
||||
const LibraryComponent = require('../components/library/library.jsx');
|
||||
|
||||
const soundIcon = require('../components/asset-panel/icon--sound.svg');
|
||||
|
||||
@@ -14,14 +14,19 @@ class SoundLibrary extends React.Component {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleItemSelected',
|
||||
'handleItemChosen'
|
||||
'handleItemMouseEnter',
|
||||
'handleItemMouseLeave'
|
||||
]);
|
||||
}
|
||||
componentDidMount () {
|
||||
this.audioEngine = new AudioEngine();
|
||||
this.player = this.audioEngine.createPlayer();
|
||||
}
|
||||
handleItemChosen (soundItem) {
|
||||
componentWillReceiveProps (newProps) {
|
||||
// Stop playing sounds if the library closes without a mouseleave (e.g. by using the escape key)
|
||||
if (this.player && !newProps.visible) this.player.stopAllSounds();
|
||||
}
|
||||
handleItemMouseEnter (soundItem) {
|
||||
const md5ext = soundItem._md5;
|
||||
const idParts = md5ext.split('.');
|
||||
const md5 = idParts[0];
|
||||
@@ -39,6 +44,9 @@ class SoundLibrary extends React.Component {
|
||||
this.player.playSound(soundItem._md5);
|
||||
});
|
||||
}
|
||||
handleItemMouseLeave () {
|
||||
this.player.stopAllSounds();
|
||||
}
|
||||
handleItemSelected (soundItem) {
|
||||
const vmSound = {
|
||||
format: soundItem.format,
|
||||
@@ -64,11 +72,12 @@ class SoundLibrary extends React.Component {
|
||||
});
|
||||
|
||||
return (
|
||||
<LibaryComponent
|
||||
<LibraryComponent
|
||||
data={soundLibraryThumbnailData}
|
||||
title="Sound Library"
|
||||
visible={this.props.visible}
|
||||
onItemChosen={this.handleItemChosen}
|
||||
onItemMouseEnter={this.handleItemMouseEnter}
|
||||
onItemMouseLeave={this.handleItemMouseLeave}
|
||||
onItemSelected={this.handleItemSelected}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,7 @@ const VM = require('scratch-vm');
|
||||
|
||||
const spriteLibraryContent = require('../lib/libraries/sprites.json');
|
||||
|
||||
const LibaryComponent = require('../components/library/library.jsx');
|
||||
const LibraryComponent = require('../components/library/library.jsx');
|
||||
|
||||
class SpriteLibrary extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -19,7 +19,7 @@ class SpriteLibrary extends React.Component {
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<LibaryComponent
|
||||
<LibraryComponent
|
||||
data={spriteLibraryContent}
|
||||
title="Sprite Library"
|
||||
visible={this.props.visible}
|
||||
|
||||
Reference in new issue
Block a user