diff --git a/README.md b/README.md index 736ce37..ac89357 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,56 @@ const theme = { ![](http://cl.ly/image/330o2L1J3V0h/screenshot%202015-08-26%20at%2010.48.24%20AM.png) +### Customization + +#### Customize CSS + +You can pass the following properties to customize styling (all optional): + +```js + ({})} + getItemStringStyle={(type, expanded) => ({})} + getListStyle={(type, expanded) => ({})} + getLabelStyle={(type, expanded) => ({})} + getValueStyle={(type, expanded) => ({})} /> +``` + +Here `type` is a string representing type of data, `expanded` is a current state for expandable items. Each function returns a style object, which extends corresponding default style. + +For example, if you pass the following function: + +```js +const getStyle = (type, expanded) => + (expanded ? { textTransform: 'uppercase' } : + { textTransform: 'lowercase' }); +``` + +Then expanded nodes will all be in uppercase: + +![](http://cl.ly/image/460Y0P3C453Q/screenshot%202015-10-07%20at%203.38.33%20PM.png) + +#### Customize Labels for Arrays, Objects, and Iterables + +You can pass `getItemString` to customize the way arrays, objects, and iterable nodes are displayed (optional). + +By default, it'll be: + +```js + {itemType} {itemString}} +``` + +But if you pass the following: + +```js +const getItemString = (type, data, itemType, itemString) + => ( // {type}); +``` + +Then the preview of child elements now look like this: + +![](http://cl.ly/image/1J1a0b0T0K3c/screenshot%202015-10-07%20at%203.44.31%20PM.png) + ### Credits - All credits to [Dave Vedder](http://www.eskimospy.com/) ([veddermatic@gmail.com](mailto:veddermatic@gmail.com)), who wrote the original code as [JSONViewer](https://bitbucket.org/davevedder/react-json-viewer/). diff --git a/examples/src/App.js b/examples/src/App.js index c380962..1e00898 100755 --- a/examples/src/App.js +++ b/examples/src/App.js @@ -36,13 +36,33 @@ export default class App extends Component { base0F: '#cc6633' }; + const getStyle = (type, expanded) => {}; + const getItemString = (type, data, itemType, itemString) => ( // {type}); + return (

+

Dark Theme

+
+

Style Customization

+
    +
  • Text changes between uppercase/lowercase based on the expanded state.
  • +
  • The labels of objects, arrays, and iterables are customized as "// type".
  • +
  • See code for details.
  • +
+
+ +
); } diff --git a/src/JSONArrayNode.js b/src/JSONArrayNode.js index 01012c0..a3a305f 100644 --- a/src/JSONArrayNode.js +++ b/src/JSONArrayNode.js @@ -61,7 +61,7 @@ export default class JSONArrayNode extends React.Component { if (typeof this.props.previousData !== 'undefined' && this.props.previousData !== null) { prevData = this.props.previousData[idx]; } - const node = grabNode(idx, element, prevData, this.props.theme); + const node = grabNode(idx, element, prevData, this.props.theme, this.props.styles, this.props.getItemString); if (node !== false) { childNodes.push(node); } @@ -74,11 +74,11 @@ export default class JSONArrayNode extends React.Component { // Returns the "n Items" string for this node, generating and // caching it if it hasn't been created yet. - getItemString() { + getItemString(itemType) { if (!this.itemString) { this.itemString = this.props.data.length + ' item' + (this.props.data.length !== 1 ? 's' : ''); } - return this.itemString; + return this.props.getItemString('Array', this.props.data, itemType, this.itemString); } render() { @@ -105,18 +105,24 @@ export default class JSONArrayNode extends React.Component { } return (
  • - + - - [] - {this.getItemString()} + + {this.getItemString([])} -
      +
        {childNodes}
      diff --git a/src/JSONArrow.js b/src/JSONArrow.js index 4e94a8a..ac7417a 100644 --- a/src/JSONArrow.js +++ b/src/JSONArrow.js @@ -37,6 +37,10 @@ export default class JSONArrow extends React.Component { ...styles.open }; } + style = { + ...style, + ...this.props.style + }; return
      ; } } diff --git a/src/JSONBooleanNode.js b/src/JSONBooleanNode.js index 495d1d8..5a828f9 100644 --- a/src/JSONBooleanNode.js +++ b/src/JSONBooleanNode.js @@ -29,11 +29,15 @@ export default class JSONBooleanNode extends React.Component {
    1. - {truthString} + {truthString}
    2. ); } diff --git a/src/JSONDateNode.js b/src/JSONDateNode.js index 9fe8c47..0020952 100644 --- a/src/JSONDateNode.js +++ b/src/JSONDateNode.js @@ -28,11 +28,15 @@ export default class JSONDateNode extends React.Component {
    3. - {this.props.value.toISOString()} + {this.props.value.toISOString()}
    4. ); } diff --git a/src/JSONIterableNode.js b/src/JSONIterableNode.js index 34038b3..20f301e 100644 --- a/src/JSONIterableNode.js +++ b/src/JSONIterableNode.js @@ -70,7 +70,7 @@ export default class JSONIterableNode extends React.Component { if (typeof this.props.previousData !== 'undefined' && this.props.previousData !== null) { prevData = this.props.previousData[key]; } - const node = grabNode(key, value, prevData, this.props.theme); + const node = grabNode(key, value, prevData, this.props.theme, this.props.styles, this.props.getItemString); if (node !== false) { childNodes.push(node); } @@ -83,7 +83,7 @@ export default class JSONIterableNode extends React.Component { // Returns the "n entries" string for this node, generating and // caching it if it hasn't been created yet. - getItemString() { + getItemString(itemType) { if (!this.itemString) { const { data } = this.props; let count = 0; @@ -96,7 +96,7 @@ export default class JSONIterableNode extends React.Component { } this.itemString = count + ' entr' + (count !== 1 ? 'ies' : 'y'); } - return this.itemString; + return this.props.getItemString('Iterable', this.props.data, itemType, this.itemString); } render() { @@ -123,18 +123,24 @@ export default class JSONIterableNode extends React.Component { } return (
    5. - + - - () - {this.getItemString()} + + {this.getItemString(())} -
        +
          {childNodes}
        diff --git a/src/JSONNullNode.js b/src/JSONNullNode.js index 202abff..1bbcc7c 100644 --- a/src/JSONNullNode.js +++ b/src/JSONNullNode.js @@ -28,11 +28,15 @@ export default class JSONNullNode extends React.Component {
      1. - null + null
      2. ); } diff --git a/src/JSONNumberNode.js b/src/JSONNumberNode.js index b254063..1b77ee7 100644 --- a/src/JSONNumberNode.js +++ b/src/JSONNumberNode.js @@ -28,11 +28,15 @@ export default class JSONNumberNode extends React.Component {
      3. - {this.props.value} + {this.props.value}
      4. ); } diff --git a/src/JSONObjectNode.js b/src/JSONObjectNode.js index 1b79659..8636f49 100644 --- a/src/JSONObjectNode.js +++ b/src/JSONObjectNode.js @@ -61,7 +61,7 @@ export default class JSONObjectNode extends React.Component { if (typeof this.props.previousData !== 'undefined' && this.props.previousData !== null) { prevData = this.props.previousData[k]; } - const node = grabNode(k, obj[k], prevData, this.props.theme); + const node = grabNode(k, obj[k], prevData, this.props.theme, this.props.styles, this.props.getItemString); if (node !== false) { childNodes.push(node); } @@ -75,12 +75,12 @@ export default class JSONObjectNode extends React.Component { // Returns the "n Items" string for this node, generating and // caching it if it hasn't been created yet. - getItemString() { + getItemString(itemType) { if (!this.itemString) { const len = Object.keys(this.props.data).length; this.itemString = len + ' key' + (len !== 1 ? 's' : ''); } - return this.itemString; + return this.props.getItemString('Object', this.props.data, itemType, this.itemString); } render() { @@ -106,18 +106,24 @@ export default class JSONObjectNode extends React.Component { } return (
      5. - + - - {} - {this.getItemString()} + + {this.getItemString({})} -
          +
            {this.getChildNodes()}
          diff --git a/src/JSONStringNode.js b/src/JSONStringNode.js index 148345a..a6ba50e 100644 --- a/src/JSONStringNode.js +++ b/src/JSONStringNode.js @@ -28,11 +28,15 @@ export default class JSONStringNode extends React.Component {
        • - "{this.props.value}" + "{this.props.value}"
        • ); } diff --git a/src/grab-node.js b/src/grab-node.js index d7af3fc..23711df 100644 --- a/src/grab-node.js +++ b/src/grab-node.js @@ -9,24 +9,24 @@ import JSONBooleanNode from './JSONBooleanNode'; import JSONNullNode from './JSONNullNode'; import JSONDateNode from './JSONDateNode'; -export default function(key, value, prevValue, theme, initialExpanded = false) { +export default function(key, value, prevValue, theme, styles, getItemString, initialExpanded = false) { const nodeType = objType(value); if (nodeType === 'Object') { - return ; + return ; } else if (nodeType === 'Array') { - return ; + return ; } else if (nodeType === 'Iterable') { - return ; + return ; } else if (nodeType === 'String') { - return ; + return ; } else if (nodeType === 'Number') { - return ; + return ; } else if (nodeType === 'Boolean') { - return ; + return ; } else if (nodeType === 'Date') { - return ; + return ; } else if (nodeType === 'Null') { - return ; + return ; } return false; } diff --git a/src/index.js b/src/index.js index 378a36f..663af2a 100644 --- a/src/index.js +++ b/src/index.js @@ -22,6 +22,8 @@ const styles = { } }; +const getEmptyStyle = () => ({}); + export default class JSONTree extends React.Component { static propTypes = { data: React.PropTypes.oneOfType([ @@ -31,7 +33,13 @@ export default class JSONTree extends React.Component { }; static defaultProps = { - theme: solarized + theme: solarized, + getArrowStyle: getEmptyStyle, + getListStyle: getEmptyStyle, + getItemStringStyle: getEmptyStyle, + getLabelStyle: getEmptyStyle, + getValueStyle: getEmptyStyle, + getItemString: (type, data, itemType, itemString) => {itemType} {itemString} }; constructor(props) { @@ -40,7 +48,14 @@ export default class JSONTree extends React.Component { render() { const keyName = this.props.keyName || 'root'; - const rootNode = grabNode(keyName, this.props.data, this.props.previousData, this.props.theme, true); + const getStyles = { + getArrowStyle: this.props.getArrowStyle, + getListStyle: this.props.getListStyle, + getItemStringStyle: this.props.getItemStringStyle, + getLabelStyle: this.props.getLabelStyle, + getValueStyle: this.props.getValueStyle + }; + const rootNode = grabNode(keyName, this.props.data, this.props.previousData, this.props.theme, getStyles, this.props.getItemString, true); return (