diff --git a/src/components/prompt/prompt.css b/src/components/prompt/prompt.css
new file mode 100644
index 000000000..e7a12d9d9
--- /dev/null
+++ b/src/components/prompt/prompt.css
@@ -0,0 +1,71 @@
+@import "../../css/colors.css";
+@import "../../css/units.css";
+
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1000;
+ background-color: rgba(94, 102, 125, .95);
+}
+
+.modal-content {
+ width: 360px;
+ margin: 100px auto;
+ outline: none;
+ border: 3px solid rgb(126, 133, 151);
+ padding: 0;
+ border-radius: $space;
+ user-select: none;
+
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #5d647a;
+ overflow: hidden;
+}
+
+.body {
+ background: $ui-pane-gray;
+ padding: 1.5rem 2.25rem;
+}
+
+.label {
+ font-weight: 500;
+ margin: 0 0 0.75rem;
+}
+
+.input {
+ margin-bottom: 1.5rem;
+ width: 100%;
+ border: 1px solid rgba(0,0,0,.1);
+ border-radius: 5px;
+ padding: 0 1rem;
+ height: 3rem;
+ color: #6b6b6b;
+ font-size: .875rem;
+}
+
+.button-row {
+ font-weight: bolder;
+ text-align: right;
+}
+
+.button-row button {
+ padding: 0.75rem 1rem;
+ border-radius: 0.25rem;
+ background: white;
+ border: 1px solid $ui-pane-border;
+ font-weight: 600;
+ font-size: 0.85rem;
+}
+
+.button-row button.ok-button {
+ background: $blue;
+ border: $blue;
+ color: white;
+}
+
+.button-row button + button {
+ margin-left: 0.5rem;
+}
diff --git a/src/components/prompt/prompt.jsx b/src/components/prompt/prompt.jsx
new file mode 100644
index 000000000..d2411468b
--- /dev/null
+++ b/src/components/prompt/prompt.jsx
@@ -0,0 +1,74 @@
+const React = require('react');
+const ReactModal = require('react-modal');
+const bindAll = require('lodash.bindall');
+const Box = require('../box/box.jsx');
+
+const styles = require('./prompt.css');
+
+class PromptComponent extends React.Component {
+ constructor (props) {
+ super(props);
+ bindAll(this, [
+ 'handleOk',
+ 'handleKeyPress'
+ ]);
+ }
+ handleKeyPress (event) {
+ if (event.key === 'Enter') this.handleOk();
+ }
+ handleOk () {
+ this.props.onOk(this.input.value);
+ }
+ render () {
+ return (
+
+
+
+ {this.props.label}
+
+
+ (this.input = el)}
+ onKeyPress={this.handleKeyPress}
+ />
+
+
+
+
+
+
+
+ );
+ }
+}
+
+PromptComponent.propTypes = {
+ label: React.PropTypes.string.isRequired,
+ onCancel: React.PropTypes.func.isRequired,
+ onOk: React.PropTypes.func.isRequired,
+ placeholder: React.PropTypes.string
+};
+
+PromptComponent.defaultProps = {
+ placeholder: '...'
+};
+
+module.exports = PromptComponent;
diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index 69ae0bf1d..e319c920f 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -4,7 +4,7 @@ const PropTypes = require('prop-types');
const React = require('react');
const VMScratchBlocks = require('../lib/blocks');
const VM = require('scratch-vm');
-
+const Prompt = require('../components/prompt/prompt.jsx');
const BlocksComponent = require('../components/blocks/blocks.jsx');
const addFunctionListener = (object, property, callback) => {
@@ -23,6 +23,8 @@ class Blocks extends React.Component {
bindAll(this, [
'attachVM',
'detachVM',
+ 'handlePromptCallback',
+ 'handlePromptClose',
'onScriptGlowOn',
'onScriptGlowOff',
'onBlockGlowOn',
@@ -32,20 +34,27 @@ class Blocks extends React.Component {
'onWorkspaceMetricsChange',
'setBlocks'
]);
- this.state = {workspaceMetrics: {}};
+ this.state = {
+ workspaceMetrics: {},
+ prompt: null
+ };
}
componentDidMount () {
const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options);
this.workspace = this.ScratchBlocks.inject(this.blocks, workspaceConfig);
+ this.ScratchBlocks.prompt = (message, defaultValue, callback) => {
+ this.setState({prompt: {callback, message, defaultValue}});
+ };
+
// @todo change this when blockly supports UI events
addFunctionListener(this.workspace, 'translate', this.onWorkspaceMetricsChange);
addFunctionListener(this.workspace, 'zoom', this.onWorkspaceMetricsChange);
this.attachVM();
}
- shouldComponentUpdate () {
- return false;
+ shouldComponentUpdate (nextProps, nextState) {
+ return this.state.prompt !== nextState.prompt;
}
componentWillUnmount () {
this.detachVM();
@@ -72,6 +81,7 @@ class Blocks extends React.Component {
this.props.vm.removeListener('VISUAL_REPORT', this.onVisualReport);
this.props.vm.removeListener('workspaceUpdate', this.onWorkspaceUpdate);
}
+
onWorkspaceMetricsChange () {
const target = this.props.vm.editingTarget;
if (target && target.id) {
@@ -124,6 +134,13 @@ class Blocks extends React.Component {
setBlocks (blocks) {
this.blocks = blocks;
}
+ handlePromptCallback (data) {
+ this.state.prompt.callback(data);
+ this.handlePromptClose();
+ }
+ handlePromptClose () {
+ this.setState({prompt: null});
+ }
render () {
const {
options, // eslint-disable-line no-unused-vars
@@ -131,10 +148,20 @@ class Blocks extends React.Component {
...props
} = this.props;
return (
-
+
+
+ {this.state.prompt ? (
+
+ ) : null}
+
);
}
}