diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/package-lock.json b/package-lock.json index 2c3df91..66c1208 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-json-editor-viewer", - "version": "1.0.7", + "version": "1.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "react-json-editor-viewer", - "version": "1.0.7", + "version": "1.1.1", "license": "MIT", "devDependencies": { "autoprefixer": "7.1.6", @@ -43,7 +43,7 @@ "raf": "3.4.0", "react": "17.0.2", "react-dev-utils": "^4.2.1", - "react-dom": "^16.2.0", + "react-dom": "17.0.2", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "url-loader": "0.6.2", @@ -2256,23 +2256,31 @@ "dev": true }, "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "optional": true, "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/chokidar/node_modules/anymatch": { @@ -11828,15 +11836,17 @@ } }, "node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", "dev": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" } }, "node_modules/react-error-overlay": { @@ -11919,9 +11929,9 @@ } }, "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "optional": true, "dependencies": { @@ -12483,9 +12493,9 @@ "dev": true }, "node_modules/scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, "dependencies": { "loose-envify": "^1.1.0", @@ -15055,7 +15065,8 @@ "node_modules/webpack-dev-server/node_modules/chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "integrity": "sha512-mk8fAWcRUOxY7btlLtitj3A45jOwSAxH4tOFOoEGbVsl6cL6pPMWUy7dwZ/canfj3QEdP6FHSnf/l1c6/WkzVg==", + "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", "dev": true, "dependencies": { "anymatch": "^1.3.0", @@ -18102,20 +18113,20 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "optional": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "dependencies": { "anymatch": { @@ -26073,15 +26084,14 @@ } }, "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" + "scheduler": "^0.20.2" } }, "react-error-overlay": { @@ -26154,9 +26164,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "optional": true, "requires": { @@ -26635,9 +26645,9 @@ "dev": true }, "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "dev": true, "requires": { "loose-envify": "^1.1.0", @@ -28929,7 +28939,7 @@ "chokidar": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "integrity": "sha512-mk8fAWcRUOxY7btlLtitj3A45jOwSAxH4tOFOoEGbVsl6cL6pPMWUy7dwZ/canfj3QEdP6FHSnf/l1c6/WkzVg==", "dev": true, "requires": { "anymatch": "^1.3.0", diff --git a/package.json b/package.json index c98f56d..ddf8cbe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-json-editor-viewer", - "version": "1.0.7", + "version": "1.1.1", "description": "React JSON Editor and JSON Viewer", "main": "build/index.js", "scripts": { @@ -56,7 +56,7 @@ "raf": "3.4.0", "react": "17.0.2", "react-dev-utils": "^4.2.1", - "react-dom": "^16.2.0", + "react-dom": "17.0.2", "style-loader": "0.19.0", "sw-precache-webpack-plugin": "0.11.4", "url-loader": "0.6.2", diff --git a/src/demo/App.js b/src/demo/App.js index 17ab120..4c053fd 100644 --- a/src/demo/App.js +++ b/src/demo/App.js @@ -4,25 +4,66 @@ import { JSONEditor } from "../lib"; // to compile a production version //npm publish to publish -const App = () => ( -
-

Using default styles

- +const App = () => { + const onJsonChange = (key, value, parent, data) => { + console.log(key, value, parent, data); + }; + return ( +
+

Empty object

+ {" "} +

Empty array

+ {" "} +

Empty string

+ {" "} +

A number

+ {" "} +

A boolean

+ {" "} +

Data

+ + {/*

Using customized styles

-
-); + /> */} +
+ ); +}; const styles = { dualView: { diff --git a/src/lib/JSONEditor.js b/src/lib/JSONEditor.js index 7a4f04f..07a9704 100644 --- a/src/lib/JSONEditor.js +++ b/src/lib/JSONEditor.js @@ -19,7 +19,8 @@ import ParentLabel from "./components/editor/ParentLabel"; import Input from "./components/editor/Input"; import { EDIT_KEY } from "./util"; import { jsonEditorDefaultStyles } from "./util"; -import { getKey } from "./util"; +import { getKey, defaultValueByType } from "./util"; +import EmptyElement from "./components/editor/EmptyElement"; export default class JSONEditor extends React.Component { static defaultProps = { @@ -132,6 +133,7 @@ export default class JSONEditor extends React.Component { //special case to avoid showing root elems.push( ); + } else { + for (let key = 0; key < data.length; key++) { + this.recursiveParseData( + key, + parentKeyPath, + data, + elems, + marginLeft + marginLeftStep + ); + } } } else if (isObject(data)) { if (marginLeft > 0) { //special case to avoid showing root elems.push( { - this.recursiveParseData( - key, - parentKeyPath, - data, - elems, - marginLeft + marginLeftStep + const fields = Object.keys(data); + if (fields.length === 0 && marginLeft === 0) { + elems.push( + ); - }); + } else { + fields.forEach((key) => { + this.recursiveParseData( + key, + parentKeyPath, + data, + elems, + marginLeft + marginLeftStep + ); + }); + } } else if (isNumber(data)) { elems.push( { + addElement = (parent, type = "text") => { let newKey = null; if (isArray(parent)) { - parent.push(""); + parent.push(defaultValueByType(type)); newKey = parent.length - 1; } else { newKey = EDIT_KEY; - parent[newKey] = ""; + parent[newKey] = defaultValueByType(type); } this.setState({ data: this.state.data }); if (this.props.onChange) @@ -277,11 +307,35 @@ export default class JSONEditor extends React.Component { this.props.onChange(removeKey, currentValue, parent, this.state.data); }; - saveElement = (parent, saveKey) => { + saveElement = (parent, saveKey, type, newValue) => { let value = parent[EDIT_KEY]; + + // if type exists then it is a new item + if (type === "object") { + value = {}; + } + if (type === "array") { + value = []; + } + if (type === "null") { + value = null; + } + if (type === "number") { + try { + value = parseFloat(newValue); + } catch (error) { + value = 0; + } + } + if (type === "boolean") { + value = newValue === "true"; + } + // else string + parent[saveKey] = value; delete parent[EDIT_KEY]; this.setState(this.state.data); + if (this.props.onChange) this.props.onChange(saveKey, value, parent, this.state.data); }; diff --git a/src/lib/components/editor/AddIcon.js b/src/lib/components/editor/AddIcon.js index 013a10c..9eaeebe 100644 --- a/src/lib/components/editor/AddIcon.js +++ b/src/lib/components/editor/AddIcon.js @@ -1,12 +1,32 @@ import React from "react"; +import PropTypes from "prop-types"; const AddIcon = (props) => { - let { addElement, addTo, hidden, styles } = props; + let { addElement, addTo, hidden, styles, type } = props; return ( -