Skip to content
This repository was archived by the owner on May 14, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
<JSONTree getArrowStyle={(type, expanded) => ({})}
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
<JSONTree getArrowStyle={(type, data, itemType, itemString)
=> <span>{itemType} {itemString}</span>}
```

But if you pass the following:

```js
const getItemString = (type, data, itemType, itemString)
=> (<span> // {type}</span>);
```

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/).
Expand Down
20 changes: 20 additions & 0 deletions examples/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,33 @@ export default class App extends Component {
base0F: '#cc6633'
};

const getStyle = (type, expanded) => {};
const getItemString = (type, data, itemType, itemString) => (<span> // {type}</span>);

return (
<div>
<JSONTree data={ data } />
<br />
<h3>Dark Theme</h3>
<div style={{ backgroundColor: theme.base00 }}>
<JSONTree data={ data } theme={ theme } />
</div>
<br />
<h3>Style Customization</h3>
<ul>
<li>Text changes between uppercase/lowercase based on the expanded state.</li>
<li>The labels of objects, arrays, and iterables are customized as "// type".</li>
<li>See code for details.</li>
</ul>
<div>
<JSONTree data={ data } theme={ theme }
getArrowStyle={ getStyle }
getItemStringStyle={ getStyle }
getListStyle={ getStyle }
getLabelStyle={ getStyle }
getValueStyle={ getStyle }
getItemString={ getItemString }/>
</div>
</div>
);
}
Expand Down
24 changes: 15 additions & 9 deletions src/JSONArrayNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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() {
Expand All @@ -105,18 +105,24 @@ export default class JSONArrayNode extends React.Component {
}
return (
<li style={containerStyle}>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick}/>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick} style={this.props.styles.getArrowStyle(this.state.expanded)}/>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Array', this.state.expanded)
}} onClick={::this.handleClick}>
{this.props.keyName}:
</label>
<span style={spanStyle} onClick={::this.handleClick}>
<span style={styles.spanType}>[]</span>
{this.getItemString()}
<span style={{
...spanStyle,
...this.props.styles.getItemStringStyle('Array', this.state.expanded)
}} onClick={::this.handleClick}>
{this.getItemString(<span style={styles.spanType}>[]</span>)}
</span>
<ol style={childListStyle}>
<ol style={{
...childListStyle,
...this.props.styles.getListStyle('Array', this.state.expanded)
}}>
{childNodes}
</ol>
</li>
Expand Down
4 changes: 4 additions & 0 deletions src/JSONArrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ export default class JSONArrow extends React.Component {
...styles.open
};
}
style = {
...style,
...this.props.style
};
return <div style={style} onClick={this.props.onClick}/>;
}
}
8 changes: 6 additions & 2 deletions src/JSONBooleanNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ export default class JSONBooleanNode extends React.Component {
<li style={{ ...styles.base, backgroundColor }} onClick={::this.handleClick}>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Boolean', true)
}}>
{this.props.keyName}:
</label>
<span style={{ color: this.props.theme.base09 }}>{truthString}</span>
<span style={{
color: this.props.theme.base09,
...this.props.styles.getValueStyle('Boolean', true)
}}>{truthString}</span>
</li>
);
}
Expand Down
8 changes: 6 additions & 2 deletions src/JSONDateNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ export default class JSONDateNode extends React.Component {
<li style={{ ...styles.base, backgroundColor }} onClick={::this.handleClick}>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Date', true)
}}>
{this.props.keyName}:
</label>
<span style={{ color: this.props.theme.base0B }}>{this.props.value.toISOString()}</span>
<span style={{
color: this.props.theme.base0B,
...this.props.styles.getValueStyle('Date', true)
}}>{this.props.value.toISOString()}</span>
</li>
);
}
Expand Down
24 changes: 15 additions & 9 deletions src/JSONIterableNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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;
Expand All @@ -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() {
Expand All @@ -123,18 +123,24 @@ export default class JSONIterableNode extends React.Component {
}
return (
<li style={containerStyle}>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick}/>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick} style={this.props.styles.getArrowStyle(this.state.expanded)} />
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Iterable', this.state.expanded)
}} onClick={::this.handleClick}>
{this.props.keyName}:
</label>
<span style={spanStyle} onClick={::this.handleClick}>
<span style={styles.spanType}>()</span>
{this.getItemString()}
<span style={{
...spanStyle,
...this.props.styles.getItemStringStyle('Iterable', this.state.expanded)
}} onClick={::this.handleClick}>
{this.getItemString(<span style={styles.spanType}>()</span>)}
</span>
<ol style={childListStyle}>
<ol style={{
...childListStyle,
...this.props.styles.getListStyle('Iterable', this.state.expanded)
}}>
{childNodes}
</ol>
</li>
Expand Down
8 changes: 6 additions & 2 deletions src/JSONNullNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ export default class JSONNullNode extends React.Component {
<li style={{ ...styles.base, backgroundColor }} onClick={::this.handleClick}>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Null', true)
}}>
{this.props.keyName}:
</label>
<span style={{ color: this.props.theme.base08 }}>null</span>
<span style={{
color: this.props.theme.base08,
...this.props.styles.getValueStyle('Null', true)
}}>null</span>
</li>
);
}
Expand Down
8 changes: 6 additions & 2 deletions src/JSONNumberNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ export default class JSONNumberNode extends React.Component {
<li style={{ ...styles.base, backgroundColor }} onClick={::this.handleClick}>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Number', true)
}}>
{this.props.keyName}:
</label>
<span style={{ color: this.props.theme.base09 }}>{this.props.value}</span>
<span style={{
color: this.props.theme.base09,
...this.props.styles.getValueStyle('Number', true)
}}>{this.props.value}</span>
</li>
);
}
Expand Down
24 changes: 15 additions & 9 deletions src/JSONObjectNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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() {
Expand All @@ -106,18 +106,24 @@ export default class JSONObjectNode extends React.Component {
}
return (
<li style={containerStyle}>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick}/>
<JSONArrow theme={this.props.theme} open={this.state.expanded} onClick={::this.handleClick} style={this.props.styles.getArrowStyle(this.state.expanded)} />
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('Object', this.state.expanded)
}} onClick={::this.handleClick}>
{this.props.keyName}:
</label>
<span style={spanStyle} onClick={::this.handleClick}>
<span style={styles.spanType}>&#123;&#125;</span>
{this.getItemString()}
<span style={{
...spanStyle,
...this.props.styles.getItemStringStyle('Object', this.state.expanded)
}} onClick={::this.handleClick}>
{this.getItemString(<span style={styles.spanType}>&#123;&#125;</span>)}
</span>
<ul style={childListStyle}>
<ul style={{
...childListStyle,
...this.props.styles.getListStyle('Object', this.state.expanded)
}}>
{this.getChildNodes()}
</ul>
</li>
Expand Down
8 changes: 6 additions & 2 deletions src/JSONStringNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,15 @@ export default class JSONStringNode extends React.Component {
<li style={{ ...styles.base, backgroundColor }} onClick={::this.handleClick}>
<label style={{
...styles.label,
color: this.props.theme.base0D
color: this.props.theme.base0D,
...this.props.styles.getLabelStyle('String', true)
}}>
{this.props.keyName}:
</label>
<span style={{ color: this.props.theme.base0B }}>"{this.props.value}"</span>
<span style={{
color: this.props.theme.base0B,
...this.props.styles.getValueStyle('String', true)
}}>"{this.props.value}"</span>
</li>
);
}
Expand Down
18 changes: 9 additions & 9 deletions src/grab-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <JSONObjectNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} />;
return <JSONObjectNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} styles={styles} getItemString={getItemString} />;
} else if (nodeType === 'Array') {
return <JSONArrayNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} />;
return <JSONArrayNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} styles={styles} getItemString={getItemString} />;
} else if (nodeType === 'Iterable') {
return <JSONIterableNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} />;
return <JSONIterableNode data={value} previousData={prevValue} theme={theme} initialExpanded={initialExpanded} keyName={key} key={key} styles={styles} getItemString={getItemString} />;
} else if (nodeType === 'String') {
return <JSONStringNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
return <JSONStringNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} styles={styles} />;
} else if (nodeType === 'Number') {
return <JSONNumberNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
return <JSONNumberNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} styles={styles} />;
} else if (nodeType === 'Boolean') {
return <JSONBooleanNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
return <JSONBooleanNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} styles={styles} />;
} else if (nodeType === 'Date') {
return <JSONDateNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
return <JSONDateNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} styles={styles} />;
} else if (nodeType === 'Null') {
return <JSONNullNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} />;
return <JSONNullNode keyName={key} previousValue={prevValue} theme={theme} value={value} key={key} styles={styles} />;
}
return false;
}
Loading