Replace svg sprite with fontawesome icons. Extend menu (WIP)
This commit is contained in:
parent
0fb816d074
commit
081cde4489
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,8 @@
|
|||
"bugs": "https://github.com/josdejong/jsoneditor/issues",
|
||||
"private": false,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome": "1.1.8",
|
||||
"@fortawesome/fontawesome-free-solid": "5.0.13",
|
||||
"ajv": "6.5.3",
|
||||
"brace": "0.11.1",
|
||||
"javascript-natural-sort": "0.7.1",
|
||||
|
|
|
@ -15,6 +15,13 @@ import {
|
|||
import { compileJSONPointer } from '../jsonPointer'
|
||||
import { ERROR, EXPANDED, ID, SEARCH_PROPERTY, SEARCH_VALUE, SELECTION, TYPE, VALUE } from '../eson'
|
||||
|
||||
import fontawesome from '@fortawesome/fontawesome'
|
||||
import faExclamationTriangle from '@fortawesome/fontawesome-free-solid/faExclamationTriangle'
|
||||
import faCaretRight from '@fortawesome/fontawesome-free-solid/faCaretRight'
|
||||
import faCaretDown from '@fortawesome/fontawesome-free-solid/faCaretDown'
|
||||
|
||||
fontawesome.library.add(faExclamationTriangle, faCaretRight, faCaretDown)
|
||||
|
||||
export default class JSONNode extends PureComponent {
|
||||
static URL_TITLE = 'Ctrl+Click or Ctrl+Enter to open url'
|
||||
|
||||
|
@ -96,12 +103,9 @@ export default class JSONNode extends PureComponent {
|
|||
? [
|
||||
this.renderTag(`${jsonPropsCount} ${jsonPropsCount === 1 ? 'prop' : 'props'}`,
|
||||
`Object containing ${jsonPropsCount} ${jsonPropsCount === 1 ? 'property' : 'properties'}`),
|
||||
this.renderDelimiter('}', 'jsoneditor-delimiter-end jsoneditor-delimiter-collapsed'),
|
||||
this.renderInsertAfter()
|
||||
this.renderDelimiter('}', 'jsoneditor-delimiter-end jsoneditor-delimiter-collapsed')
|
||||
]
|
||||
: [
|
||||
this.renderInsertBefore()
|
||||
],
|
||||
: null,
|
||||
this.renderError(this.props.eson[ERROR])
|
||||
])
|
||||
|
||||
|
@ -131,8 +135,7 @@ export default class JSONNode extends PureComponent {
|
|||
const floatingMenu = this.renderFloatingMenu('object', this.props.eson[SELECTION])
|
||||
const nodeEnd = this.props.eson[EXPANDED]
|
||||
? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
|
||||
this.renderDelimiter('}', 'jsoneditor-delimiter-end'),
|
||||
this.renderInsertAfter()
|
||||
this.renderDelimiter('}', 'jsoneditor-delimiter-end')
|
||||
])
|
||||
: null
|
||||
|
||||
|
@ -162,11 +165,8 @@ export default class JSONNode extends PureComponent {
|
|||
this.renderTag(`${count} ${count === 1 ? 'item' : 'items'}`,
|
||||
`Array containing ${count} ${count === 1 ? 'item' : 'items'}`),
|
||||
this.renderDelimiter(']', 'jsoneditor-delimiter-end jsoneditor-delimiter-collapsed'),
|
||||
this.renderInsertAfter(),
|
||||
]
|
||||
: [
|
||||
this.renderInsertBefore()
|
||||
],
|
||||
: null,
|
||||
this.renderError(this.props.eson[ERROR])
|
||||
])
|
||||
|
||||
|
@ -195,8 +195,7 @@ export default class JSONNode extends PureComponent {
|
|||
const floatingMenu = this.renderFloatingMenu('array', this.props.eson[SELECTION])
|
||||
const nodeEnd = this.props.eson[EXPANDED]
|
||||
? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
|
||||
this.renderDelimiter(']', 'jsoneditor-delimiter-end'),
|
||||
this.renderInsertAfter()
|
||||
this.renderDelimiter(']', 'jsoneditor-delimiter-end')
|
||||
])
|
||||
: null
|
||||
|
||||
|
@ -219,7 +218,6 @@ export default class JSONNode extends PureComponent {
|
|||
this.renderProperty(),
|
||||
this.renderSeparator(),
|
||||
this.renderValue(this.props.eson[VALUE], this.props.eson[SEARCH_VALUE], this.props.options), // FIXME
|
||||
this.renderInsertAfter(),
|
||||
this.renderError(this.props.eson[ERROR])
|
||||
])
|
||||
|
||||
|
@ -236,24 +234,6 @@ export default class JSONNode extends PureComponent {
|
|||
}, [node, floatingMenu])
|
||||
}
|
||||
|
||||
renderInsertBefore () {
|
||||
return h('div', {
|
||||
key: 'insert',
|
||||
className: 'jsoneditor-insert jsoneditor-insert-before',
|
||||
title: 'Insert a new item or paste clipboard',
|
||||
'data-area': 'inside'
|
||||
})
|
||||
}
|
||||
|
||||
renderInsertAfter () {
|
||||
return h('div', {
|
||||
key: 'insert',
|
||||
className: 'jsoneditor-insert jsoneditor-insert-after',
|
||||
title: 'Insert a new item or paste clipboard after this line',
|
||||
'data-area': 'after'
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Render contents for an empty object or array
|
||||
* @param {string} text
|
||||
|
@ -398,7 +378,10 @@ export default class JSONNode extends PureComponent {
|
|||
onFocus: this.updatePopoverDirection,
|
||||
onMouseOver: this.updatePopoverDirection
|
||||
},
|
||||
h('div', {className: 'jsoneditor-popover jsoneditor-right'}, error.message)
|
||||
[
|
||||
h('i', {className: 'fa fa-exclamation-triangle'}),
|
||||
h('div', {className: 'jsoneditor-popover jsoneditor-right'}, error.message)
|
||||
]
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
@ -445,7 +428,7 @@ export default class JSONNode extends PureComponent {
|
|||
*/
|
||||
updatePopoverDirection = (event) => {
|
||||
if (event.target.nodeName === 'BUTTON') {
|
||||
const popover = event.target.firstChild
|
||||
const popover = event.target.lastChild
|
||||
|
||||
const directions = ['right', 'above', 'below', 'left']
|
||||
for (let i = 0; i < directions.length; i++) {
|
||||
|
@ -537,16 +520,19 @@ export default class JSONNode extends PureComponent {
|
|||
}
|
||||
|
||||
renderExpandButton () {
|
||||
const className = `jsoneditor-button jsoneditor-${this.props.eson[EXPANDED] ? 'expanded' : 'collapsed'}`
|
||||
const expanded = this.props.eson[EXPANDED]
|
||||
const className = `jsoneditor-button jsoneditor-${expanded ? 'expanded' : 'collapsed'}`
|
||||
|
||||
return h('div', {key: 'expand', className: 'jsoneditor-button-container'},
|
||||
// unique key depending on expanded state is to force the fontawesome icon to update
|
||||
return h('div', {key: expanded, className: 'jsoneditor-button-container'},
|
||||
h('button', {
|
||||
className: className,
|
||||
onClick: this.handleExpand,
|
||||
title:
|
||||
'Click to expand/collapse this field. \n' +
|
||||
'Ctrl+Click to expand/collapse including all childs.'
|
||||
})
|
||||
}, h('i', {
|
||||
className: expanded ? 'fa fa-caret-down' : 'fa fa-caret-right'}))
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
import { createElement as h, Component } from 'react'
|
||||
import { Component, createElement as h } from 'react'
|
||||
import Ajv from 'ajv'
|
||||
import { parseJSON } from '../utils/jsonUtils'
|
||||
import { escapeUnicodeChars } from '../utils/stringUtils'
|
||||
import { enrichSchemaError, limitErrors } from '../utils/schemaUtils'
|
||||
import { createFindKeyBinding } from '../utils/keyBindings'
|
||||
import { KEY_BINDINGS } from '../constants'
|
||||
|
||||
import ModeButton from './menu/ModeButton'
|
||||
import { immutableJSONPatch } from '../immutableJSONPatch'
|
||||
import TextModeMenu from './menu/TextModeMenu'
|
||||
|
||||
import fontawesome from '@fortawesome/fontawesome'
|
||||
import faExclamationTriangle from '@fortawesome/fontawesome-free-solid/faExclamationTriangle'
|
||||
|
||||
fontawesome.library.add(faExclamationTriangle)
|
||||
|
||||
const AJV_OPTIONS = {
|
||||
allErrors: true,
|
||||
|
@ -112,37 +116,15 @@ export default class TextMode extends Component {
|
|||
|
||||
/** @protected */
|
||||
renderMenu () {
|
||||
// TODO: move Menu into a separate Component
|
||||
return h('div', {key: 'menu', className: 'jsoneditor-menu'}, [
|
||||
h('button', {
|
||||
key: 'format',
|
||||
className: 'jsoneditor-format',
|
||||
title: 'Format the JSON document',
|
||||
onClick: this.handleFormat
|
||||
}),
|
||||
h('button', {
|
||||
key: 'compact',
|
||||
className: 'jsoneditor-compact',
|
||||
title: 'Compact the JSON document',
|
||||
onClick: this.handleCompact
|
||||
}),
|
||||
return h(TextModeMenu, {
|
||||
mode: this.props.mode,
|
||||
modes: this.props.modes,
|
||||
onChangeMode: this.props.onChangeMode,
|
||||
|
||||
// TODO: implement a button "Repair"
|
||||
|
||||
h('div', {
|
||||
key: 'separator',
|
||||
className: 'jsoneditor-vertical-menu-separator'
|
||||
}),
|
||||
|
||||
this.props.modes && h(ModeButton, {
|
||||
key: 'mode',
|
||||
// TODO: simply pass all options?
|
||||
modes: this.props.modes,
|
||||
mode: this.props.mode,
|
||||
onChangeMode: this.props.onChangeMode,
|
||||
onError: this.props.onError
|
||||
})
|
||||
])
|
||||
onFormat: this.handleFormat,
|
||||
onCompact: this.handleCompact,
|
||||
onRepair: this.handleRepair
|
||||
})
|
||||
}
|
||||
|
||||
/** @protected */
|
||||
|
@ -188,7 +170,8 @@ export default class TextMode extends Component {
|
|||
* @return {JSX.Element}
|
||||
*/
|
||||
static renderSchemaError (error, index) {
|
||||
const icon = h('input', {type: 'button', className: 'jsoneditor-schema-error'})
|
||||
const icon = h('button', {className: 'jsoneditor-schema-error'},
|
||||
h('i', {className: 'fa fa-exclamation-triangle'}))
|
||||
|
||||
if (error && error.schema && error.schemaPath) {
|
||||
// this is an ajv error message
|
||||
|
@ -301,6 +284,13 @@ export default class TextMode extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
/** @protected */
|
||||
handleRepair = () => {
|
||||
// FIXME: implement repair button
|
||||
console.log('handleRepair not yet implemented')
|
||||
alert('sorry, not yet implemented...')
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply new text to the state, and emit an onChangeText event if there is a change
|
||||
* @param {string} text
|
||||
|
|
|
@ -30,8 +30,6 @@ import {
|
|||
import JSONNode from './JSONNode'
|
||||
import JSONNodeView from './JSONNodeView'
|
||||
import JSONNodeForm from './JSONNodeForm'
|
||||
import ModeButton from './menu/ModeButton'
|
||||
import Search from './menu/Search'
|
||||
import {
|
||||
findBaseNode,
|
||||
findNode,
|
||||
|
@ -64,6 +62,7 @@ import {
|
|||
syncEson
|
||||
} from '../eson'
|
||||
import TreeModeMenu from './menu/TreeModeMenu'
|
||||
import Search from './menu/Search'
|
||||
|
||||
const AJV_OPTIONS = {
|
||||
allErrors: true,
|
||||
|
@ -73,6 +72,7 @@ const AJV_OPTIONS = {
|
|||
|
||||
const MAX_HISTORY_ITEMS = 1000 // maximum number of undo/redo items to be kept in memory
|
||||
const SCROLL_DURATION = 400 // milliseconds
|
||||
const SEARCH_DEBOUNCE = 300 // milliseconds
|
||||
|
||||
export default class TreeMode extends PureComponent {
|
||||
id = Math.round(Math.random() * 1e5) // TODO: create a uuid here?
|
||||
|
@ -136,6 +136,7 @@ export default class TreeMode extends PureComponent {
|
|||
|
||||
options: {},
|
||||
|
||||
showSearch: false,
|
||||
searchResult: {
|
||||
text: '',
|
||||
matches: null,
|
||||
|
@ -238,6 +239,8 @@ export default class TreeMode extends PureComponent {
|
|||
}, [
|
||||
this.renderMenu(),
|
||||
|
||||
this.renderSearch(),
|
||||
|
||||
h('div', {
|
||||
key: 'contents',
|
||||
ref: 'contents',
|
||||
|
@ -273,22 +276,30 @@ export default class TreeMode extends PureComponent {
|
|||
modes: this.props.modes,
|
||||
onChangeMode: this.props.onChangeMode,
|
||||
|
||||
onExpandAll: this.handleExpandAll,
|
||||
onCollapseAll: this.handleCollapseAll,
|
||||
|
||||
enableHistory: this.props.history,
|
||||
canUndo: this.canUndo(),
|
||||
canRedo: this.canRedo(),
|
||||
onUndo: this.undo,
|
||||
onRedo: this.redo,
|
||||
|
||||
enableSearch: this.props.search,
|
||||
searchResult: this.state.searchResult,
|
||||
onSearch: this.handleSearch,
|
||||
onSearchNext: this.handleNext,
|
||||
onSearchPrevious: this.handlePrevious,
|
||||
onToggleSearch: this.toggleSearch
|
||||
})
|
||||
}
|
||||
|
||||
findKeyBinding: this.findKeyBinding,
|
||||
renderSearch () {
|
||||
if (!this.state.showSearch) {
|
||||
return null
|
||||
}
|
||||
|
||||
return 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.props.findKeyBinding,
|
||||
delay: SEARCH_DEBOUNCE
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -602,6 +613,12 @@ export default class TreeMode extends PureComponent {
|
|||
})
|
||||
}
|
||||
|
||||
toggleSearch = () => {
|
||||
this.setState({
|
||||
showSearch: !this.state.showSearch
|
||||
})
|
||||
}
|
||||
|
||||
handleSearch = (text) => {
|
||||
// FIXME
|
||||
// FIXME: also apply search when eson is changed
|
||||
|
|
|
@ -17,74 +17,6 @@ $insert-area-height: 6px;
|
|||
line-height: normal;
|
||||
}
|
||||
|
||||
.jsoneditor-menu {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: white;
|
||||
background-color: $theme-color;
|
||||
flex: 0 0 auto;
|
||||
|
||||
button {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
border-radius: 2px;
|
||||
border: 1px solid transparent;
|
||||
background: transparent url('img/jsoneditor-icons.svg');
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border: 1px solid rgba(255,255,255,0.4);
|
||||
}
|
||||
button:focus,
|
||||
button:active {
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.jsoneditor-vertical-menu-separator {
|
||||
width: 8px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button.jsoneditor-expand-all {
|
||||
background-position: 0 -120px;
|
||||
}
|
||||
button.jsoneditor-collapse-all {
|
||||
background-position: 0 -96px;
|
||||
}
|
||||
|
||||
button.jsoneditor-undo {
|
||||
background-position: -24px -96px;
|
||||
}
|
||||
button.jsoneditor-undo:disabled {
|
||||
background-position: -24px -120px;
|
||||
}
|
||||
button.jsoneditor-redo {
|
||||
background-position: -48px -96px;
|
||||
}
|
||||
button.jsoneditor-redo:disabled {
|
||||
background-position: -48px -120px;
|
||||
}
|
||||
|
||||
button.jsoneditor-compact {
|
||||
background-position: -72px -96px;
|
||||
}
|
||||
button.jsoneditor-format {
|
||||
background-position: -72px -120px;
|
||||
}
|
||||
}
|
||||
|
||||
.jsoneditor-contents {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -337,7 +269,9 @@ button.jsoneditor-button {
|
|||
margin: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
background: transparent url('img/jsoneditor-icons.svg');
|
||||
background: transparent;
|
||||
color: $gray-icon;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
button.jsoneditor-button:focus {
|
||||
|
@ -349,31 +283,6 @@ button.jsoneditor-button:focus {
|
|||
outline: #e5e5e5 solid 1px;
|
||||
}
|
||||
|
||||
/* FIXME: change icons from size 24x24 to 20x20 */
|
||||
|
||||
button.jsoneditor-button.jsoneditor-collapsed {
|
||||
background-position: -2px -50px;
|
||||
}
|
||||
|
||||
button.jsoneditor-button.jsoneditor-expanded {
|
||||
background-position: -2px -74px;
|
||||
}
|
||||
|
||||
button.jsoneditor-button.jsoneditor-drag {
|
||||
background-position: -74px -74px;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
button.jsoneditor-button.jsoneditor-actionmenu {
|
||||
background-position: -50px -74px;
|
||||
}
|
||||
|
||||
button.jsoneditor-button.jsoneditor-actionmenu:hover,
|
||||
button.jsoneditor-button.jsoneditor-actionmenu:focus,
|
||||
button.jsoneditor-button.jsoneditor-actionmenu.jsoneditor-visible {
|
||||
background-position: -50px -50px;
|
||||
}
|
||||
|
||||
/*********************************** Menu *************************************/
|
||||
|
||||
div.jsoneditor-menu-panel-right {
|
||||
|
@ -445,159 +354,6 @@ button.jsoneditor-menu-button.jsoneditor-selected {
|
|||
button.jsoneditor-menu-default {
|
||||
width: 104px; /* 136px - 32px */
|
||||
}
|
||||
//
|
||||
//button.jsoneditor-menu-expand {
|
||||
// width: 32px;
|
||||
// float: right;
|
||||
// border-left: 1px solid #e5e5e5;
|
||||
//}
|
||||
|
||||
//span.jsoneditor-icon {
|
||||
// float: left;
|
||||
// width: 24px;
|
||||
// height: 24px;
|
||||
// border: none;
|
||||
// padding: 0;
|
||||
// margin: 0;
|
||||
// background-image: url('img/jsoneditor-icons.svg');
|
||||
//}
|
||||
//
|
||||
//span.jsoneditor-icon.jsoneditor-icon-expand {
|
||||
// float: right;
|
||||
// width: 24px;
|
||||
// margin: 0 4px;
|
||||
//
|
||||
// background-position: 0 -72px !important;
|
||||
// opacity: 0.4;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-menu-item button.jsoneditor-menu-button:hover span.jsoneditor-icon-expand,
|
||||
//div.jsoneditor-menu-item button:focus span.jsoneditor-icon-expand {
|
||||
// opacity: 1;
|
||||
//}
|
||||
//
|
||||
//span.jsoneditor-text {
|
||||
// display: inline-block;
|
||||
// line-height: 24px;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-menu-separator {
|
||||
// height: 0;
|
||||
// border-top: 1px solid #e5e5e5;
|
||||
// padding-top: 5px;
|
||||
// margin-top: 5px;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-remove span.jsoneditor-icon {
|
||||
// background-position: -24px -24px;
|
||||
//}
|
||||
//button.jsoneditor-remove:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-remove:focus span.jsoneditor-icon {
|
||||
// background-position: -24px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-insert span.jsoneditor-icon {
|
||||
// background-position: 0 -24px;
|
||||
//}
|
||||
//button.jsoneditor-insert:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-insert:focus span.jsoneditor-icon {
|
||||
// background-position: 0 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-duplicate span.jsoneditor-icon {
|
||||
// background-position: -48px -24px;
|
||||
//}
|
||||
//button.jsoneditor-duplicate:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-duplicate:focus span.jsoneditor-icon {
|
||||
// background-position: -48px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-sort-asc span.jsoneditor-icon {
|
||||
// background-position: -168px -24px;
|
||||
//}
|
||||
//button.jsoneditor-sort-asc:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-sort-asc:focus span.jsoneditor-icon {
|
||||
// background-position: -168px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-sort-desc span.jsoneditor-icon {
|
||||
// background-position: -192px -24px;
|
||||
//}
|
||||
//button.jsoneditor-sort-desc:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-sort-desc:focus span.jsoneditor-icon {
|
||||
// background-position: -192px 0;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu {
|
||||
// visibility: hidden;
|
||||
// max-height: 0;
|
||||
//
|
||||
// overflow: hidden;
|
||||
//
|
||||
// transition: max-height 0.3s ease-out;
|
||||
//
|
||||
// box-shadow: inset 0 10px 10px -10px rgba(128, 128, 128, 0.5),
|
||||
// inset 0 -10px 10px -10px rgba(128, 128, 128, 0.5)
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu.jsoneditor-expanded {
|
||||
// visibility: visible;
|
||||
// max-height: 104px; /* 4 * 24px + 2 * 5px */
|
||||
// /* FIXME: shouldn't rely on max-height equal to 4 items, should be flexible */
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu.jsoneditor-collapsing {
|
||||
// visibility: visible;
|
||||
// max-height: 0;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu button {
|
||||
// padding-left: 24px;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu div.jsoneditor-menu-item:first-child {
|
||||
// margin-top: 5px;
|
||||
//}
|
||||
//
|
||||
//div.jsoneditor-submenu div.jsoneditor-menu-item:last-child {
|
||||
// margin-bottom: 5px;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-type-string span.jsoneditor-icon {
|
||||
// background-position: -144px -24px;
|
||||
//}
|
||||
//button.jsoneditor-type-string:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-string:focus span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-string.jsoneditor-selected span.jsoneditor-icon {
|
||||
// background-position: -144px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-type-value span.jsoneditor-icon {
|
||||
// background-position: -120px -24px;
|
||||
//}
|
||||
//button.jsoneditor-type-value:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-value:focus span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-value.jsoneditor-selected span.jsoneditor-icon {
|
||||
// background-position: -120px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-type-Object span.jsoneditor-icon {
|
||||
// background-position: -72px -24px;
|
||||
//}
|
||||
//button.jsoneditor-type-Object:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-Object:focus span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-Object.jsoneditor-selected span.jsoneditor-icon {
|
||||
// background-position: -72px 0;
|
||||
//}
|
||||
//
|
||||
//button.jsoneditor-type-Array span.jsoneditor-icon {
|
||||
// background-position: -96px -24px;
|
||||
//}
|
||||
//button.jsoneditor-type-Array:hover span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-Array:focus span.jsoneditor-icon,
|
||||
//button.jsoneditor-type-Array.jsoneditor-selected span.jsoneditor-icon {
|
||||
// background-position: -96px 0;
|
||||
//}
|
||||
|
||||
/******************************* Floating Menu **********************************/
|
||||
|
||||
|
@ -665,39 +421,6 @@ div.jsoneditor-node-container {
|
|||
}
|
||||
}
|
||||
|
||||
div.jsoneditor-insert {
|
||||
width: $line-height;
|
||||
height: $line-height;
|
||||
|
||||
&:hover {
|
||||
background: url('img/jsoneditor-icons.svg') -2px -26px;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsoneditor-selected-insert-after {
|
||||
border-bottom: 1px dashed $light-gray;
|
||||
margin-bottom: -1px;
|
||||
|
||||
> .jsoneditor-node > .jsoneditor-insert-after,
|
||||
> .jsoneditor-node-end > .jsoneditor-insert-after {
|
||||
background-image: url('img/jsoneditor-icons.svg');
|
||||
background-position: -2px -2px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsoneditor-selected-insert-before {
|
||||
> .jsoneditor-node > .jsoneditor-insert-before,
|
||||
> .jsoneditor-node-end > .jsoneditor-insert-before {
|
||||
background-image: url('img/jsoneditor-icons.svg');
|
||||
background-position: -2px -2px !important;
|
||||
}
|
||||
|
||||
> .jsoneditor-list {
|
||||
border-top: 1px dashed $light-gray;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.jsoneditor-hover {
|
||||
> .jsoneditor-node > .jsoneditor-button-container,
|
||||
> .jsoneditor-node > .jsoneditor-button-placeholder {
|
||||
|
@ -712,10 +435,8 @@ div.jsoneditor-node-container {
|
|||
//padding-left: $line-height + $input-padding + 2px;
|
||||
border-left-color: $hoverColor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
div.jsoneditor-floating-menu {
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
|
@ -782,15 +503,16 @@ div.jsoneditor-node-container {
|
|||
}
|
||||
|
||||
/******************************* **********************************/
|
||||
|
||||
div.jsoneditor-modes {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
|
||||
button {
|
||||
background: none;
|
||||
width: auto;
|
||||
padding: 2px 6px;
|
||||
font-size: $fontSize;
|
||||
}
|
||||
|
||||
button.jsoneditor-type-modes {
|
||||
|
@ -855,7 +577,7 @@ div.jsoneditor-code {
|
|||
}
|
||||
|
||||
|
||||
.jsoneditor-schema-error {
|
||||
button.jsoneditor-schema-error {
|
||||
//user-select: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
|
@ -863,6 +585,7 @@ div.jsoneditor-code {
|
|||
height: 20px;
|
||||
padding: 0;
|
||||
margin: 0 4px;
|
||||
background: url('img/jsoneditor-icons.svg') -171px -49px;
|
||||
background: transparent;
|
||||
color: $warning-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
@import '../style.scss';
|
||||
@import './MenuButton.scss';
|
||||
|
||||
.jsoneditor-menu {
|
||||
// TODO: there is also css for this menu in jsoneditor.scss, move this here
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
color: white;
|
||||
background-color: $theme-color;
|
||||
flex: 0 0 auto;
|
||||
|
||||
.jsoneditor-menu-group {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
.jsoneditor-menu {
|
||||
|
||||
.jsoneditor-menu-group:not(:first-child) {
|
||||
border-left: 1px solid rgba(255,255,255, 0.1);
|
||||
margin-left: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin: 2px;
|
||||
padding: 0;
|
||||
border-radius: 2px;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: white;
|
||||
opacity: 0.8;
|
||||
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border: 1px solid rgba(255,255,255,0.4);
|
||||
}
|
||||
button:focus,
|
||||
button:active {
|
||||
background-color: rgba(255,255,255,0.3);
|
||||
}
|
||||
button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
|
@ -3,8 +3,17 @@ import PropTypes from 'prop-types'
|
|||
import { keyComboFromEvent } from '../../utils/keyBindings'
|
||||
import { findEditorContainer, setSelection } from '../utils/domSelector'
|
||||
|
||||
import fontawesome from '@fortawesome/fontawesome'
|
||||
import faSearch from '@fortawesome/fontawesome-free-solid/faSearch'
|
||||
import faCaretUp from '@fortawesome/fontawesome-free-solid/faCaretUp'
|
||||
import faCaretDown from '@fortawesome/fontawesome-free-solid/faCaretDown'
|
||||
|
||||
import './Menu.css'
|
||||
|
||||
import './Search.css'
|
||||
|
||||
fontawesome.library.add(faSearch, faCaretUp, faCaretDown)
|
||||
|
||||
export default class Search extends Component {
|
||||
constructor (props) {
|
||||
super (props)
|
||||
|
@ -16,12 +25,14 @@ export default class Search extends Component {
|
|||
|
||||
render () {
|
||||
return h('div', {className: 'jsoneditor-search'}, [
|
||||
this.renderResultsCount(this.props.resultCount),
|
||||
h('form', {
|
||||
key: 'box',
|
||||
className: 'jsoneditor-search-box',
|
||||
onSubmit: this.handleSubmit
|
||||
}, [
|
||||
h('div', { className: 'jsoneditor-search-icon' }, [
|
||||
h('i', {className: 'fa fa-search'})
|
||||
]),
|
||||
h('input', {
|
||||
key: 'input',
|
||||
type: 'text',
|
||||
|
@ -30,21 +41,22 @@ export default class Search extends Component {
|
|||
onInput: this.handleChange,
|
||||
onKeyDown: this.handleKeyDown
|
||||
}),
|
||||
h('input', {
|
||||
h('button', {
|
||||
key: 'next',
|
||||
type: 'button',
|
||||
className: 'jsoneditor-search-next',
|
||||
title: 'Next result',
|
||||
onClick: this.props.onNext
|
||||
}),
|
||||
h('input', {
|
||||
}, h('i', {className: 'fa fa-caret-down'})),
|
||||
h('button', {
|
||||
key: 'previous',
|
||||
type: 'button',
|
||||
className: 'jsoneditor-search-previous',
|
||||
title: 'Previous result',
|
||||
onClick: this.props.onPrevious
|
||||
})
|
||||
])
|
||||
}, h('i', {className: 'fa fa-caret-up'}))
|
||||
]),
|
||||
this.renderResultsCount(this.props.resultCount)
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -54,13 +66,13 @@ export default class Search extends Component {
|
|||
}
|
||||
|
||||
if (resultCount === 0) {
|
||||
return h('div', {key: 'count', className: 'jsoneditor-results'}, '(no results)')
|
||||
return h('div', {key: 'count', className: 'jsoneditor-search-results'}, '(no results)')
|
||||
}
|
||||
|
||||
if (resultCount > 0) {
|
||||
const suffix = resultCount === 1 ? ' result' : ' results'
|
||||
|
||||
return h('div', {key: 'count', className: 'jsoneditor-results'}, resultCount + suffix)
|
||||
return h('div', {key: 'count', className: 'jsoneditor-search-results'}, resultCount + suffix)
|
||||
}
|
||||
|
||||
return null
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
@import '../style.scss';
|
||||
|
||||
$theme-color: #3883fa;
|
||||
|
||||
div.jsoneditor-search {
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
|
||||
div.jsoneditor-results {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
position: relative;
|
||||
background: $theme-color;
|
||||
font-family: $fontFamilyMenu;
|
||||
font-size: $fontSize;
|
||||
|
||||
form.jsoneditor-search-box {
|
||||
display: inline-flex;
|
||||
|
@ -15,18 +14,22 @@ div.jsoneditor-search {
|
|||
max-width: 100%;
|
||||
|
||||
background-color: white;
|
||||
border: 2px solid $theme-color;
|
||||
border: 1px solid $theme-color;
|
||||
border-left-width: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
$search-icon-width: 22px;
|
||||
$search-icon-width: 28px;
|
||||
$search-icon-padding: 4px;
|
||||
|
||||
&::before {
|
||||
div.jsoneditor-search-icon {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
width: $search-icon-width;
|
||||
height: 100%;
|
||||
background: transparent url('../img/jsoneditor-icons.svg') -97px -71px;
|
||||
content: '';
|
||||
height: $search-icon-width;
|
||||
color: $light-gray;
|
||||
font-size: 16px;
|
||||
padding: $search-icon-padding;
|
||||
line-height: $search-icon-width - 2 * $search-icon-padding;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input.jsoneditor-search-text {
|
||||
|
@ -43,42 +46,28 @@ div.jsoneditor-search {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
input[type=button] {
|
||||
button {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
line-height: 22px;
|
||||
margin: 2px 0;
|
||||
padding: 0;
|
||||
line-height: 28px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
background: transparent url('../img/jsoneditor-icons.svg');
|
||||
opacity: 0.8;
|
||||
outline: none;
|
||||
color: $light-gray;
|
||||
|
||||
font-family: arial, sans-serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
input[type=button]:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
input.jsoneditor-search-next {
|
||||
cursor: pointer;
|
||||
background-position: -124px -73px;
|
||||
}
|
||||
input.jsoneditor-search-next:hover {
|
||||
background-position: -124px -49px;
|
||||
}
|
||||
|
||||
input.jsoneditor-search-previous {
|
||||
cursor: pointer;
|
||||
background-position: -148px -73px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
input.jsoneditor-search-previous:hover {
|
||||
background-position: -148px -49px;
|
||||
font-size: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
div.jsoneditor-search-results {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import { createElement as h, PureComponent } from 'react'
|
||||
import ModeButton from './ModeButton'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import fontawesome from '@fortawesome/fontawesome'
|
||||
import faAlignLeft from '@fortawesome/fontawesome-free-solid/faAlignLeft'
|
||||
import faAlignJustify from '@fortawesome/fontawesome-free-solid/faAlignJustify'
|
||||
import faScrewdriver from '@fortawesome/fontawesome-free-solid/faScrewdriver'
|
||||
|
||||
import './Menu.css'
|
||||
|
||||
fontawesome.library.add(faAlignLeft, faAlignJustify, faScrewdriver)
|
||||
|
||||
export default class TreeModeMenu extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
mode: PropTypes.string.isRequired,
|
||||
modes: PropTypes.arrayOf(PropTypes.string),
|
||||
onChangeMode: PropTypes.func.isRequired,
|
||||
|
||||
onFormat: PropTypes.func.isRequired,
|
||||
onCompact: PropTypes.func.isRequired,
|
||||
onRepair: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
render () {
|
||||
let items = []
|
||||
|
||||
// mode
|
||||
if (this.props.modes ) {
|
||||
items = items.concat([
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
h(ModeButton, {
|
||||
key: 'mode',
|
||||
modes: this.props.modes,
|
||||
mode: this.props.mode,
|
||||
onChangeMode: this.props.onChangeMode,
|
||||
onError: this.props.onError
|
||||
})
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
// format / compact / repair
|
||||
items = items.concat([
|
||||
h('button', {
|
||||
key: 'format',
|
||||
className: 'jsoneditor-format',
|
||||
title: 'Format the JSON document',
|
||||
onClick: this.props.onFormat
|
||||
}, h('i', {className: 'fa fa-align-left'})),
|
||||
h('button', {
|
||||
key: 'compact',
|
||||
className: 'jsoneditor-compact',
|
||||
title: 'Compact the JSON document',
|
||||
onClick: this.props.onCompact
|
||||
}, h('i', {className: 'fa fa-align-justify'})),
|
||||
h('button', {
|
||||
key: 'repair',
|
||||
className: 'jsoneditor-repair',
|
||||
title: 'Repair the JSON document',
|
||||
onClick: this.props.onRepair
|
||||
}, h('i', {className: 'fa fa-screwdriver'})),
|
||||
])
|
||||
|
||||
return h('div', {key: 'menu', className: 'jsoneditor-menu'}, items)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,31 @@
|
|||
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
|
||||
import fontawesome from '@fortawesome/fontawesome'
|
||||
import faPlusSquare from '@fortawesome/fontawesome-free-solid/faPlusSquare'
|
||||
import faMinusSquare from '@fortawesome/fontawesome-free-solid/faMinusSquare'
|
||||
import faCut from '@fortawesome/fontawesome-free-solid/faCut'
|
||||
import faCopy from '@fortawesome/fontawesome-free-solid/faCopy'
|
||||
import faPaste from '@fortawesome/fontawesome-free-solid/faPaste'
|
||||
import faPlus from '@fortawesome/fontawesome-free-solid/faPlus'
|
||||
import faClone from '@fortawesome/fontawesome-free-solid/faClone'
|
||||
import faTimes from '@fortawesome/fontawesome-free-solid/faTimes'
|
||||
import faUndo from '@fortawesome/fontawesome-free-solid/faUndo'
|
||||
import faRedo from '@fortawesome/fontawesome-free-solid/faRedo'
|
||||
import faSortAmountDown from '@fortawesome/fontawesome-free-solid/faSortAmountDown'
|
||||
import faFilter from '@fortawesome/fontawesome-free-solid/faFilter'
|
||||
import faSearch from '@fortawesome/fontawesome-free-solid/faSearch'
|
||||
|
||||
import './Menu.css'
|
||||
|
||||
fontawesome.library.add(
|
||||
faPlusSquare, faMinusSquare,
|
||||
faCut, faCopy, faPaste,
|
||||
faPlus, faClone, faTimes,
|
||||
faUndo, faRedo,
|
||||
faSortAmountDown, faFilter, faSearch
|
||||
)
|
||||
|
||||
export default class TreeModeMenu extends PureComponent {
|
||||
|
||||
|
@ -12,8 +34,12 @@ export default class TreeModeMenu extends PureComponent {
|
|||
modes: PropTypes.arrayOf(PropTypes.string),
|
||||
onChangeMode: PropTypes.func.isRequired,
|
||||
|
||||
onExpandAll: PropTypes.func.isRequired,
|
||||
onCollapseAll: PropTypes.func.isRequired,
|
||||
canCut: PropTypes.bool.isRequired,
|
||||
canCopy: PropTypes.bool.isRequired,
|
||||
canPaste: PropTypes.bool.isRequired,
|
||||
onCut: PropTypes.func.isRequired,
|
||||
onCopy: PropTypes.func.isRequired,
|
||||
onPaste: PropTypes.func.isRequired,
|
||||
|
||||
enableHistory: PropTypes.bool,
|
||||
canUndo: PropTypes.bool,
|
||||
|
@ -21,80 +47,124 @@ export default class TreeModeMenu extends PureComponent {
|
|||
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,
|
||||
onToggleSearch: PropTypes.func
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
])
|
||||
}
|
||||
let items = []
|
||||
|
||||
// mode
|
||||
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
|
||||
})
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
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
|
||||
// cut / copy / paste
|
||||
items = items.concat([
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
h('button', {
|
||||
key: 'cut',
|
||||
className: 'jsoneditor-cut',
|
||||
title: 'Cut current selection',
|
||||
disabled: !this.props.canCut,
|
||||
onClick: this.props.onCut
|
||||
}, h('i', {className: 'fa fa-cut'})),
|
||||
h('button', {
|
||||
key: 'copy',
|
||||
className: 'jsoneditor-copy',
|
||||
title: 'Copy current selection',
|
||||
// disabled: !this.props.canPaste,
|
||||
onClick: this.props.onPaste
|
||||
}, h('i', {className: 'fa fa-copy'})),
|
||||
h('button', {
|
||||
key: 'paste',
|
||||
className: 'jsoneditor-paste',
|
||||
title: 'Paste copied selection',
|
||||
// disabled: !this.props.canPaste,
|
||||
onClick: this.props.onPaste
|
||||
}, h('i', {className: 'fa fa-paste'}))
|
||||
])
|
||||
])
|
||||
|
||||
// TODO: [insert structure / insert value / insert array / insert object] / duplicate / remove
|
||||
items = items.concat([
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
h('button', {
|
||||
key: 'insert',
|
||||
className: 'jsoneditor-insert',
|
||||
title: 'Insert new contents',
|
||||
onClick: this.props.onInsert
|
||||
}, h('i', {className: 'fa fa-plus'})),
|
||||
h('button', {
|
||||
key: 'duplicate',
|
||||
className: 'jsoneditor-duplicate',
|
||||
title: 'Duplicate current selection',
|
||||
disabled: !this.props.canDuplicate,
|
||||
onClick: this.props.onDuplicate
|
||||
}, h('i', {className: 'fa fa-clone'})),
|
||||
h('button', {
|
||||
key: 'remove',
|
||||
className: 'jsoneditor-remove',
|
||||
title: 'Remove selection',
|
||||
disabled: !this.props.canRemove,
|
||||
onClick: this.props.onRemove
|
||||
}, h('i', {className: 'fa fa-times'}))
|
||||
])
|
||||
])
|
||||
|
||||
// sort / transform
|
||||
items = items.concat([
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
h('button', {
|
||||
key: 'sort',
|
||||
className: 'jsoneditor-sort',
|
||||
title: 'Sort contents',
|
||||
onClick: this.props.onSort // TODO: implement onSort
|
||||
}, h('i', {className: 'fa fa-sort-amount-down'})),
|
||||
h('button', {
|
||||
key: 'transform',
|
||||
className: 'jsoneditor-transform',
|
||||
title: 'Transform contents',
|
||||
// disabled: !this.props.canPaste,
|
||||
onClick: this.props.onTransform
|
||||
}, h('i', {className: 'fa fa-filter'})),
|
||||
h('button', {
|
||||
key: 'search',
|
||||
className: 'jsoneditor-search',
|
||||
title: 'Search and replace',
|
||||
onClick: this.props.onToggleSearch
|
||||
}, h('i', {className: 'fa fa-search'}))
|
||||
])
|
||||
])
|
||||
|
||||
// undo / redo
|
||||
if (this.props.mode !== 'view' && this.props.enableHistory !== false) {
|
||||
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
|
||||
})
|
||||
)
|
||||
h('div', {className: 'jsoneditor-menu-group'}, [
|
||||
h('button', {
|
||||
key: 'undo',
|
||||
className: 'jsoneditor-undo',
|
||||
title: 'Undo last action',
|
||||
disabled: !this.props.canUndo,
|
||||
onClick: this.props.onUndo
|
||||
}, h('i', {className: 'fa fa-undo'})),
|
||||
h('button', {
|
||||
key: 'redo',
|
||||
className: 'jsoneditor-redo',
|
||||
title: 'Redo',
|
||||
disabled: !this.props.canRedo,
|
||||
onClick: this.props.onRedo
|
||||
}, h('i', {className: 'fa fa-redo'}))
|
||||
])
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
$fontFamily: "dejavu sans mono", "droid sans mono", consolas, monaco, "lucida console", "courier new", courier, monospace, sans-serif;
|
||||
$fontSize: 10pt;
|
||||
$fontFamilyMenu: arial, "sans-serif";
|
||||
|
||||
$black: #1A1A1A;
|
||||
$contentsMinHeight: 150px;
|
||||
$theme-color: #3883fa;
|
||||
|
@ -10,6 +12,8 @@ $floating-menu-color: #fff;
|
|||
$selectedColor: #ffed99;
|
||||
$hoverColor: #d3d3d3;
|
||||
$hoverAndSelectedColor: #ffdb80;
|
||||
$warning-color: #FBB917;
|
||||
$gray: #9d9d9d;
|
||||
$gray-icon: #5e5e5e;
|
||||
$light-gray: #c0c0c0;
|
||||
$input-padding: 5px;
|
||||
|
|
|
@ -158,7 +158,7 @@ export function findParentWithClassName (element, className) {
|
|||
* @return {boolean}
|
||||
*/
|
||||
export function hasClassName (element, className) {
|
||||
return element && element.className
|
||||
return element && element.className && element.className.split
|
||||
? element.className.split(' ').indexOf(className) !== -1
|
||||
: false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue