├── .gitattributes ├── .gitignore ├── README.md ├── circle.yml ├── dist └── react-json-editor.js ├── package.json ├── screenshot.png ├── src ├── JsonLeafEditor.js ├── react-json-editor.css └── react-json-editor.js └── webpack.config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # These files are text and should be normalized (convert crlf => lf) 2 | *.c text 3 | *.check text 4 | *.css text 5 | *.html text 6 | *.java text 7 | *.js text 8 | *.sbt text 9 | *.scala text 10 | *.sh text 11 | *.txt text 12 | *.xml text 13 | *.xsd text 14 | *.properties text 15 | *.wt text 16 | *.sql text 17 | *.config text 18 | *.json text 19 | *.strings text 20 | *.ldif text 21 | *.classpath text 22 | *.project text 23 | *.version text 24 | *.wsdl text 25 | 26 | # Windows-specific files get windows endings 27 | *.bat eol=crlf 28 | *.cmd eol=crlf 29 | *-windows.tmpl eol=crlf 30 | 31 | # Visual Studio 32 | *.sln binary 33 | *.csproj binary 34 | *.resx binary 35 | *.pdb binary 36 | *.cs eol=crlf 37 | *.svcmap binary 38 | *.svcinfo binary 39 | *.datasource binary 40 | 41 | 42 | # Some binary file types for completeness 43 | # (binary is a macro for -text -diff) 44 | *.exe binary 45 | *.dll binary 46 | *.gif binary 47 | *.jpg binary 48 | *.png binary 49 | *.class -text diff=class 50 | *.jar -text diff=jar 51 | *.zip binary 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Thumbs.db 2 | .DS_STORE 3 | /node_modules 4 | /bower_components 5 | /js-built 6 | /.idea 7 | /npm-debug.log 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | react-json-editor 2 | ============== 3 | > A generic JSON editor, specifically designed for attaching to React state values. 4 | 5 | ### Warnings 6 | * no documentation, you'll have to read the source 7 | * no tests 8 | 9 | ### Live Demo 10 | [![View Live Demo](screenshot.png?raw=true)](http://demo-react-json-editor.s3-website-us-east-1.amazonaws.com/) 11 | 12 | Here is the [live demo](http://demo-react-json-editor.s3-website-us-east-1.amazonaws.com/), and [source code to the live demo](https://github.com/prognostic-llc/react-json-editor-example). 13 | 14 | There are probably features missing. Please open an issue! 15 | 16 | Please [let me know](https://twitter.com/dustingetz) if you use this, if this project is valued I will invest more time in it. Seriously, please, if you're reading this and want to use it, tweet me. 17 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | python: 3 | version: 2.7.3 4 | node: 5 | version: 0.12.0 6 | 7 | dependencies: 8 | post: 9 | - webpack 10 | 11 | general: 12 | artifacts: 13 | - dist 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@dustingetz/react-json-editor", 3 | "version": "0.3.0", 4 | "description": "react json editor", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/prognostic-llc/react-json-editor" 8 | }, 9 | "license": "MIT", 10 | "scripts": { 11 | "build": "webpack", 12 | "test": "echo \"Error: no test specified\"" 13 | }, 14 | "main": "dist/react-json-editor.js", 15 | "jsnext:main": "src/react-json-editor.js", 16 | "devDependencies": { 17 | "babel-core": "^5.8.22", 18 | "babel-loader": "^5.3.2", 19 | "css-loader": "^0.19.0", 20 | "webpack": "^1.11.0", 21 | "style-loader": "^0.12.4", 22 | "webpack-dev-server": "^1.10.1" 23 | }, 24 | "dependencies": { 25 | "lodash": "^3.10.1", 26 | "react": "^0.14.6", 27 | "react-cursor": "2.0.0-alpha.11", 28 | "react-treeview": "^0.4.6" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dustingetz/react-json-editor/5023742c967517b28178f120fa72dab73fffe7a0/screenshot.png -------------------------------------------------------------------------------- /src/JsonLeafEditor.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React from 'react'; 3 | import {Cursor} from 'react-cursor'; 4 | import TreeView from 'react-treeview'; 5 | import "./react-json-editor.css"; 6 | 7 | class JsonLeafEditor extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | // Stringified value includes "type" - e.g. strings are quoted. 11 | this.state = { 12 | jsValue: JSON.stringify(this.props.cursor.value(), undefined, 2), 13 | editing: false 14 | }; 15 | 16 | this.onChange = (e) => this.setState({ jsValue: e.target.value }); 17 | this.edit = () => this.setState({ editing: true }); 18 | this.commit = () => { 19 | this.props.cursor.set(JSON.parse(this.state.jsValue)); 20 | this.setState({ editing: false }); 21 | }; 22 | } 23 | 24 | componentWillReceiveProps(nextProps) { 25 | this.setState({ 26 | jsValue: JSON.stringify(nextProps.cursor.value(), undefined, 2) 27 | }) 28 | } 29 | 30 | render() { 31 | var classes = _.compact([ 32 | 'JsonLeafEditor', 33 | this.isDirty() ? 'dirty' : null, 34 | !this.isValid() ? 'invalid' : null 35 | ]); 36 | 37 | var leaf = (this.state.editing 38 | ? [(), 39 | ()] 40 | : [({this.state.jsValue})]); 41 | 42 | return {leaf}; 43 | } 44 | 45 | isValid() { 46 | try { 47 | JSON.parse(this.state.jsValue); 48 | return true; 49 | } 50 | catch (e) { 51 | return false; 52 | } 53 | } 54 | 55 | isDirty() { 56 | if (!this.isValid()) return false; // we're invalid, not dirty 57 | var unmodified = _.isEqual(JSON.parse(this.state.jsValue), this.props.cursor.value()); 58 | return !unmodified; 59 | } 60 | } 61 | 62 | JsonLeafEditor.defaultProps = { 63 | cursor: undefined 64 | }; 65 | 66 | export default JsonLeafEditor; 67 | -------------------------------------------------------------------------------- /src/react-json-editor.css: -------------------------------------------------------------------------------- 1 | .JsonLeafEditor.dirty { 2 | background-color: #99ccff; 3 | } 4 | 5 | .JsonLeafEditor.invalid { 6 | background-color: #CC9999; 7 | } 8 | 9 | .JsonLeafEditor > .editButton { 10 | cursor: pointer; 11 | text-decoration: underline; 12 | } 13 | -------------------------------------------------------------------------------- /src/react-json-editor.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import React from 'react'; 3 | import {Cursor} from 'react-cursor'; 4 | import TreeView from 'react-treeview'; 5 | import JsonLeafEditor from './JsonLeafEditor'; 6 | import "react-treeview/react-treeview.css"; 7 | 8 | class JsonEditor extends React.Component { 9 | render() { 10 | var cur = this.props.targetCursor; 11 | var val = cur.value(); 12 | 13 | console.assert(_.isArray(val) || _.isObject(val), 'todo'); 14 | 15 | const el = _.map(val, (v, k) => { 16 | if (_.isArray(v) || _.isObject(v)) { 17 | return ( 18 | {k}} defaultCollapsed={this.props.initialExpandedLevels <= 0}> 19 | 20 | 21 | ); 22 | } 23 | else { 24 | return
{k}:
; 25 | } 26 | }); 27 | 28 | return
{el}
; 29 | } 30 | } 31 | 32 | JsonEditor.defaultProps = { 33 | initialExpandedLevels: 0, 34 | targetCursor: undefined // the app state that we're targeting 35 | }; 36 | 37 | export default JsonEditor; -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | devtool: 'inline-source-map', 6 | entry: './src/react-json-editor', 7 | 8 | output: { 9 | path: path.resolve('./dist'), 10 | filename: 'react-json-editor.js', 11 | libraryTarget: 'umd', 12 | library: 'ReactJsonEditor', 13 | publicPath: '/static/' 14 | }, 15 | 16 | resolve: { 17 | extensions: ['', '.js'], 18 | root: [ 19 | path.resolve('./src') 20 | ], 21 | modulesDirectories: ['node_modules'] 22 | }, 23 | 24 | plugins: [ 25 | new webpack.NoErrorsPlugin() 26 | ], 27 | 28 | module: { 29 | loaders: [ 30 | {test: /\.js$/, loaders: ['babel'], include: path.resolve('./src')}, 31 | {test: /\.css$/, loader: 'style!css'} 32 | ] 33 | } 34 | }; 35 | --------------------------------------------------------------------------------