diff --git a/package.json b/package.json index 145b75a..a119b9a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "randomcolor": "^0.4.4", "react": "^15.4.0", "react-addons-pure-render-mixin": "^15.4.0", + "react-codemirror": "^0.3.0", "react-collapse": "^2.3.3", "react-color": "^2.10.0", "react-dom": "^15.4.0", diff --git a/src/codemirror-maputnik.css b/src/codemirror-maputnik.css new file mode 100644 index 0000000..c5808a1 --- /dev/null +++ b/src/codemirror-maputnik.css @@ -0,0 +1,43 @@ +.cm-s-maputnik.CodeMirror { + height: 100%; + font-size: 10px; +} + +.cm-s-maputnik.CodeMirror, .cm-s-maputnik .CodeMirror-gutters { + background: transparent; + color: #8e8e8e; + border: none; +} +.cm-s-maputnik .CodeMirror-cursor { + border-left: solid thin #8e8e8e !important; +} + +.cm-s-maputnik.CodeMirror-focused div.CodeMirror-selected { + background: rgba(255, 255, 255, 0.10); +} + +.cm-s-maputnik .CodeMirror-line::selection, +.cm-s-maputnik .CodeMirror-line > span::selection, +.cm-s-maputnik .CodeMirror-line > span > span::selection { + background: rgba(255, 255, 255, 0.10); +} + +.cm-s-maputnik .CodeMirror-line::-moz-selection, +.cm-s-maputnik .CodeMirror-line > span::-moz-selection, +.cm-s-maputnik .CodeMirror-line > span > span::-moz-selection { + background: rgba(255, 255, 255, 0.10); +} + +.cm-s-maputnik span.cm-string, .cm-s-maputnik span.cm-string-2 { + color: #8f9d6a; +} +.cm-s-maputnik span.cm-number { color: #91675f; } +.cm-s-maputnik span.cm-property { color: #b8a077; } + +.cm-s-maputnik .CodeMirror-activeline-background { + background: rgba(255,255,255,0.1); +} + +.cm-s-maputnik .CodeMirror-matchingbracket { + text-decoration: underline; color: white !important; +} diff --git a/src/components/layers/JSONEditor.jsx b/src/components/layers/JSONEditor.jsx new file mode 100644 index 0000000..cc93b01 --- /dev/null +++ b/src/components/layers/JSONEditor.jsx @@ -0,0 +1,64 @@ +import React from 'react' + +import CodeMirror from 'react-codemirror' +import InputBlock from '../inputs/InputBlock' +import StringInput from '../inputs/StringInput' +import SelectInput from '../inputs/SelectInput' + +import colors from '../../config/colors' +import { margins } from '../../config/scales' + +import 'codemirror/mode/javascript/javascript' +import 'codemirror/lib/codemirror.css' +import '../../codemirror-maputnik.css' + + +class JSONEditor extends React.Component { + static propTypes = { + layer: React.PropTypes.object.isRequired, + onChange: React.PropTypes.func, + } + + constructor(props) { + super(props) + this.state = { + code: JSON.stringify(props.layer, null, 2) + } + } + + componentWillReceiveProps(nextProps) { + this.setState({ + code: JSON.stringify(nextProps.layer, null, 2) + }) + } + + onCodeUpdate(newCode) { + try { + const parsedLayer = JSON.parse(newCode) + this.props.onChange(parsedLayer) + } catch(err) { + console.warn(err) + this.setState({ + code: newCode + }) + } + } + + render() { + const codeMirrorOptions = { + mode: {name: "javascript", json: true}, + tabSize: 2, + theme: 'maputnik', + viewportMargin: Infinity, + lineNumbers: false, + } + + return + } +} + +export default JSONEditor diff --git a/src/components/layers/LayerEditor.jsx b/src/components/layers/LayerEditor.jsx index 8af64cc..873e27e 100644 --- a/src/components/layers/LayerEditor.jsx +++ b/src/components/layers/LayerEditor.jsx @@ -1,5 +1,6 @@ import React from 'react' +import JSONEditor from './JSONEditor' import SourceEditor from './SourceEditor' import FilterEditor from '../filter/FilterEditor' import PropertyGroup from '../fields/PropertyGroup' @@ -126,6 +127,10 @@ export default class LayerEditor extends React.Component { groupFields={fields} onChange={this.onPropertyChange.bind(this)} /> + case 'jsoneditor': return default: return null } } diff --git a/src/config/layout.json b/src/config/layout.json index 4e5f561..b947355 100644 --- a/src/config/layout.json +++ b/src/config/layout.json @@ -34,6 +34,10 @@ "line-dasharray", "line-gap-width" ] + }, + { + "title": "JSON", + "type": "jsoneditor" } ] }, @@ -55,6 +59,10 @@ "background-pattern", "background-opacity" ] + }, + { + "title": "JSON", + "type": "jsoneditor" } ] }, @@ -80,6 +88,10 @@ "fill-translate", "fill-translate-anchor" ] + }, + { + "title": "JSON", + "type": "jsoneditor" } ] }, @@ -150,6 +162,10 @@ "icon-keep-upright", "icon-offset" ] + }, + { + "title": "JSON", + "type": "jsoneditor" } ] }