From 0fb816d07485f4adac80e54ed245ce472cb11818 Mon Sep 17 00:00:00 2001 From: jos Date: Wed, 12 Sep 2018 11:16:04 +0200 Subject: [PATCH] Moved tree mode menu in a separate component --- src/jsoneditor/components/TreeMode.js | 84 ++++---------- src/jsoneditor/components/jsoneditor.scss | 15 +-- src/jsoneditor/components/menu/ModeButton.js | 4 +- .../menu/{ModeMenu.js => ModeSelector.js} | 2 +- .../components/menu/TreeModeMenu.js | 103 ++++++++++++++++++ src/jsoneditor/components/style.scss | 15 +++ 6 files changed, 141 insertions(+), 82 deletions(-) rename src/jsoneditor/components/menu/{ModeMenu.js => ModeSelector.js} (98%) create mode 100644 src/jsoneditor/components/menu/TreeModeMenu.js create mode 100644 src/jsoneditor/components/style.scss diff --git a/src/jsoneditor/components/TreeMode.js b/src/jsoneditor/components/TreeMode.js index bf8430c..8730850 100644 --- a/src/jsoneditor/components/TreeMode.js +++ b/src/jsoneditor/components/TreeMode.js @@ -63,6 +63,7 @@ import { search, syncEson } from '../eson' +import TreeModeMenu from './menu/TreeModeMenu' const AJV_OPTIONS = { allErrors: true, @@ -71,7 +72,6 @@ const AJV_OPTIONS = { } const MAX_HISTORY_ITEMS = 1000 // maximum number of undo/redo items to be kept in memory -const SEARCH_DEBOUNCE = 300 // milliseconds const SCROLL_DURATION = 400 // milliseconds export default class TreeMode extends PureComponent { @@ -268,74 +268,28 @@ export default class TreeMode extends PureComponent { } renderMenu () { - let items = [ - h('button', { - key: 'expand-all', - className: 'jsoneditor-expand-all', - title: 'Expand all objects and arrays', - onClick: this.handleExpandAll - }), - h('button', { - key: 'collapse-all', - className: 'jsoneditor-collapse-all', - title: 'Collapse all objects and arrays', - onClick: this.handleCollapseAll - }) - ] + return h(TreeModeMenu, { + mode: this.props.mode, + modes: this.props.modes, + onChangeMode: this.props.onChangeMode, - if (this.props.mode !== 'view' && this.props.history !== false) { - items = items.concat([ - h('div', {key: 'history-separator', className: 'jsoneditor-vertical-menu-separator'}), + onExpandAll: this.handleExpandAll, + onCollapseAll: this.handleCollapseAll, - h('button', { - key: 'undo', - className: 'jsoneditor-undo', - title: 'Undo last action', - disabled: !this.canUndo(), - onClick: this.undo - }), - h('button', { - key: 'redo', - className: 'jsoneditor-redo', - title: 'Redo', - disabled: !this.canRedo(), - onClick: this.redo - }) - ]) - } + enableHistory: this.props.history, + canUndo: this.canUndo(), + canRedo: this.canRedo(), + onUndo: this.undo, + onRedo: this.redo, - if (this.props.modes ) { - items = items.concat([ - h('div', {key: 'mode-separator', className: 'jsoneditor-vertical-menu-separator'}), + enableSearch: this.props.search, + searchResult: this.state.searchResult, + onSearch: this.handleSearch, + onSearchNext: this.handleNext, + onSearchPrevious: this.handlePrevious, - h(ModeButton, { - key: 'mode', - modes: this.props.modes, - mode: this.props.mode, - onChangeMode: this.props.onChangeMode, - onError: this.props.onError - }) - ]) - } - - if (this.props.searchResult !== false) { - // option search is true or undefined - items = items.concat([ - h('div', {key: 'search', className: 'jsoneditor-menu-panel-right'}, - h(Search, { - text: this.state.searchResult.text, - resultCount: this.state.searchResult.matches ? this.state.searchResult.matches.length : 0, - onChange: this.handleSearch, - onNext: this.handleNext, - onPrevious: this.handlePrevious, - findKeyBinding: this.findKeyBinding, - delay: SEARCH_DEBOUNCE - }) - ) - ]) - } - - return h('div', {key: 'menu', className: 'jsoneditor-menu'}, items) + findKeyBinding: this.findKeyBinding, + }) } /** diff --git a/src/jsoneditor/components/jsoneditor.scss b/src/jsoneditor/components/jsoneditor.scss index 40163aa..0fd8588 100644 --- a/src/jsoneditor/components/jsoneditor.scss +++ b/src/jsoneditor/components/jsoneditor.scss @@ -1,19 +1,6 @@ +@import './style.scss'; @import './popover.scss'; -$fontFamily: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif; -$fontSize: 10pt; -$black: #1A1A1A; -$contentsMinHeight: 150px; -$theme-color: #3883fa; // TODO: create a central file with the theme colors -$floating-menu-background: #4d4d4d; -$floating-menu-color: #fff; -$selectedColor: #ffed99; -$hoverColor: #d3d3d3; -$hoverAndSelectedColor: #ffdb80; -$gray: #9d9d9d; -$light-gray: #c0c0c0; -$input-padding: 5px; - // TODO: split this scss file into separate files per React component $line-height: 20px; diff --git a/src/jsoneditor/components/menu/ModeButton.js b/src/jsoneditor/components/menu/ModeButton.js index b437860..69040c8 100644 --- a/src/jsoneditor/components/menu/ModeButton.js +++ b/src/jsoneditor/components/menu/ModeButton.js @@ -1,5 +1,5 @@ import { createElement as h, Component } from 'react' -import ModeMenu from './ModeMenu' +import ModeSelector from './ModeSelector' import { toCapital } from '../../utils/stringUtils' export default class ModeButton extends Component { @@ -24,7 +24,7 @@ export default class ModeButton extends Component { onClick: this.handleOpen }, `${toCapital(props.mode)} \u25BC`), - h(ModeMenu, { + h(ModeSelector, { key: 'menu', ...props, open: state.open, diff --git a/src/jsoneditor/components/menu/ModeMenu.js b/src/jsoneditor/components/menu/ModeSelector.js similarity index 98% rename from src/jsoneditor/components/menu/ModeMenu.js rename to src/jsoneditor/components/menu/ModeSelector.js index 0c66c7e..149a35f 100644 --- a/src/jsoneditor/components/menu/ModeMenu.js +++ b/src/jsoneditor/components/menu/ModeSelector.js @@ -5,7 +5,7 @@ import { keyComboFromEvent } from '../../utils/keyBindings' const MENU_CLASS_NAME = 'jsoneditor-actionmenu' const MODE_MENU_CLASS_NAME = MENU_CLASS_NAME + ' jsoneditor-modemenu' -export default class ModeMenu extends Component { +export default class ModeSelector extends Component { /** * {{open, modes, mode, onChangeMode, onRequestClose, onError}} props */ diff --git a/src/jsoneditor/components/menu/TreeModeMenu.js b/src/jsoneditor/components/menu/TreeModeMenu.js new file mode 100644 index 0000000..9273327 --- /dev/null +++ b/src/jsoneditor/components/menu/TreeModeMenu.js @@ -0,0 +1,103 @@ +import { createElement as h, PureComponent } from 'react' +import ModeButton from './ModeButton' +import Search from './Search' +import PropTypes from 'prop-types' + +const SEARCH_DEBOUNCE = 300 // milliseconds + +export default class TreeModeMenu extends PureComponent { + + static propTypes = { + mode: PropTypes.string.isRequired, + modes: PropTypes.arrayOf(PropTypes.string), + onChangeMode: PropTypes.func.isRequired, + + onExpandAll: PropTypes.func.isRequired, + onCollapseAll: PropTypes.func.isRequired, + + enableHistory: PropTypes.bool, + canUndo: PropTypes.bool, + canRedo: PropTypes.bool, + onUndo: PropTypes.func, + onRedo: PropTypes.func, + + enableSearch: PropTypes.bool, + searchResult: PropTypes.string, + onSearch: PropTypes.func, + onSearchNext: PropTypes.func, + onSearchPrevious: PropTypes.func, + + findKeyBinding: PropTypes.func.isRequired, + } + + render () { + let items = [ + h('button', { + key: 'expand-all', + className: 'jsoneditor-expand-all', + title: 'Expand all objects and arrays', + onClick: this.props.onExpandAll + }), + h('button', { + key: 'collapse-all', + className: 'jsoneditor-collapse-all', + title: 'Collapse all objects and arrays', + onClick: this.props.onCollapseAll + }) + ] + + if (this.props.mode !== 'view' && this.props.enableHistory !== false) { + items = items.concat([ + h('div', {key: 'history-separator', className: 'jsoneditor-vertical-menu-separator'}), + + h('button', { + key: 'undo', + className: 'jsoneditor-undo', + title: 'Undo last action', + disabled: !this.props.canUndo, + onClick: this.props.onUndo + }), + h('button', { + key: 'redo', + className: 'jsoneditor-redo', + title: 'Redo', + disabled: !this.props.canRedo, + onClick: this.props.onRedo + }) + ]) + } + + if (this.props.modes ) { + items = items.concat([ + h('div', {key: 'mode-separator', className: 'jsoneditor-vertical-menu-separator'}), + + h(ModeButton, { + key: 'mode', + modes: this.props.modes, + mode: this.props.mode, + onChangeMode: this.props.onChangeMode, + onError: this.props.onError + }) + ]) + } + + if (this.props.enableSearch !== false) { + // option search is true or undefined + items = items.concat([ + h('div', {key: 'search', className: 'jsoneditor-menu-panel-right'}, + h(Search, { + text: this.props.searchResult.text, + resultCount: this.props.searchResult.matches ? this.props.searchResult.matches.length : 0, + onChange: this.props.onSearch, + onNext: this.props.onSearchNext, + onPrevious: this.props.onSearchPrevious, + findKeyBinding: this.props.findKeyBinding, + delay: SEARCH_DEBOUNCE + }) + ) + ]) + } + + return h('div', {key: 'menu', className: 'jsoneditor-menu'}, items) + } +} \ No newline at end of file diff --git a/src/jsoneditor/components/style.scss b/src/jsoneditor/components/style.scss new file mode 100644 index 0000000..1c7dba2 --- /dev/null +++ b/src/jsoneditor/components/style.scss @@ -0,0 +1,15 @@ + +$fontFamily: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif; +$fontSize: 10pt; +$black: #1A1A1A; +$contentsMinHeight: 150px; +$theme-color: #3883fa; +$theme-color-light: lighten($theme-color, 5); +$floating-menu-background: #4d4d4d; +$floating-menu-color: #fff; +$selectedColor: #ffed99; +$hoverColor: #d3d3d3; +$hoverAndSelectedColor: #ffdb80; +$gray: #9d9d9d; +$light-gray: #c0c0c0; +$input-padding: 5px;