import React from 'react'; import PropTypes from 'prop-types'; import FormGroup from 'react-bootstrap/es/FormGroup'; import FormControl from 'react-bootstrap/es/FormControl'; import ControlLabel from 'react-bootstrap/es/ControlLabel'; import Dropdown from 'react-bootstrap/es/Dropdown'; import MenuItem from 'react-bootstrap/es/MenuItem'; export default class OptionsSelector extends React.Component { constructor(props) { super(props); const config = this.props.crowi.getConfig(); const isMathJaxEnabled = !!config.env.MATHJAX; this.state = { editorOptions: this.props.editorOptions || new EditorOptions(), previewOptions: this.props.previewOptions || new PreviewOptions(), isCddMenuOpened: false, isMathJaxEnabled, }; this.availableThemes = [ 'eclipse', 'elegant', 'neo', 'mdn-like', 'material', 'dracula', 'monokai', 'twilight' ]; this.keymapModes = { default: 'Default', vim: 'Vim', emacs: 'Emacs', sublime: 'Sublime Text', }; this.onChangeTheme = this.onChangeTheme.bind(this); this.onChangeKeymapMode = this.onChangeKeymapMode.bind(this); this.onClickStyleActiveLine = this.onClickStyleActiveLine.bind(this); this.onClickRenderMathJaxInRealtime = this.onClickRenderMathJaxInRealtime.bind(this); this.onToggleConfigurationDropdown = this.onToggleConfigurationDropdown.bind(this); } componentDidMount() { this.init(); } init() { this.themeSelectorInputEl.value = this.state.editorOptions.theme; this.keymapModeSelectorInputEl.value = this.state.editorOptions.keymapMode; } onChangeTheme() { const newValue = this.themeSelectorInputEl.value; const newOpts = Object.assign(this.state.editorOptions, {theme: newValue}); this.setState({editorOptions: newOpts}); // dispatch event this.dispatchOnChange(); } onChangeKeymapMode() { const newValue = this.keymapModeSelectorInputEl.value; const newOpts = Object.assign(this.state.editorOptions, {keymapMode: newValue}); this.setState({editorOptions: newOpts}); // dispatch event this.dispatchOnChange(); } onClickStyleActiveLine(event) { // keep dropdown opened this._cddForceOpen = true; const newValue = !this.state.editorOptions.styleActiveLine; const newOpts = Object.assign(this.state.editorOptions, {styleActiveLine: newValue}); this.setState({editorOptions: newOpts}); // dispatch event this.dispatchOnChange(); } onClickRenderMathJaxInRealtime(event) { // keep dropdown opened this._cddForceOpen = true; const newValue = !this.state.previewOptions.renderMathJaxInRealtime; const newOpts = Object.assign(this.state.previewOptions, {renderMathJaxInRealtime: newValue}); this.setState({previewOptions: newOpts}); // dispatch event this.dispatchOnChange(); } /* * see: https://github.com/react-bootstrap/react-bootstrap/issues/1490#issuecomment-207445759 */ onToggleConfigurationDropdown(newValue) { if (this._cddForceOpen) { this.setState({ isCddMenuOpened: true }); this._cddForceOpen = false; } else { this.setState({ isCddMenuOpened: newValue }); } } /** * dispatch onChange event */ dispatchOnChange() { if (this.props.onChange != null) { this.props.onChange(this.state.editorOptions, this.state.previewOptions); } } renderThemeSelector() { const optionElems = this.availableThemes.map((theme) => { return ; }); const bsClassName = 'form-control-dummy'; // set form-control* to shrink width return ( Theme: this.themeSelectorInputEl=el }> {optionElems} ); } renderKeymapModeSelector() { const optionElems = []; for (let mode in this.keymapModes) { const label = this.keymapModes[mode]; const dataContent = (mode === 'default') ? label : ` ${label}`; optionElems.push( ); } const bsClassName = 'form-control-dummy'; // set form-control* to shrink width return ( Keymap: this.keymapModeSelectorInputEl=el }> {optionElems} ); } renderConfigurationDropdown() { return ( {this.renderActiveLineMenuItem()} {this.renderRealtimeMathJaxMenuItem()} {/* */} ); } renderActiveLineMenuItem() { const isActive = this.state.editorOptions.styleActiveLine; const iconClasses = ['text-info']; if (isActive) { iconClasses.push('ti-check'); } const iconClassName = iconClasses.join(' '); return ( Show active line ); } renderRealtimeMathJaxMenuItem() { if (!this.state.isMathJaxEnabled) { return; } const isEnabled = this.state.isMathJaxEnabled; const isActive = isEnabled && this.state.previewOptions.renderMathJaxInRealtime; const iconClasses = ['text-info']; if (isActive) { iconClasses.push('ti-check'); } const iconClassName = iconClasses.join(' '); return ( MathJax Rendering ); } render() { return
{this.renderThemeSelector()} {this.renderKeymapModeSelector()} {this.renderConfigurationDropdown()}
; } } export class EditorOptions { constructor(props) { this.theme = 'elegant'; this.keymapMode = 'default'; this.styleActiveLine = false; Object.assign(this, props); } } export class PreviewOptions { constructor(props) { this.renderMathJaxInRealtime = false; Object.assign(this, props); } } OptionsSelector.propTypes = { crowi: PropTypes.object.isRequired, editorOptions: PropTypes.instanceOf(EditorOptions), previewOptions: PropTypes.instanceOf(PreviewOptions), onChange: PropTypes.func, };