@redheadphone/react-json-grid
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -1,2 +0,2 @@ | ||
import React from 'react'; | ||
import React, { useState, useEffect, useRef, Fragment } from 'react'; | ||
@@ -30,5 +30,68 @@ function styleInject(css, ref) { | ||
var css = ""; | ||
var css = ".styles_json-grid-container__1do2c {\r\n margin: 0;\r\n font-family: \"Lato\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\r\n \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\",\r\n \"Segoe UI Symbol\";\r\n font-size: 0.9375rem;\r\n font-weight: 400;\r\n line-height: 1.5;\r\n color: #fff;\r\n text-align: left;\r\n background-color: #222;\r\n}\r\n\r\n.styles_json-grid-table__3KxDK {\r\n border-collapse: separate !important;\r\n border-spacing: 0;\r\n border: solid #b5b5b5 1px;\r\n -moz-border-radius: 3px;\r\n -webkit-border-radius: 3px;\r\n border-radius: 3px;\r\n -webkit-box-shadow: 0 1px 1px #ccc;\r\n -moz-box-shadow: 0 1px 1px #ccc;\r\n box-shadow: 0 1px 1px #ccc;\r\n}\r\n.styles_highlight__1bpMD {\r\n background-color: #3b3b3b;\r\n font-weight: bold;\r\n}\r\n.styles_obj__dFKgt {\r\n font-family: \"Segoe UI\", Tahoma, Geneva, Verdana, sans-serif;\r\n border: 1px solid #474747;\r\n padding: 3px 10px 3px 10px;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n}\r\n.styles_obj__dFKgt .styles_name__13yyl {\r\n color: white;\r\n}\r\n.styles_obj__dFKgt .styles_index__2HDDg {\r\n color: #949494;\r\n}\r\n.styles_obj__dFKgt .styles_string__rq61g {\r\n color: #a5c261;\r\n}\r\n.styles_obj__dFKgt .styles_number__2AHSW {\r\n color: #6c99bb;\r\n}\r\n.styles_obj__dFKgt .styles_boolean__1BANa {\r\n color: #6c99bb;\r\n}\r\n.styles_obj__dFKgt .styles_object__3BV4k {\r\n color: white;\r\n}\r\n.styles_order__3lWKM {\r\n background-color: #444;\r\n color: White;\r\n}\r\n.styles_key__2l8qn {\r\n vertical-align: top;\r\n}\r\n.styles_title__1cca0 {\r\n font-weight: bold;\r\n}\r\n.styles_plusminus__3UVy2 {\r\n font-size: 15px;\r\n cursor: pointer;\r\n margin-right: 2px;\r\n}\r\n.styles_search-highlight__PcqVt {\r\n background-color: #565a36;\r\n padding: 1px 5px 1px 5px;\r\n border-radius: 2px;\r\n}\r\n.styles_glyphicon__3VdjK {\r\n position: relative;\r\n top: 3px;\r\n display: inline-block;\r\n font-family: \"Glyphicons Halflings\";\r\n font-style: normal;\r\n font-weight: 400;\r\n line-height: 1;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n}\r\n"; | ||
var styles = { "json-grid-container": "styles_json-grid-container__1do2c", "json-grid-table": "styles_json-grid-table__3KxDK", "highlight": "styles_highlight__1bpMD", "obj": "styles_obj__dFKgt", "name": "styles_name__13yyl", "index": "styles_index__2HDDg", "string": "styles_string__rq61g", "number": "styles_number__2AHSW", "boolean": "styles_boolean__1BANa", "object": "styles_object__3BV4k", "order": "styles_order__3lWKM", "key": "styles_key__2l8qn", "title": "styles_title__1cca0", "plusminus": "styles_plusminus__3UVy2", "search-highlight": "styles_search-highlight__PcqVt", "glyphicon": "styles_glyphicon__3VdjK" }; | ||
styleInject(css); | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
var classnames = createCommonjsModule(function (module) { | ||
/*! | ||
Copyright (c) 2018 Jed Watson. | ||
Licensed under the MIT License (MIT), see | ||
http://jedwatson.github.io/classnames | ||
*/ | ||
/* global define */ | ||
(function () { | ||
var hasOwn = {}.hasOwnProperty; | ||
function classNames() { | ||
var classes = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var arg = arguments[i]; | ||
if (!arg) continue; | ||
var argType = typeof arg; | ||
if (argType === 'string' || argType === 'number') { | ||
classes.push(arg); | ||
} else if (Array.isArray(arg)) { | ||
if (arg.length) { | ||
var inner = classNames.apply(null, arg); | ||
if (inner) { | ||
classes.push(inner); | ||
} | ||
} | ||
} else if (argType === 'object') { | ||
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) { | ||
classes.push(arg.toString()); | ||
continue; | ||
} | ||
for (var key in arg) { | ||
if (hasOwn.call(arg, key) && arg[key]) { | ||
classes.push(key); | ||
} | ||
} | ||
} | ||
} | ||
return classes.join(' '); | ||
} | ||
if (module.exports) { | ||
classNames.default = classNames; | ||
module.exports = classNames; | ||
} else { | ||
window.classNames = classNames; | ||
} | ||
}()); | ||
}); | ||
var menuIcon = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%221em%22%20viewBox%3D%220%200%20448%20512%22%3E%3Cstyle%3Esvg%7Bfill%3A%23ffffff%7D%3C%2Fstyle%3E%3Cpath%20%20%20%20d%3D%22M0%2096C0%2078.3%2014.3%2064%2032%2064H416c17.7%200%2032%2014.3%2032%2032s-14.3%2032-32%2032H32C14.3%20128%200%20113.7%200%2096zM0%20256c0-17.7%2014.3-32%2032-32H416c17.7%200%2032%2014.3%2032%2032s-14.3%2032-32%2032H32c-17.7%200-32-14.3-32-32zM448%20416c0%2017.7-14.3%2032-32%2032H32c-17.7%200-32-14.3-32-32s14.3-32%2032-32H416c17.7%200%2032%2014.3%2032%2032z%22%20%20%2F%3E%3C%2Fsvg%3E"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
@@ -40,44 +103,283 @@ return typeof obj; | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var JSONGrid = function JSONGrid(props) { | ||
var data = props.data, | ||
wrapperClassName = props.wrapperClassName, | ||
tableClassName = props.tableClassName; | ||
var data = props.data; | ||
var _useState = useState(null), | ||
_useState2 = slicedToArray(_useState, 2), | ||
highlightedElement = _useState2[0], | ||
setHighlightedElement = _useState2[1]; | ||
var wrapperRef = useRef(null); | ||
useEffect(function () { | ||
function handleClickOutside(event) { | ||
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) { | ||
if (highlightedElement != null) highlightedElement.classList.remove(styles.highlight); | ||
setHighlightedElement(null); | ||
} | ||
} | ||
document.addEventListener("mousedown", handleClickOutside); | ||
return function () { | ||
return document.removeEventListener("mousedown", handleClickOutside); | ||
}; | ||
}, [wrapperRef, highlightedElement]); | ||
if (data == null) throw new Error("JSONGrid: data prop cannot be null or undefined"); | ||
return React.createElement( | ||
'div', | ||
{ className: wrapperClassName }, | ||
React.createElement( | ||
'table', | ||
{ className: tableClassName }, | ||
"div", | ||
{ className: styles["json-grid-container"], ref: wrapperRef }, | ||
React.createElement(NestedJSONGrid, { | ||
level: 0, | ||
data: data, | ||
highlightedElement: highlightedElement, | ||
setHighlightedElement: setHighlightedElement | ||
}) | ||
); | ||
}; | ||
var NestedJSONGrid = function NestedJSONGrid(props) { | ||
var level = props.level, | ||
data = props.data, | ||
dataKey = props.dataKey, | ||
highlightedElement = props.highlightedElement, | ||
setHighlightedElement = props.setHighlightedElement; | ||
var highlight = function highlight(e) { | ||
if (e.target !== e.currentTarget && e.target.hasAttribute("clickable") || e.target.parentElement !== e.currentTarget && e.target.parentElement.hasAttribute("clickable")) return; | ||
if (highlightedElement != null) highlightedElement.classList.remove(styles.highlight); | ||
var nextHighlightElement = e.currentTarget; | ||
if (e.currentTarget.hasAttribute("rowhighlight")) nextHighlightElement = e.currentTarget.parentElement;else if (e.currentTarget.hasAttribute("colhighlight")) { | ||
var colIndex = Array.prototype.indexOf.call(e.currentTarget.parentElement.children, e.currentTarget); | ||
nextHighlightElement = e.currentTarget.parentElement.parentElement.previousElementSibling.children[colIndex]; | ||
} | ||
nextHighlightElement.classList.add(styles.highlight); | ||
setHighlightedElement(nextHighlightElement); | ||
}; | ||
var checkAllObjects = function checkAllObjects(data) { | ||
var allObjects = false; | ||
var keys = void 0; | ||
if (Array.isArray(data)) { | ||
allObjects = true; | ||
keys = new Set(); | ||
for (var i = 0; i < data.length; i++) { | ||
if (_typeof(data[i]) !== "object" || Array.isArray(data[i])) { | ||
allObjects = false; | ||
break; | ||
} | ||
Object.keys(data[i]).forEach(function (k) { | ||
return keys.add(k); | ||
}); | ||
} | ||
keys = Array.from(keys); | ||
if (allObjects) { | ||
var _loop = function _loop(_i) { | ||
data[_i] = keys.reduce(function (obj, key) { | ||
obj[key] = data[_i][key] !== undefined ? data[_i][key] : "-"; | ||
return obj; | ||
}, {}); | ||
}; | ||
for (var _i = 0; _i < data.length; _i++) { | ||
_loop(_i); | ||
} | ||
} | ||
} | ||
return { allObjects: allObjects, keys: keys }; | ||
}; | ||
var renderValue = function renderValue(key, value, level) { | ||
if (value && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object") return React.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.value), | ||
onClick: highlight, | ||
clickable: "true", | ||
key: key | ||
}, | ||
React.createElement(NestedJSONGrid, { | ||
level: level + 1, | ||
dataKey: key, | ||
data: value, | ||
highlightedElement: highlightedElement, | ||
setHighlightedElement: setHighlightedElement | ||
}) | ||
); | ||
return React.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.value), | ||
onClick: highlight, | ||
clickable: "true", | ||
key: key | ||
}, | ||
React.createElement("span", { | ||
className: styles[typeof value === "undefined" ? "undefined" : _typeof(value)], | ||
dangerouslySetInnerHTML: { __html: value } | ||
}) | ||
); | ||
}; | ||
var renderTable = function renderTable(data, level) { | ||
var _checkAllObjects = checkAllObjects(data), | ||
allObjects = _checkAllObjects.allObjects, | ||
keys = _checkAllObjects.keys; | ||
return React.createElement( | ||
"table", | ||
{ className: styles["json-grid-table"] }, | ||
allObjects && React.createElement( | ||
Fragment, | ||
null, | ||
React.createElement( | ||
"colgroup", | ||
null, | ||
React.createElement("col", null), | ||
keys.map(function (k) { | ||
return React.createElement("col", { key: k }); | ||
}) | ||
), | ||
React.createElement( | ||
"thead", | ||
null, | ||
React.createElement( | ||
"tr", | ||
null, | ||
React.createElement( | ||
"th", | ||
{ | ||
className: classnames(styles.obj, styles.order), | ||
clickable: "true" | ||
}, | ||
React.createElement("img", { | ||
className: styles.glyphicon, | ||
src: menuIcon, | ||
clickable: "true" | ||
}) | ||
), | ||
keys.map(function (k) { | ||
return React.createElement( | ||
"th", | ||
{ | ||
className: classnames(styles.obj, styles.order, styles.name), | ||
key: k, | ||
onClick: highlight, | ||
clickable: "true", | ||
colhighlight: "true" | ||
}, | ||
k.replace(/_/g, " ") | ||
); | ||
}) | ||
) | ||
) | ||
), | ||
React.createElement( | ||
'tbody', | ||
"tbody", | ||
null, | ||
Object.keys(data).map(function (k) { | ||
return React.createElement( | ||
'tr', | ||
"tr", | ||
{ key: k }, | ||
!Array.isArray(data) && React.createElement( | ||
'td', | ||
null, | ||
k.replace(/_/g, ' ') | ||
Array.isArray(data) ? React.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.order, styles.index), | ||
onClick: highlight, | ||
clickable: "true", | ||
rowhighlight: "true" | ||
}, | ||
parseInt(k) + 1 | ||
) : React.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.key, styles.name), | ||
onClick: highlight, | ||
clickable: "true" | ||
}, | ||
k.replace(/_/g, " ") | ||
), | ||
function () { | ||
if (data[k] && _typeof(data[k]) === 'object') { | ||
return React.createElement( | ||
'td', | ||
null, | ||
React.createElement(JSONGrid, { data: data[k], tableClassName: tableClassName }) | ||
); | ||
} | ||
return React.createElement( | ||
'td', | ||
null, | ||
React.createElement('span', { dangerouslySetInnerHTML: { __html: data[k] } }) | ||
); | ||
}() | ||
allObjects ? Object.entries(data[k]).map(function (_ref) { | ||
var _ref2 = slicedToArray(_ref, 2), | ||
kk = _ref2[0], | ||
v = _ref2[1]; | ||
return renderValue(kk, v, level); | ||
}) : renderValue(k, data[k], level) | ||
); | ||
}) | ||
) | ||
) | ||
); | ||
); | ||
}; | ||
if (level !== 0) { | ||
var _useState3 = useState(false), | ||
_useState4 = slicedToArray(_useState3, 2), | ||
open = _useState4[0], | ||
setOpen = _useState4[1]; | ||
return React.createElement( | ||
"div", | ||
{ className: styles.box }, | ||
React.createElement( | ||
"span", | ||
{ | ||
className: styles.plusminus, | ||
onClick: function onClick() { | ||
return setOpen(!open); | ||
}, | ||
clickable: "true" | ||
}, | ||
open ? "[-]" : "[+]" | ||
), | ||
React.createElement( | ||
"span", | ||
{ className: styles.title }, | ||
dataKey, | ||
"\xA0", | ||
Array.isArray(data) ? "[" + data.length + "]" : "{}" | ||
), | ||
open && renderTable(data, level) | ||
); | ||
} | ||
return renderTable(data, level); | ||
}; | ||
@@ -84,0 +386,0 @@ |
@@ -7,3 +7,4 @@ 'use strict'; | ||
var React = _interopDefault(require('react')); | ||
var React = require('react'); | ||
var React__default = _interopDefault(React); | ||
@@ -37,5 +38,68 @@ function styleInject(css, ref) { | ||
var css = ""; | ||
var css = ".styles_json-grid-container__1do2c {\r\n margin: 0;\r\n font-family: \"Lato\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto,\r\n \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\",\r\n \"Segoe UI Symbol\";\r\n font-size: 0.9375rem;\r\n font-weight: 400;\r\n line-height: 1.5;\r\n color: #fff;\r\n text-align: left;\r\n background-color: #222;\r\n}\r\n\r\n.styles_json-grid-table__3KxDK {\r\n border-collapse: separate !important;\r\n border-spacing: 0;\r\n border: solid #b5b5b5 1px;\r\n -moz-border-radius: 3px;\r\n -webkit-border-radius: 3px;\r\n border-radius: 3px;\r\n -webkit-box-shadow: 0 1px 1px #ccc;\r\n -moz-box-shadow: 0 1px 1px #ccc;\r\n box-shadow: 0 1px 1px #ccc;\r\n}\r\n.styles_highlight__1bpMD {\r\n background-color: #3b3b3b;\r\n font-weight: bold;\r\n}\r\n.styles_obj__dFKgt {\r\n font-family: \"Segoe UI\", Tahoma, Geneva, Verdana, sans-serif;\r\n border: 1px solid #474747;\r\n padding: 3px 10px 3px 10px;\r\n cursor: pointer;\r\n white-space: nowrap;\r\n}\r\n.styles_obj__dFKgt .styles_name__13yyl {\r\n color: white;\r\n}\r\n.styles_obj__dFKgt .styles_index__2HDDg {\r\n color: #949494;\r\n}\r\n.styles_obj__dFKgt .styles_string__rq61g {\r\n color: #a5c261;\r\n}\r\n.styles_obj__dFKgt .styles_number__2AHSW {\r\n color: #6c99bb;\r\n}\r\n.styles_obj__dFKgt .styles_boolean__1BANa {\r\n color: #6c99bb;\r\n}\r\n.styles_obj__dFKgt .styles_object__3BV4k {\r\n color: white;\r\n}\r\n.styles_order__3lWKM {\r\n background-color: #444;\r\n color: White;\r\n}\r\n.styles_key__2l8qn {\r\n vertical-align: top;\r\n}\r\n.styles_title__1cca0 {\r\n font-weight: bold;\r\n}\r\n.styles_plusminus__3UVy2 {\r\n font-size: 15px;\r\n cursor: pointer;\r\n margin-right: 2px;\r\n}\r\n.styles_search-highlight__PcqVt {\r\n background-color: #565a36;\r\n padding: 1px 5px 1px 5px;\r\n border-radius: 2px;\r\n}\r\n.styles_glyphicon__3VdjK {\r\n position: relative;\r\n top: 3px;\r\n display: inline-block;\r\n font-family: \"Glyphicons Halflings\";\r\n font-style: normal;\r\n font-weight: 400;\r\n line-height: 1;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n}\r\n"; | ||
var styles = { "json-grid-container": "styles_json-grid-container__1do2c", "json-grid-table": "styles_json-grid-table__3KxDK", "highlight": "styles_highlight__1bpMD", "obj": "styles_obj__dFKgt", "name": "styles_name__13yyl", "index": "styles_index__2HDDg", "string": "styles_string__rq61g", "number": "styles_number__2AHSW", "boolean": "styles_boolean__1BANa", "object": "styles_object__3BV4k", "order": "styles_order__3lWKM", "key": "styles_key__2l8qn", "title": "styles_title__1cca0", "plusminus": "styles_plusminus__3UVy2", "search-highlight": "styles_search-highlight__PcqVt", "glyphicon": "styles_glyphicon__3VdjK" }; | ||
styleInject(css); | ||
function createCommonjsModule(fn, module) { | ||
return module = { exports: {} }, fn(module, module.exports), module.exports; | ||
} | ||
var classnames = createCommonjsModule(function (module) { | ||
/*! | ||
Copyright (c) 2018 Jed Watson. | ||
Licensed under the MIT License (MIT), see | ||
http://jedwatson.github.io/classnames | ||
*/ | ||
/* global define */ | ||
(function () { | ||
var hasOwn = {}.hasOwnProperty; | ||
function classNames() { | ||
var classes = []; | ||
for (var i = 0; i < arguments.length; i++) { | ||
var arg = arguments[i]; | ||
if (!arg) continue; | ||
var argType = typeof arg; | ||
if (argType === 'string' || argType === 'number') { | ||
classes.push(arg); | ||
} else if (Array.isArray(arg)) { | ||
if (arg.length) { | ||
var inner = classNames.apply(null, arg); | ||
if (inner) { | ||
classes.push(inner); | ||
} | ||
} | ||
} else if (argType === 'object') { | ||
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) { | ||
classes.push(arg.toString()); | ||
continue; | ||
} | ||
for (var key in arg) { | ||
if (hasOwn.call(arg, key) && arg[key]) { | ||
classes.push(key); | ||
} | ||
} | ||
} | ||
} | ||
return classes.join(' '); | ||
} | ||
if (module.exports) { | ||
classNames.default = classNames; | ||
module.exports = classNames; | ||
} else { | ||
window.classNames = classNames; | ||
} | ||
}()); | ||
}); | ||
var menuIcon = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%221em%22%20viewBox%3D%220%200%20448%20512%22%3E%3Cstyle%3Esvg%7Bfill%3A%23ffffff%7D%3C%2Fstyle%3E%3Cpath%20%20%20%20d%3D%22M0%2096C0%2078.3%2014.3%2064%2032%2064H416c17.7%200%2032%2014.3%2032%2032s-14.3%2032-32%2032H32C14.3%20128%200%20113.7%200%2096zM0%20256c0-17.7%2014.3-32%2032-32H416c17.7%200%2032%2014.3%2032%2032s-14.3%2032-32%2032H32c-17.7%200-32-14.3-32-32zM448%20416c0%2017.7-14.3%2032-32%2032H32c-17.7%200-32-14.3-32-32s14.3-32%2032-32H416c17.7%200%2032%2014.3%2032%2032z%22%20%20%2F%3E%3C%2Fsvg%3E"; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { | ||
@@ -47,44 +111,283 @@ return typeof obj; | ||
var slicedToArray = function () { | ||
function sliceIterator(arr, i) { | ||
var _arr = []; | ||
var _n = true; | ||
var _d = false; | ||
var _e = undefined; | ||
try { | ||
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { | ||
_arr.push(_s.value); | ||
if (i && _arr.length === i) break; | ||
} | ||
} catch (err) { | ||
_d = true; | ||
_e = err; | ||
} finally { | ||
try { | ||
if (!_n && _i["return"]) _i["return"](); | ||
} finally { | ||
if (_d) throw _e; | ||
} | ||
} | ||
return _arr; | ||
} | ||
return function (arr, i) { | ||
if (Array.isArray(arr)) { | ||
return arr; | ||
} else if (Symbol.iterator in Object(arr)) { | ||
return sliceIterator(arr, i); | ||
} else { | ||
throw new TypeError("Invalid attempt to destructure non-iterable instance"); | ||
} | ||
}; | ||
}(); | ||
var JSONGrid = function JSONGrid(props) { | ||
var data = props.data, | ||
wrapperClassName = props.wrapperClassName, | ||
tableClassName = props.tableClassName; | ||
var data = props.data; | ||
return React.createElement( | ||
'div', | ||
{ className: wrapperClassName }, | ||
React.createElement( | ||
'table', | ||
{ className: tableClassName }, | ||
React.createElement( | ||
'tbody', | ||
var _useState = React.useState(null), | ||
_useState2 = slicedToArray(_useState, 2), | ||
highlightedElement = _useState2[0], | ||
setHighlightedElement = _useState2[1]; | ||
var wrapperRef = React.useRef(null); | ||
React.useEffect(function () { | ||
function handleClickOutside(event) { | ||
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) { | ||
if (highlightedElement != null) highlightedElement.classList.remove(styles.highlight); | ||
setHighlightedElement(null); | ||
} | ||
} | ||
document.addEventListener("mousedown", handleClickOutside); | ||
return function () { | ||
return document.removeEventListener("mousedown", handleClickOutside); | ||
}; | ||
}, [wrapperRef, highlightedElement]); | ||
if (data == null) throw new Error("JSONGrid: data prop cannot be null or undefined"); | ||
return React__default.createElement( | ||
"div", | ||
{ className: styles["json-grid-container"], ref: wrapperRef }, | ||
React__default.createElement(NestedJSONGrid, { | ||
level: 0, | ||
data: data, | ||
highlightedElement: highlightedElement, | ||
setHighlightedElement: setHighlightedElement | ||
}) | ||
); | ||
}; | ||
var NestedJSONGrid = function NestedJSONGrid(props) { | ||
var level = props.level, | ||
data = props.data, | ||
dataKey = props.dataKey, | ||
highlightedElement = props.highlightedElement, | ||
setHighlightedElement = props.setHighlightedElement; | ||
var highlight = function highlight(e) { | ||
if (e.target !== e.currentTarget && e.target.hasAttribute("clickable") || e.target.parentElement !== e.currentTarget && e.target.parentElement.hasAttribute("clickable")) return; | ||
if (highlightedElement != null) highlightedElement.classList.remove(styles.highlight); | ||
var nextHighlightElement = e.currentTarget; | ||
if (e.currentTarget.hasAttribute("rowhighlight")) nextHighlightElement = e.currentTarget.parentElement;else if (e.currentTarget.hasAttribute("colhighlight")) { | ||
var colIndex = Array.prototype.indexOf.call(e.currentTarget.parentElement.children, e.currentTarget); | ||
nextHighlightElement = e.currentTarget.parentElement.parentElement.previousElementSibling.children[colIndex]; | ||
} | ||
nextHighlightElement.classList.add(styles.highlight); | ||
setHighlightedElement(nextHighlightElement); | ||
}; | ||
var checkAllObjects = function checkAllObjects(data) { | ||
var allObjects = false; | ||
var keys = void 0; | ||
if (Array.isArray(data)) { | ||
allObjects = true; | ||
keys = new Set(); | ||
for (var i = 0; i < data.length; i++) { | ||
if (_typeof(data[i]) !== "object" || Array.isArray(data[i])) { | ||
allObjects = false; | ||
break; | ||
} | ||
Object.keys(data[i]).forEach(function (k) { | ||
return keys.add(k); | ||
}); | ||
} | ||
keys = Array.from(keys); | ||
if (allObjects) { | ||
var _loop = function _loop(_i) { | ||
data[_i] = keys.reduce(function (obj, key) { | ||
obj[key] = data[_i][key] !== undefined ? data[_i][key] : "-"; | ||
return obj; | ||
}, {}); | ||
}; | ||
for (var _i = 0; _i < data.length; _i++) { | ||
_loop(_i); | ||
} | ||
} | ||
} | ||
return { allObjects: allObjects, keys: keys }; | ||
}; | ||
var renderValue = function renderValue(key, value, level) { | ||
if (value && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object") return React__default.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.value), | ||
onClick: highlight, | ||
clickable: "true", | ||
key: key | ||
}, | ||
React__default.createElement(NestedJSONGrid, { | ||
level: level + 1, | ||
dataKey: key, | ||
data: value, | ||
highlightedElement: highlightedElement, | ||
setHighlightedElement: setHighlightedElement | ||
}) | ||
); | ||
return React__default.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.value), | ||
onClick: highlight, | ||
clickable: "true", | ||
key: key | ||
}, | ||
React__default.createElement("span", { | ||
className: styles[typeof value === "undefined" ? "undefined" : _typeof(value)], | ||
dangerouslySetInnerHTML: { __html: value } | ||
}) | ||
); | ||
}; | ||
var renderTable = function renderTable(data, level) { | ||
var _checkAllObjects = checkAllObjects(data), | ||
allObjects = _checkAllObjects.allObjects, | ||
keys = _checkAllObjects.keys; | ||
return React__default.createElement( | ||
"table", | ||
{ className: styles["json-grid-table"] }, | ||
allObjects && React__default.createElement( | ||
React.Fragment, | ||
null, | ||
React__default.createElement( | ||
"colgroup", | ||
null, | ||
React__default.createElement("col", null), | ||
keys.map(function (k) { | ||
return React__default.createElement("col", { key: k }); | ||
}) | ||
), | ||
React__default.createElement( | ||
"thead", | ||
null, | ||
React__default.createElement( | ||
"tr", | ||
null, | ||
React__default.createElement( | ||
"th", | ||
{ | ||
className: classnames(styles.obj, styles.order), | ||
clickable: "true" | ||
}, | ||
React__default.createElement("img", { | ||
className: styles.glyphicon, | ||
src: menuIcon, | ||
clickable: "true" | ||
}) | ||
), | ||
keys.map(function (k) { | ||
return React__default.createElement( | ||
"th", | ||
{ | ||
className: classnames(styles.obj, styles.order, styles.name), | ||
key: k, | ||
onClick: highlight, | ||
clickable: "true", | ||
colhighlight: "true" | ||
}, | ||
k.replace(/_/g, " ") | ||
); | ||
}) | ||
) | ||
) | ||
), | ||
React__default.createElement( | ||
"tbody", | ||
null, | ||
Object.keys(data).map(function (k) { | ||
return React.createElement( | ||
'tr', | ||
return React__default.createElement( | ||
"tr", | ||
{ key: k }, | ||
!Array.isArray(data) && React.createElement( | ||
'td', | ||
null, | ||
k.replace(/_/g, ' ') | ||
Array.isArray(data) ? React__default.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.order, styles.index), | ||
onClick: highlight, | ||
clickable: "true", | ||
rowhighlight: "true" | ||
}, | ||
parseInt(k) + 1 | ||
) : React__default.createElement( | ||
"td", | ||
{ | ||
className: classnames(styles.obj, styles.key, styles.name), | ||
onClick: highlight, | ||
clickable: "true" | ||
}, | ||
k.replace(/_/g, " ") | ||
), | ||
function () { | ||
if (data[k] && _typeof(data[k]) === 'object') { | ||
return React.createElement( | ||
'td', | ||
null, | ||
React.createElement(JSONGrid, { data: data[k], tableClassName: tableClassName }) | ||
); | ||
} | ||
return React.createElement( | ||
'td', | ||
null, | ||
React.createElement('span', { dangerouslySetInnerHTML: { __html: data[k] } }) | ||
); | ||
}() | ||
allObjects ? Object.entries(data[k]).map(function (_ref) { | ||
var _ref2 = slicedToArray(_ref, 2), | ||
kk = _ref2[0], | ||
v = _ref2[1]; | ||
return renderValue(kk, v, level); | ||
}) : renderValue(k, data[k], level) | ||
); | ||
}) | ||
) | ||
) | ||
); | ||
); | ||
}; | ||
if (level !== 0) { | ||
var _useState3 = React.useState(false), | ||
_useState4 = slicedToArray(_useState3, 2), | ||
open = _useState4[0], | ||
setOpen = _useState4[1]; | ||
return React__default.createElement( | ||
"div", | ||
{ className: styles.box }, | ||
React__default.createElement( | ||
"span", | ||
{ | ||
className: styles.plusminus, | ||
onClick: function onClick() { | ||
return setOpen(!open); | ||
}, | ||
clickable: "true" | ||
}, | ||
open ? "[-]" : "[+]" | ||
), | ||
React__default.createElement( | ||
"span", | ||
{ className: styles.title }, | ||
dataKey, | ||
"\xA0", | ||
Array.isArray(data) ? "[" + data.length + "]" : "{}" | ||
), | ||
open && renderTable(data, level) | ||
); | ||
} | ||
return renderTable(data, level); | ||
}; | ||
@@ -91,0 +394,0 @@ |
{ | ||
"name": "@redheadphone/react-json-grid", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "React Component that converts JSON to grid table", | ||
@@ -8,10 +8,27 @@ "author": "Huzaifa Khilawala", | ||
"repository": "https://github.com/RedHeadphone/react-json-grid", | ||
"keywords": [ | ||
"react", | ||
"json", | ||
"grid", | ||
"table", | ||
"layout", | ||
"component", | ||
"render", | ||
"ui" | ||
], | ||
"main": "dist/index.js", | ||
"module": "dist/index.es.js", | ||
"files": [ | ||
"dist" | ||
], | ||
"scripts": { | ||
"test": "cross-env CI=1 react-scripts test --env=jsdom", | ||
"build": "rollup -c", | ||
"start": "rollup -c -w", | ||
"dev": "rollup -c -w", | ||
"prepublish": "npm run build" | ||
}, | ||
"engines": { | ||
"node": ">=8", | ||
"npm": ">=5" | ||
}, | ||
"peerDependencies": { | ||
@@ -48,3 +65,6 @@ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", | ||
"rollup-plugin-url": "^1.4.0" | ||
}, | ||
"dependencies": { | ||
"classnames": "^2.3.2" | ||
} | ||
} |
# react-json-grid | ||
React Component that converts JSON to grid table | ||
<img src="https://raw.githubusercontent.com/RedHeadphone/react-json-grid/master/assets/images/github-banner.png"> | ||
A simple react component to convert any nested JSON object or array into an grid table. | ||
The library react-json-grid provides the React component JSONGrid, which is a user-friendly and versatile tool that enables you to effortlessly transform nested JSON objects or arrays into visually appealing grid tables. Whether you're working on a data visualization project or simply need to present complex JSON data in an organized manner, this component has got you covered. | ||
## Features | ||
- **Ease of Integration**: Seamlessly incorporate the component into your React applications without any hassle. | ||
- **Nested JSON Support**: Handle deeply nested JSON structures with ease, creating structured grid tables. | ||
- **Interactive Interface**: Provide users with an interactive and user-friendly way to explore complex data. | ||
<!-- - **Customizable Styling**: Tailor the appearance of the grid to match your application's design using custom CSS. --> | ||
## Install | ||
Run either one in your React directory: | ||
```bash | ||
@@ -13,7 +21,11 @@ npm install @redheadphone/react-json-grid | ||
```bash | ||
yarn add @redheadphone/react-json-grid | ||
``` | ||
## Usage | ||
Here's an example of how to use the react-json-grid library: | ||
```jsx | ||
import React, { Component } from 'react' | ||
import { JSONGrid } from '@redheadphone/react-json-grid' | ||
@@ -50,6 +62,23 @@ | ||
return ( | ||
<JSONGrid data={data} tableClassName="table table-sm"/> | ||
<JSONGrid data={data}/> | ||
) | ||
} | ||
} | ||
``` | ||
``` | ||
## Props | ||
The JSONGrid component supports the following props: | ||
| Name | Type | Description | Default | | ||
| -------- | -------- | ------------------------------------------------------------------ | ----------- | | ||
| data | object | The JSON object or array to be transformed into a grid table. | undefined | | ||
## Contributing | ||
Please kindly follow [CONTRIBUTING.md](CONTRIBUTING.md) to get started. | ||
## Acknowledgements | ||
- [jsongrid.com](https://jsongrid.com/json-grid): Grid design and styles | ||
- [kevincobain2000/json-to-html-table](https://github.com/kevincobain2000/json-to-html-table): React Component and project structure |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
70875
714
82
3
7
3
1
+ Addedclassnames@^2.3.2
+ Addedclassnames@2.5.1(transitive)