JSON Tree
Install
npm install zeta-global/json-tree
# or
yarn add zeta-global/json-tree
Example Usage
// Import
import {
JsonTree,
ADD_DELTA_TYPE,
REMOVE_DELTA_TYPE,
UPDATE_DELTA_TYPE,
DATA_TYPES,
INPUT_USAGE_TYPES,
} from 'zeta-global/json-tree'
// Data
const data = {
error: new Error('error'),
text: 'text',
int: 100,
boolean: true,
null: null,
object: {
text: 'text',
int: 100,
boolean: true,
},
array: [
1,
{
string: 'test',
},
],
}
// Component
<JsonTree data={data} />
Props
data
| Key | Description | Type | Required | Default |
|---|
| data | Data to be displayed/edited | Object | Array | True | None |
rootName
| Key | Description | Type | Required | Default |
|---|
| rootName | Name of the root object | string | False | root |
isCollapsed
| Key | Description | Type | Required | Default |
|---|
| isCollapsed | Whether the node is collapsed (for Array/Object/Error) | Function | False | (keyPath, deep) => (deep !== 0) |
Function parameters:
| Key | Description | Type | Example |
|---|
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| data | Data of the current node/value | unknown | { string: 'test' } for data: { object: { string: 'test' } } |
onFullyUpdate
| Key | Description | Type | Required | Default |
|---|
| onFullyUpdate | Callback function called upon each update with the entire new data structure | Function | False | () => {} |
Function parameters:
| Key | Description | Type |
|---|
| data | Updated data | Object | Array (same type as the data prop) |
onDeltaUpdate
| Key | Description | Type | Required | Default |
|---|
| onDeltaUpdate | Callback function called upon each update with only the data that has changed | Function | False | () => {} |
Function parameters:
| Key | Description | Type |
|---|
| data | Delta data | Object |
Delta data structure:
| Key | Description | Type | Example |
|---|
| type | Delta type | string | 'ADD_DELTA_TYPE', 'REMOVE_DELTA_TYPE', or 'UPDATE_DELTA_TYPE' |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| key | Modified/created/removed key name | string | None |
| newValue | New value | unknown | None |
| oldValue | Old value | unknown | None |
readOnly
| Key | Description | Type | Required | Default |
|---|
| readOnly | If a boolean, whether the entire structure should be read-only. If a function, whether the node/value supplied to the function should be read-only (called for all nodes/values). | boolean | Function | False | (keyName, data, keyPath, deep, dataType) => false |
This function must return a boolean.
Function parameters:
| Key | Description | Type | Example |
|---|
| keyName | Key name of the current node/value | string | 'object' for data: { object: { string: 'test' } } |
| data | Data of the current node/value | unknown | { string: 'test' } for data: { object: { string: 'test' } } |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| dataType | Data type of the current node/value | string | 'Object', 'Array', 'Null', 'Undefined', 'Error', 'Number', ... |
getStyle
| Key | Description | Type | Required | Default |
|---|
| getStyle | Callback function which should return the CSS style for each node/value | Function | False | (keyName, data, keyPath, deep, dataType) => {...} |
Function parameters:
| Key | Description | Type | Example |
|---|
| keyName | Key name of the current node/value | string | 'object' for data: { object: { string: 'test' } } |
| data | data of the current node/value | unknown | { string: 'test' } for data: { object: { string: 'test' } } |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| dataType | Data type of the current node/value | string | 'Object', 'Array', 'Null', 'Undefined', 'Error', 'Number', ... |
An example of return:
{
minus: {
color: 'red',
},
plus: {
color: 'green',
},
collapsed: {
color: 'grey',
},
delimiter: {},
ul: {
padding: '0px',
margin: '0 0 0 25px',
listStyle: 'none',
},
name: {
color: '#2287CD',
},
addForm: {},
}
You can see the default style definitions in src/utils/styles.js.
addButtonElement
| Key | Description | Type | Required | Default |
|---|
| addButtonElement | Custom add button element (to confirm adding a new value to an object/array) | JSX.Element | False | <button>+</button> |
The library will add an onClick handler to the element.
cancelButtonElement
| Key | Description | Type | Required | Default |
|---|
| cancelButtonElement | Custom cancel button element (to cancel editing a value) | JSX.Element | False | <button>c</button> |
The library will add an onClick handler to the element.
editButtonElement
| Key | Description | Type | Required | Default |
|---|
| editButtonElement | Custom edit button element (to finish editing a value) | JSX.Element | False | <button>e</button> |
The library will add an onClick handler to the element.
inputElement
| Key | Description | Type | Required | Default |
|---|
| inputElement | Custom text input element (to edit a value) | JSX.Element | Function | False | (usage, keyPath, deep, keyName, data, dataType) => <input /> |
The library will add a placeholder, ref, and defaultValue prop to the
element. This element will be focused when possible.
Function parameters:
| Key | Description | Type | Example |
|---|
| usage | Usage of the generated input | string | All values are listed in INPUT_USAGE_TYPES |
| keyPath | Path to the current node/value | string[] | [] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| key | Key of the current node/value | string | 'object' for data: { object: { string: 'test' } } |
| value | Value of the key | unknown | { string: 'test' } for data: { object: { string: 'test' } } on 'object' node |
| dataType | Data type of the value | string | All values are listed in DATA_TYPES |
textareaElement
| Key | Description | Type | Required | Default |
|---|
| textareaElement | Custom textarea element (to edit a long value, like functions) | JSX.Element | Function | False | (usage, keyPath, deep, keyName, data, dataType) => <textarea /> |
The library will add a ref and defaultValue prop to the element. This
element will be focused when possible.
Function parameters:
| Key | Description | Type | Example |
|---|
| usage | Usage of the generated input | string | All values are listed in INPUT_USAGE_TYPES |
| keyPath | Path to the current node/value | string[] | [] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| key | Key of the current node/value | string | 'object' for data: { object: { string: 'test' } } |
| value | Value of the key | unknown | { string: 'test' } for data: { object: { string: 'test' } } on 'object' node |
| dataType | Data type of the value | string | All values are listed in DATA_TYPES |
minusMenuElement
| Key | Description | Type | Required | Default |
|---|
| minusMenuElement | Custom minus menu element (to remove a value from an object/array) | JSX.Element | False | <span> - </span> |
The library will add an onClick, className, and style prop to the element.
plusMenuElement
| Key | Description | Type | Required | Default |
|---|
| plusMenuElement | Custom plus menu element (to begin adding a new value to an object/array) | JSX.Element | False | <span> + </span> |
The library will add an onClick, className, and style prop to the element.
beforeRemoveAction
| Key | Description | Type | Required | Default |
|---|
| beforeRemoveAction | Async function called upon the user trying to remove a node/value with the minus menu element | Function | False | (key, keyPath, deep, oldValue) => new Promise(resolve => resolve()) |
This function must return a Promise. If the promise is resolved, the
node/value will be removed. Otherwise, if rejected, nothing will be done.
Function parameters:
| Key | Description | Type | Example |
|---|
| key | Key name of the current node/value | string | 'object' for data: { object: { string: 'test' } } |
| keyPath | Path to the current node/value | string[] | [] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| oldValue | Old value of the key | unknown | { string: 'test' } for data: { object: { string: 'test' } } on 'object' node |
beforeAddAction
| Key | Description | Type | Required | Default |
|---|
| beforeAddAction | Async function called upon the user trying to add a node/value with the add menu element | Function | False | (key, keyPath, deep, newValue) => new Promise(resolve => resolve()) |
This function must return a Promise. If the promise is resolved, the
node/value will be added. Otherwise, if rejected, nothing will be done.
Function parameters:
| Key | Description | Type | Example |
|---|
| key | Key of the current node/value | string | 'string' for data: { object: { string: 'test' } } |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| newValue | New value of the key | unknown | 'test' for data: { object: { string: 'test' } } on 'string' node |
beforeUpdateAction
| Key | Description | Type | Required | Default |
|---|
| beforeUpdateAction | Async function called upon the user trying to edit a node/value | Function | False | (key, keyPath, deep, oldValue, newValue) => new Promise(resolve => resolve()) |
This function must return a Promise. If the promise is resolved, the
node/value will be updated. Otherwise, if rejected, nothing will be done.
Function parameters:
| Key | Description | Type | Example |
|---|
| key | Key of the current node/value | string | 'string' for data: { object: { string: 'test' } } |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| oldValue | Old value of the key | unknown | 'test' for data: { object: { string: 'test' } } on 'string' node |
| newValue | New value of the key | unknown | 'update' for data: { object: { string: 'update' } } on 'string' node |
logger
| Key | Description | Type | Required | Default |
|---|
| logger | Object used to log errors caught from promises (using only the 'error' key) | Object | False | { error: () => {} } |
onSubmitValueParser
| Key | Description | Type | Required | Default |
|---|
| onSubmitValueParser | Function called upon every value addition/update to parse raw string data from inputElements or textareaElements into the correct object types | Function | False | (isEditMode, keyPath, deep, key, rawValue) => nativeParser(rawValue) |
Function parameters:
| Key | Description | Type | Example |
|---|
| isEditMode | Whether the value is being edited on an existing node/value, otherwise it's being newly added | boolean | True |
| keyPath | Path to the current node/value | string[] | ['object'] for data: { object: { string: 'test' } } |
| deep | Depth of the current node | number | 1 for data: { object: { string: 'test' } } on 'object' node |
| key | Key of the current node/value | string | 'string' for data: { object: { string: 'test' } } |
| rawValue | Raw string value from the inputElement or textareaElement | string | 'test' for data: { object: { string: 'test' } } |
allowFunctionEvaluation
| Key | Description | Type | Required | Default |
|---|
| allowFunctionEvaluation | Allow strings that appear to be Javascript function definitions to be evaluated as Javascript functions | boolean | False | True |
Development
npm commands
Build
Build the library to dist/ using parcel.
npm run build
Publish
Publishes the library to npm. This runs a parcel build.
npm publish