UNPKG

react-timesheet

Version:
163 lines (138 loc) 4.36 kB
var React = require('react'); var selfCleaningTimeout = { componentDidUpdate: function() { clearTimeout(this.timeoutID); }, setTimeout: function() { clearTimeout(this.timeoutID); this.timeoutID = setTimeout.apply(null, arguments); } }; var ComponentPreview = React.createClass({ propTypes: { code: React.PropTypes.string.isRequired }, mixins: [selfCleaningTimeout], render: function() { return <div ref="mount" />; }, componentDidMount: function() { this.executeCode(); }, componentDidUpdate: function(prevProps) { // execute code only when the state's not being updated by switching tab // this avoids re-displaying the error, which comes after a certain delay if (this.props.code !== prevProps.code) { this.executeCode(); } }, compileCode: function() { return JSXTransformer.transform( '(function() {' + this.props.code + '\n})();', { harmony: true } ).code; }, executeCode: function() { var mountNode = this.refs.mount.getDOMNode(); try { React.unmountComponentAtNode(mountNode); } catch (e) { } try { var compiledCode = this.compileCode(); React.render(eval(compiledCode), mountNode); } catch (err) { this.setTimeout(function() { React.render( <div className="playgroundError">{err.toString()}</div>, mountNode ); }, 500); } } }); var IS_MOBILE = ( navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/Windows Phone/i) ); var CodeMirrorEditor = React.createClass({ componentDidMount: function() { if (IS_MOBILE) return; this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), { mode: 'javascript', lineNumbers: true, lineWrapping: true, smartIndent: false, // javascript mode does bad things with jsx indents matchBrackets: true, readOnly: this.props.readOnly }); this.editor.on('change', this.handleChange); }, componentDidUpdate: function() { if (this.props.readOnly) { this.editor.setValue(this.props.codeText); } }, handleChange: function() { if (!this.props.readOnly && this.props.onChange) { this.props.onChange(this.editor.getValue()); } }, render: function() { // wrap in a div to fully contain CodeMirror var editor; if (IS_MOBILE) { editor = <pre style={{overflow: 'scroll'}}>{this.props.codeText}</pre>; } else { editor = <textarea ref="editor" defaultValue={this.props.codeText} />; } return ( <div style={this.props.style} className={this.props.className}> {editor} </div> ); } }); var ReactPlayground = React.createClass({ propTypes: { codeText: React.PropTypes.string.isRequired }, getInitialState: function() { return { code: this.props.codeText }; }, handleCodeChange: function(code) { this.setState({ code: code }); }, render: function() { return <div className="playground"> <div className="playgroundCode"> <CodeMirrorEditor key="jsx" onChange={this.handleCodeChange} className="playgroundStage" codeText={this.state.code} /> </div> <div className="playgroundPreview"> <ComponentPreview code={this.state.code} /> </div> </div>; } }); for(var id=1; id<10; id++){ var example = document.getElementById('example'+id); if(example){ React.render( <ReactPlayground codeText={document.getElementById('code'+id).innerHTML} />, example ); } }