react-editable-json-tree
Version:
React Editable Json Tree
1,047 lines (1,006 loc) • 85.2 kB
JavaScript
import $a6H0q$react, {Component as $a6H0q$Component} from "react";
import $a6H0q$proptypes from "prop-types";
/*
* Author: Alexandre Havrileck (Oxyno-zeta)
* Date: 19/10/16
* Licence: See Readme
*/ /* ************************************* */ /* ******** IMPORTS ******** */ /* ************************************* */ /* ************************************* */ /* ******** PRIVATE FUNCTIONS ******** */ /* ************************************* */ /* ************************************* */ /* ******** PUBLIC FUNCTIONS ******** */ /* ************************************* */ /**
* Get Object type.
* @param obj {*} object to get type
* @returns {*}
*/ function $23a5fe9e979d80ca$export$11cc42aebef2ef3a(obj) {
if (obj !== null && typeof obj === "object" && !Array.isArray(obj) && typeof obj[Symbol.iterator] === "function") return "Iterable";
return Object.prototype.toString.call(obj).slice(8, -1);
}
/**
* Is Component will change ?
* @param oldValue {*} old value
* @param newValue {*} new value
* @returns {boolean} result
*/ function $23a5fe9e979d80ca$export$1172a3730e5c4525(oldValue, newValue) {
const oldType = $23a5fe9e979d80ca$export$11cc42aebef2ef3a(oldValue);
const newType = $23a5fe9e979d80ca$export$11cc42aebef2ef3a(newValue);
return (oldType === "Function" || newType === "Function") && newType !== oldType;
}
/*
* Author: Alexandre Havrileck (Oxyno-zeta)
* Date: 27/02/18
* Licence: See Readme
*/ /* ************************************* */ /* ******** IMPORTS ******** */ /* ************************************* */ /* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ const $9d11e61eaae386e6$var$VALUE = "value";
const $9d11e61eaae386e6$var$KEY = "key";
var /* ************************************* */ /* ******** CLASSES ******** */ /* ************************************* */ /* ************************************* */ /* ******** PRIVATE FUNCTIONS ******** */ /* ************************************* */ /* ************************************* */ /* ******** PUBLIC FUNCTIONS ******** */ /* ************************************* */ /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ $9d11e61eaae386e6$export$2e2bcd8739ae039 = {
KEY: $9d11e61eaae386e6$var$KEY,
VALUE: $9d11e61eaae386e6$var$VALUE
};
const $d55c30c34fe7164f$export$6a361f9cf16d448e = (hotkeys)=>(keyEvent)=>{
if (Object.hasOwn(hotkeys, keyEvent.key)) hotkeys[keyEvent.key]();
};
/* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ // Prop types
const $5bdc19770f09e5f2$var$propTypes = {
name: (0, $a6H0q$proptypes).string.isRequired,
value: (0, $a6H0q$proptypes).any.isRequired,
originalValue: (0, $a6H0q$proptypes).any,
keyPath: (0, $a6H0q$proptypes).array,
deep: (0, $a6H0q$proptypes).number,
handleRemove: (0, $a6H0q$proptypes).func,
handleUpdateValue: (0, $a6H0q$proptypes).func,
readOnly: (0, $a6H0q$proptypes).func.isRequired,
dataType: (0, $a6H0q$proptypes).string,
getStyle: (0, $a6H0q$proptypes).func.isRequired,
editButtonElement: (0, $a6H0q$proptypes).element,
cancelButtonElement: (0, $a6H0q$proptypes).element,
inputElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
minusMenuElement: (0, $a6H0q$proptypes).element,
logger: (0, $a6H0q$proptypes).object.isRequired,
onSubmitValueParser: (0, $a6H0q$proptypes).func.isRequired
};
// Default props
const $5bdc19770f09e5f2$var$defaultProps = {
keyPath: [],
deep: 0,
handleUpdateValue: ()=>Promise.resolve(),
editButtonElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("button", null, "e"),
cancelButtonElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("button", null, "c"),
minusMenuElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, " - ")
};
/* ************************************* */ /* ******** COMPONENT ******** */ /* ************************************* */ class $5bdc19770f09e5f2$var$JsonValue extends (0, $a6H0q$Component) {
componentWillReceiveProps(nextProps) {
this.setState({
value: nextProps.value
});
}
componentDidUpdate() {
const { editEnabled: editEnabled , inputRef: inputRef , name: name , value: value , keyPath: keyPath , deep: deep } = this.state;
const { readOnly: readOnly , dataType: dataType } = this.props;
const readOnlyResult = readOnly(name, value, keyPath, deep, dataType);
if (editEnabled && !readOnlyResult && typeof inputRef.focus === "function") inputRef.focus();
}
handleEdit() {
const { handleUpdateValue: handleUpdateValue , originalValue: originalValue , logger: logger , onSubmitValueParser: onSubmitValueParser , keyPath: keyPath } = this.props;
const { inputRef: inputRef , name: name , deep: deep } = this.state;
const newValue = onSubmitValueParser(true, keyPath, deep, name, inputRef.value);
const result = {
value: newValue,
key: name
};
// Run update
handleUpdateValue(result).then(()=>{
// Cancel edit mode if necessary
if (!(0, $23a5fe9e979d80ca$export$1172a3730e5c4525)(originalValue, newValue)) this.handleCancelEdit();
}).catch(logger.error);
}
handleEditMode() {
this.setState({
editEnabled: true
});
}
refInput(node) {
this.state.inputRef = node;
}
handleCancelEdit() {
this.setState({
editEnabled: false
});
}
render() {
const { name: name , value: value , editEnabled: editEnabled , keyPath: keyPath , deep: deep } = this.state;
const { handleRemove: handleRemove , originalValue: originalValue , readOnly: readOnly , dataType: dataType , getStyle: getStyle , editButtonElement: editButtonElement , cancelButtonElement: cancelButtonElement , inputElementGenerator: inputElementGenerator , minusMenuElement: minusMenuElement , keyPath: comeFromKeyPath , } = this.props;
const hotkeys = {
Escape: this.handleCancelEdit,
Enter: this.handleEdit
};
const style = getStyle(name, originalValue, keyPath, deep, dataType);
let result = null;
let minusElement = null;
const readOnlyResult = readOnly(name, originalValue, keyPath, deep, dataType);
if (editEnabled && !readOnlyResult) {
const inputElement = inputElementGenerator((0, $9d11e61eaae386e6$export$2e2bcd8739ae039).VALUE, comeFromKeyPath, deep, name, originalValue, dataType);
const editButtonElementLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(editButtonElement, {
onClick: this.handleEdit
});
const cancelButtonElementLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(cancelButtonElement, {
onClick: this.handleCancelEdit
});
const inputElementLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(inputElement, {
ref: this.refInput,
defaultValue: originalValue,
onKeyUp: (0, $d55c30c34fe7164f$export$6a361f9cf16d448e)(hotkeys)
});
result = /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-edit-form",
style: style.editForm
}, inputElementLayout, " ", cancelButtonElementLayout, editButtonElementLayout);
minusElement = null;
} else {
/* eslint-disable jsx-a11y/no-static-element-interactions */ result = /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-value",
style: style.value,
onClick: readOnlyResult ? null : this.handleEditMode
}, value);
/* eslint-enable */ const minusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(minusMenuElement, {
onClick: handleRemove,
className: "rejt-minus-menu",
style: style.minus
});
minusElement = readOnlyResult ? null : minusMenuLayout;
}
return /*#__PURE__*/ (0, $a6H0q$react).createElement("li", {
className: "rejt-value-node",
style: style.li
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-name",
style: style.name
}, name, ": "), result, minusElement);
}
constructor(props){
super(props);
const keyPath = [
...props.keyPath,
props.name,
];
this.state = {
value: props.value,
name: props.name,
keyPath: keyPath,
deep: props.deep,
editEnabled: false,
inputRef: null
};
// Bind
this.handleEditMode = this.handleEditMode.bind(this);
this.refInput = this.refInput.bind(this);
this.handleCancelEdit = this.handleCancelEdit.bind(this);
this.handleEdit = this.handleEdit.bind(this);
}
}
// Add prop types
$5bdc19770f09e5f2$var$JsonValue.propTypes = $5bdc19770f09e5f2$var$propTypes;
// Add default props
$5bdc19770f09e5f2$var$JsonValue.defaultProps = $5bdc19770f09e5f2$var$defaultProps;
var /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ $5bdc19770f09e5f2$export$2e2bcd8739ae039 = $5bdc19770f09e5f2$var$JsonValue;
/* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ // Prop types
const $2bab15d14095d489$var$propTypes = {
handleAdd: (0, $a6H0q$proptypes).func.isRequired,
handleCancel: (0, $a6H0q$proptypes).func.isRequired,
onlyValue: (0, $a6H0q$proptypes).bool,
addButtonElement: (0, $a6H0q$proptypes).element,
cancelButtonElement: (0, $a6H0q$proptypes).element,
inputElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
keyPath: (0, $a6H0q$proptypes).array,
deep: (0, $a6H0q$proptypes).number,
onSubmitValueParser: (0, $a6H0q$proptypes).func.isRequired
};
// Default props
const $2bab15d14095d489$var$defaultProps = {
onlyValue: false,
addButtonElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("button", null, "+"),
cancelButtonElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("button", null, "c")
};
/* ************************************* */ /* ******** COMPONENT ******** */ /* ************************************* */ class $2bab15d14095d489$var$JsonAddValue extends (0, $a6H0q$Component) {
componentDidMount() {
const { inputRefKey: inputRefKey , inputRefValue: inputRefValue } = this.state;
const { onlyValue: onlyValue } = this.props;
if (inputRefKey && typeof inputRefKey.focus === "function") inputRefKey.focus();
if (onlyValue && inputRefValue && typeof inputRefValue.focus === "function") inputRefValue.focus();
}
onSubmit() {
const { handleAdd: handleAdd , onlyValue: onlyValue , onSubmitValueParser: onSubmitValueParser , keyPath: keyPath , deep: deep } = this.props;
const { inputRefKey: inputRefKey , inputRefValue: inputRefValue } = this.state;
const result = {};
// Check if we have the key
if (!onlyValue) {
// Check that there is a key
if (!inputRefKey.value) // Empty key => Not authorized
return;
result.key = inputRefKey.value;
}
result.newValue = onSubmitValueParser(false, keyPath, deep, result.key, inputRefValue.value);
handleAdd(result);
}
refInputKey(node) {
this.state.inputRefKey = node;
}
refInputValue(node) {
this.state.inputRefValue = node;
}
render() {
const { handleCancel: handleCancel , onlyValue: onlyValue , addButtonElement: addButtonElement , cancelButtonElement: cancelButtonElement , inputElementGenerator: inputElementGenerator , keyPath: keyPath , deep: deep , } = this.props;
const hotkeys = {
Escape: handleCancel,
Enter: this.onSubmit
};
const addButtonElementLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(addButtonElement, {
onClick: this.onSubmit
});
const cancelButtonElementLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(cancelButtonElement, {
onClick: handleCancel
});
const inputElementValue = inputElementGenerator((0, $9d11e61eaae386e6$export$2e2bcd8739ae039).VALUE, keyPath, deep);
const inputElementValueLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(inputElementValue, {
placeholder: "Value",
ref: this.refInputValue,
onKeyUp: (0, $d55c30c34fe7164f$export$6a361f9cf16d448e)(hotkeys)
});
let inputElementKeyLayout = null;
let separatorElement = null;
if (!onlyValue) {
const inputElementKey = inputElementGenerator((0, $9d11e61eaae386e6$export$2e2bcd8739ae039).KEY, keyPath, deep);
inputElementKeyLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(inputElementKey, {
placeholder: "Key",
ref: this.refInputKey,
onKeyUp: (0, $d55c30c34fe7164f$export$6a361f9cf16d448e)(hotkeys)
});
separatorElement = ":";
}
return /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-add-value-node"
}, inputElementKeyLayout, " ", separatorElement, " ", inputElementValueLayout, " ", cancelButtonElementLayout, addButtonElementLayout);
}
constructor(props){
super(props);
this.state = {
inputRefKey: null,
inputRefValue: null
};
// Bind
this.refInputValue = this.refInputValue.bind(this);
this.refInputKey = this.refInputKey.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
}
// Add prop types
$2bab15d14095d489$var$JsonAddValue.propTypes = $2bab15d14095d489$var$propTypes;
// Add default props
$2bab15d14095d489$var$JsonAddValue.defaultProps = $2bab15d14095d489$var$defaultProps;
var /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ $2bab15d14095d489$export$2e2bcd8739ae039 = $2bab15d14095d489$var$JsonAddValue;
/*
* Author: Alexandre Havrileck (Oxyno-zeta)
* Date: 23/10/16
* Licence: See Readme
*/ /* ************************************* */ /* ******** IMPORTS ******** */ /* ************************************* */ /* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ const $81a31a9bc7e2feaa$export$58df28f56f04475d = "ADD_DELTA_TYPE";
const $81a31a9bc7e2feaa$export$eb8fc0985296a20 = "REMOVE_DELTA_TYPE";
const $81a31a9bc7e2feaa$export$f84f3b228725d3db = "UPDATE_DELTA_TYPE";
/* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ // Prop types
const $96531d4eb44d63bb$var$propTypes = {
data: (0, $a6H0q$proptypes).object.isRequired,
name: (0, $a6H0q$proptypes).string.isRequired,
isCollapsed: (0, $a6H0q$proptypes).func.isRequired,
keyPath: (0, $a6H0q$proptypes).array,
deep: (0, $a6H0q$proptypes).number,
handleRemove: (0, $a6H0q$proptypes).func,
onUpdate: (0, $a6H0q$proptypes).func.isRequired,
onDeltaUpdate: (0, $a6H0q$proptypes).func.isRequired,
readOnly: (0, $a6H0q$proptypes).func.isRequired,
dataType: (0, $a6H0q$proptypes).string,
getStyle: (0, $a6H0q$proptypes).func.isRequired,
addButtonElement: (0, $a6H0q$proptypes).element,
cancelButtonElement: (0, $a6H0q$proptypes).element,
editButtonElement: (0, $a6H0q$proptypes).element,
inputElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
textareaElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
minusMenuElement: (0, $a6H0q$proptypes).element,
plusMenuElement: (0, $a6H0q$proptypes).element,
beforeRemoveAction: (0, $a6H0q$proptypes).func,
beforeAddAction: (0, $a6H0q$proptypes).func,
beforeUpdateAction: (0, $a6H0q$proptypes).func,
logger: (0, $a6H0q$proptypes).object.isRequired,
onSubmitValueParser: (0, $a6H0q$proptypes).func.isRequired
};
// Default props
const $96531d4eb44d63bb$var$defaultProps = {
keyPath: [],
deep: 0,
minusMenuElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, " - "),
plusMenuElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, " + ")
};
/* ************************************* */ /* ******** COMPONENT ******** */ /* ************************************* */ class $96531d4eb44d63bb$var$JsonObject extends (0, $a6H0q$Component) {
componentWillReceiveProps(nextProps) {
this.setState({
data: nextProps.data
});
}
onChildUpdate(childKey, childData) {
const { data: data , keyPath: keyPath } = this.state;
// Update data
data[childKey] = childData;
// Put new data
this.setState({
data: data
});
// Spread
const { onUpdate: onUpdate } = this.props;
const size = keyPath.length;
onUpdate(keyPath[size - 1], data);
}
handleAddMode() {
this.setState({
addFormVisible: true
});
}
handleAddValueCancel() {
this.setState({
addFormVisible: false
});
}
handleAddValueAdd({ key: key , newValue: newValue }) {
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
const { beforeAddAction: beforeAddAction , logger: logger } = this.props;
beforeAddAction(key, keyPath, deep, newValue).then(()=>{
// Update data
data[key] = newValue;
this.setState({
data: data
});
// Cancel add to close
this.handleAddValueCancel();
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], data);
// Spread delta update
onDeltaUpdate({
type: (0, $81a31a9bc7e2feaa$export$58df28f56f04475d),
keyPath: keyPath,
deep: deep,
key: key,
newValue: newValue
});
}).catch(logger.error);
}
handleRemoveValue(key) {
return ()=>{
const { beforeRemoveAction: beforeRemoveAction , logger: logger } = this.props;
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
const oldValue = data[key];
// Before Remove Action
beforeRemoveAction(key, keyPath, deep, oldValue).then(()=>{
const objType = (0, $23a5fe9e979d80ca$export$11cc42aebef2ef3a)(oldValue);
const deltaUpdateResult = {
keyPath: keyPath,
deep: deep,
key: key,
oldValue: oldValue
};
if (objType === "Object" || objType === "Array") {
deltaUpdateResult.type = (0, $81a31a9bc7e2feaa$export$f84f3b228725d3db);
deltaUpdateResult.newValue = null;
data[key] = null;
} else {
deltaUpdateResult.type = (0, $81a31a9bc7e2feaa$export$eb8fc0985296a20);
delete data[key];
}
this.setState({
data: data
});
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], data);
// Spread delta update
onDeltaUpdate(deltaUpdateResult);
}).catch(logger.error);
};
}
handleCollapseMode() {
this.setState({
collapsed: !this.state.collapsed
});
}
handleEditValue({ key: key , value: value }) {
return new Promise((resolve, reject)=>{
const { beforeUpdateAction: beforeUpdateAction } = this.props;
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
// Old value
const oldValue = data[key];
// Before update action
beforeUpdateAction(key, keyPath, deep, oldValue, value).then(()=>{
// Update value
data[key] = value;
// Set state
this.setState({
data: data
});
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], data);
// Spread delta update
onDeltaUpdate({
type: (0, $81a31a9bc7e2feaa$export$f84f3b228725d3db),
keyPath: keyPath,
deep: deep,
key: key,
newValue: value,
oldValue: oldValue
});
// Resolve
resolve();
}).catch(reject);
});
}
renderCollapsed() {
const { name: name , keyPath: keyPath , deep: deep , data: data } = this.state;
const { handleRemove: handleRemove , readOnly: readOnly , dataType: dataType , getStyle: getStyle , minusMenuElement: minusMenuElement } = this.props;
const { minus: minus , collapsed: collapsed } = getStyle(name, data, keyPath, deep, dataType);
const keyList = Object.getOwnPropertyNames(data);
const collapseValue = " {...}";
const numberOfItems = keyList.length;
const itemName = numberOfItems > 1 ? "keys" : "key";
let minusElement = null;
// Check if readOnly is activated
if (!readOnly(name, data, keyPath, deep, dataType)) {
const minusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(minusMenuElement, {
onClick: handleRemove,
className: "rejt-minus-menu",
style: minus
});
minusElement = deep !== -1 ? minusMenuLayout : null;
}
/* eslint-disable jsx-a11y/no-static-element-interactions */ return /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-collapsed"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-collapsed-text",
style: collapsed,
onClick: this.handleCollapseMode
}, collapseValue, " ", numberOfItems, " ", itemName), minusElement);
/* eslint-enable */ }
renderNotCollapsed() {
const { name: name , data: data , keyPath: keyPath , deep: deep , nextDeep: nextDeep , addFormVisible: addFormVisible } = this.state;
const { isCollapsed: isCollapsed , handleRemove: handleRemove , onDeltaUpdate: onDeltaUpdate , readOnly: readOnly , getStyle: getStyle , dataType: dataType , addButtonElement: addButtonElement , cancelButtonElement: cancelButtonElement , editButtonElement: editButtonElement , inputElementGenerator: inputElementGenerator , textareaElementGenerator: textareaElementGenerator , minusMenuElement: minusMenuElement , plusMenuElement: plusMenuElement , beforeRemoveAction: beforeRemoveAction , beforeAddAction: beforeAddAction , beforeUpdateAction: beforeUpdateAction , logger: logger , onSubmitValueParser: onSubmitValueParser , } = this.props;
const { minus: minus , plus: plus , addForm: addForm , ul: ul , delimiter: delimiter } = getStyle(name, data, keyPath, deep, dataType);
const keyList = Object.getOwnPropertyNames(data);
let minusElement = null;
const readOnlyResult = readOnly(name, data, keyPath, deep, dataType);
// Check if readOnly is activated
if (!readOnlyResult) {
const minusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(minusMenuElement, {
onClick: handleRemove,
className: "rejt-minus-menu",
style: minus
});
minusElement = deep !== -1 ? minusMenuLayout : null;
}
const list = keyList.map((key)=>/*#__PURE__*/ (0, $a6H0q$react).createElement((0, $8eee1650ad9f7cc4$export$2e2bcd8739ae039), {
key: key,
name: key,
data: data[key],
keyPath: keyPath,
deep: nextDeep,
isCollapsed: isCollapsed,
handleRemove: this.handleRemoveValue(key),
handleUpdateValue: this.handleEditValue,
onUpdate: this.onChildUpdate,
onDeltaUpdate: onDeltaUpdate,
readOnly: readOnly,
getStyle: getStyle,
addButtonElement: addButtonElement,
cancelButtonElement: cancelButtonElement,
editButtonElement: editButtonElement,
inputElementGenerator: inputElementGenerator,
textareaElementGenerator: textareaElementGenerator,
minusMenuElement: minusMenuElement,
plusMenuElement: plusMenuElement,
beforeRemoveAction: beforeRemoveAction,
beforeAddAction: beforeAddAction,
beforeUpdateAction: beforeUpdateAction,
logger: logger,
onSubmitValueParser: onSubmitValueParser
}));
const startObject = "{";
const endObject = "}";
let menu = null;
// Check if readOnly is activated
if (!readOnlyResult) {
const plusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(plusMenuElement, {
onClick: this.handleAddMode,
className: "rejt-plus-menu",
style: plus
});
menu = addFormVisible ? /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-add-form",
style: addForm
}, /*#__PURE__*/ (0, $a6H0q$react).createElement((0, $2bab15d14095d489$export$2e2bcd8739ae039), {
handleAdd: this.handleAddValueAdd,
handleCancel: this.handleAddValueCancel,
addButtonElement: addButtonElement,
cancelButtonElement: cancelButtonElement,
inputElementGenerator: inputElementGenerator,
keyPath: keyPath,
deep: deep,
onSubmitValueParser: onSubmitValueParser
})) : /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, plusMenuLayout, " ", minusElement);
}
return /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed-delimiter",
style: delimiter
}, startObject), /*#__PURE__*/ (0, $a6H0q$react).createElement("ul", {
className: "rejt-not-collapsed-list",
style: ul
}, list), /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed-delimiter",
style: delimiter
}, endObject), menu);
}
render() {
const { name: name , collapsed: collapsed , data: data , keyPath: keyPath , deep: deep } = this.state;
const { getStyle: getStyle , dataType: dataType } = this.props;
const value = collapsed ? this.renderCollapsed() : this.renderNotCollapsed();
const style = getStyle(name, data, keyPath, deep, dataType);
/* eslint-disable jsx-a11y/no-static-element-interactions */ return /*#__PURE__*/ (0, $a6H0q$react).createElement("div", {
className: "rejt-object-node"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
onClick: this.handleCollapseMode
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-name",
style: style.name
}, name, " : ")), value);
/* eslint-enable */ }
constructor(props){
super(props);
const keyPath = props.deep === -1 ? [] : [
...props.keyPath,
props.name,
];
this.state = {
name: props.name,
data: props.data,
keyPath: keyPath,
deep: props.deep,
nextDeep: props.deep + 1,
collapsed: props.isCollapsed(keyPath, props.deep, props.data),
addFormVisible: false
};
// Bind
this.handleCollapseMode = this.handleCollapseMode.bind(this);
this.handleRemoveValue = this.handleRemoveValue.bind(this);
this.handleAddMode = this.handleAddMode.bind(this);
this.handleAddValueAdd = this.handleAddValueAdd.bind(this);
this.handleAddValueCancel = this.handleAddValueCancel.bind(this);
this.handleEditValue = this.handleEditValue.bind(this);
this.onChildUpdate = this.onChildUpdate.bind(this);
this.renderCollapsed = this.renderCollapsed.bind(this);
this.renderNotCollapsed = this.renderNotCollapsed.bind(this);
}
}
// Add prop types
$96531d4eb44d63bb$var$JsonObject.propTypes = $96531d4eb44d63bb$var$propTypes;
// Add default props
$96531d4eb44d63bb$var$JsonObject.defaultProps = $96531d4eb44d63bb$var$defaultProps;
var /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ $96531d4eb44d63bb$export$2e2bcd8739ae039 = $96531d4eb44d63bb$var$JsonObject;
/* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ // Prop types
const $d75ab2710d4a52f0$var$propTypes = {
data: (0, $a6H0q$proptypes).array.isRequired,
name: (0, $a6H0q$proptypes).string.isRequired,
isCollapsed: (0, $a6H0q$proptypes).func.isRequired,
keyPath: (0, $a6H0q$proptypes).array,
deep: (0, $a6H0q$proptypes).number,
handleRemove: (0, $a6H0q$proptypes).func,
onUpdate: (0, $a6H0q$proptypes).func.isRequired,
onDeltaUpdate: (0, $a6H0q$proptypes).func.isRequired,
readOnly: (0, $a6H0q$proptypes).func.isRequired,
dataType: (0, $a6H0q$proptypes).string,
getStyle: (0, $a6H0q$proptypes).func.isRequired,
addButtonElement: (0, $a6H0q$proptypes).element,
cancelButtonElement: (0, $a6H0q$proptypes).element,
editButtonElement: (0, $a6H0q$proptypes).element,
inputElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
textareaElementGenerator: (0, $a6H0q$proptypes).func.isRequired,
minusMenuElement: (0, $a6H0q$proptypes).element,
plusMenuElement: (0, $a6H0q$proptypes).element,
beforeRemoveAction: (0, $a6H0q$proptypes).func,
beforeAddAction: (0, $a6H0q$proptypes).func,
beforeUpdateAction: (0, $a6H0q$proptypes).func,
logger: (0, $a6H0q$proptypes).object.isRequired,
onSubmitValueParser: (0, $a6H0q$proptypes).func.isRequired
};
// Default props
const $d75ab2710d4a52f0$var$defaultProps = {
keyPath: [],
deep: 0,
minusMenuElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, " - "),
plusMenuElement: /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, " + ")
};
/* ************************************* */ /* ******** COMPONENT ******** */ /* ************************************* */ class $d75ab2710d4a52f0$var$JsonArray extends (0, $a6H0q$Component) {
componentWillReceiveProps(nextProps) {
this.setState({
data: nextProps.data
});
}
onChildUpdate(childKey, childData) {
const { data: data , keyPath: keyPath } = this.state;
// Update data
data[childKey] = childData;
// Put new data
this.setState({
data: data
});
// Spread
const { onUpdate: onUpdate } = this.props;
const size = keyPath.length;
onUpdate(keyPath[size - 1], data);
}
handleAddMode() {
this.setState({
addFormVisible: true
});
}
handleCollapseMode() {
this.setState({
collapsed: !this.state.collapsed
});
}
handleRemoveItem(index) {
return ()=>{
const { beforeRemoveAction: beforeRemoveAction , logger: logger } = this.props;
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
const oldValue = data[index];
// Before Remove Action
beforeRemoveAction(index, keyPath, deep, oldValue).then(()=>{
const objType = (0, $23a5fe9e979d80ca$export$11cc42aebef2ef3a)(data[index]);
const deltaUpdateResult = {
keyPath: keyPath,
deep: deep,
key: index,
oldValue: oldValue
};
if (objType === "Object" || objType === "Array") {
deltaUpdateResult.type = (0, $81a31a9bc7e2feaa$export$f84f3b228725d3db);
deltaUpdateResult.newValue = null;
data[index] = null;
} else {
deltaUpdateResult.type = (0, $81a31a9bc7e2feaa$export$eb8fc0985296a20);
data.splice(index, 1);
}
this.setState({
data: data
});
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], data);
// Spread delta update
onDeltaUpdate(deltaUpdateResult);
}).catch(logger.error);
};
}
handleAddValueAdd({ newValue: newValue }) {
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
const { beforeAddAction: beforeAddAction , logger: logger } = this.props;
beforeAddAction(data.length, keyPath, deep, newValue).then(()=>{
// Update data
const newData = [
...data,
newValue,
];
this.setState({
data: newData
});
// Cancel add to close
this.handleAddValueCancel();
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], newData);
// Spread delta update
onDeltaUpdate({
type: (0, $81a31a9bc7e2feaa$export$58df28f56f04475d),
keyPath: keyPath,
deep: deep,
key: newData.length - 1,
newValue: newValue
});
}).catch(logger.error);
}
handleAddValueCancel() {
this.setState({
addFormVisible: false
});
}
handleEditValue({ key: key , value: value }) {
return new Promise((resolve, reject)=>{
const { beforeUpdateAction: beforeUpdateAction } = this.props;
const { data: data , keyPath: keyPath , nextDeep: deep } = this.state;
// Old value
const oldValue = data[key];
// Before update action
beforeUpdateAction(key, keyPath, deep, oldValue, value).then(()=>{
// Update value
data[key] = value;
// Set state
this.setState({
data: data
});
// Spread new update
const { onUpdate: onUpdate , onDeltaUpdate: onDeltaUpdate } = this.props;
onUpdate(keyPath[keyPath.length - 1], data);
// Spread delta update
onDeltaUpdate({
type: (0, $81a31a9bc7e2feaa$export$f84f3b228725d3db),
keyPath: keyPath,
deep: deep,
key: key,
newValue: value,
oldValue: oldValue
});
// Resolve
resolve();
}).catch(reject);
});
}
renderCollapsed() {
const { name: name , data: data , keyPath: keyPath , deep: deep } = this.state;
const { handleRemove: handleRemove , readOnly: readOnly , getStyle: getStyle , dataType: dataType , minusMenuElement: minusMenuElement } = this.props;
const { minus: minus , collapsed: collapsed } = getStyle(name, data, keyPath, deep, dataType);
const collapseValue = " [...]";
const numberOfItems = data.length;
let minusElement = null;
// Check if readOnly is activated
if (!readOnly(name, data, keyPath, deep, dataType)) {
const minusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(minusMenuElement, {
onClick: handleRemove,
className: "rejt-minus-menu",
style: minus
});
minusElement = deep !== -1 ? minusMenuLayout : null;
}
const itemName = numberOfItems > 1 ? "items" : "item";
/* eslint-disable jsx-a11y/no-static-element-interactions */ return /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-collapsed"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-collapsed-text",
style: collapsed,
onClick: this.handleCollapseMode
}, collapseValue, " ", numberOfItems, " ", itemName), minusElement);
/* eslint-enable */ }
renderNotCollapsed() {
const { name: name , data: data , keyPath: keyPath , deep: deep , addFormVisible: addFormVisible , nextDeep: nextDeep } = this.state;
const { isCollapsed: isCollapsed , handleRemove: handleRemove , onDeltaUpdate: onDeltaUpdate , readOnly: readOnly , getStyle: getStyle , dataType: dataType , addButtonElement: addButtonElement , cancelButtonElement: cancelButtonElement , editButtonElement: editButtonElement , inputElementGenerator: inputElementGenerator , textareaElementGenerator: textareaElementGenerator , minusMenuElement: minusMenuElement , plusMenuElement: plusMenuElement , beforeRemoveAction: beforeRemoveAction , beforeAddAction: beforeAddAction , beforeUpdateAction: beforeUpdateAction , logger: logger , onSubmitValueParser: onSubmitValueParser , } = this.props;
const { minus: minus , plus: plus , delimiter: delimiter , ul: ul , addForm: addForm } = getStyle(name, data, keyPath, deep, dataType);
let minusElement = null;
const readOnlyResult = readOnly(name, data, keyPath, deep, dataType);
// Check if readOnly is activated
if (!readOnlyResult) {
const minusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(minusMenuElement, {
onClick: handleRemove,
className: "rejt-minus-menu",
style: minus
});
minusElement = deep !== -1 ? minusMenuLayout : null;
}
const list = data.map((item, index)=>/*#__PURE__*/ (0, $a6H0q$react).createElement((0, $8eee1650ad9f7cc4$export$2e2bcd8739ae039), {
key: index,
name: `${index}`,
data: item,
keyPath: keyPath,
deep: nextDeep,
isCollapsed: isCollapsed,
handleRemove: this.handleRemoveItem(index),
handleUpdateValue: this.handleEditValue,
onUpdate: this.onChildUpdate,
onDeltaUpdate: onDeltaUpdate,
readOnly: readOnly,
getStyle: getStyle,
addButtonElement: addButtonElement,
cancelButtonElement: cancelButtonElement,
editButtonElement: editButtonElement,
inputElementGenerator: inputElementGenerator,
textareaElementGenerator: textareaElementGenerator,
minusMenuElement: minusMenuElement,
plusMenuElement: plusMenuElement,
beforeRemoveAction: beforeRemoveAction,
beforeAddAction: beforeAddAction,
beforeUpdateAction: beforeUpdateAction,
logger: logger,
onSubmitValueParser: onSubmitValueParser
}));
const onlyValue = true;
let menu = null;
// Check if readOnly is activated
if (!readOnlyResult) {
const plusMenuLayout = /*#__PURE__*/ (0, $a6H0q$react).cloneElement(plusMenuElement, {
onClick: this.handleAddMode,
className: "rejt-plus-menu",
style: plus
});
menu = addFormVisible ? /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-add-form",
style: addForm
}, /*#__PURE__*/ (0, $a6H0q$react).createElement((0, $2bab15d14095d489$export$2e2bcd8739ae039), {
handleAdd: this.handleAddValueAdd,
handleCancel: this.handleAddValueCancel,
onlyValue: onlyValue,
addButtonElement: addButtonElement,
cancelButtonElement: cancelButtonElement,
inputElementGenerator: inputElementGenerator,
keyPath: keyPath,
deep: deep,
onSubmitValueParser: onSubmitValueParser
})) : /*#__PURE__*/ (0, $a6H0q$react).createElement("span", null, plusMenuLayout, " ", minusElement);
}
const startObject = "[";
const endObject = "]";
return /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed-delimiter",
style: delimiter
}, startObject), /*#__PURE__*/ (0, $a6H0q$react).createElement("ul", {
className: "rejt-not-collapsed-list",
style: ul
}, list), /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-not-collapsed-delimiter",
style: delimiter
}, endObject), menu);
}
render() {
const { name: name , collapsed: collapsed , data: data , keyPath: keyPath , deep: deep } = this.state;
const { dataType: dataType , getStyle: getStyle } = this.props;
const value = collapsed ? this.renderCollapsed() : this.renderNotCollapsed();
const style = getStyle(name, data, keyPath, deep, dataType);
/* eslint-disable jsx-a11y/no-static-element-interactions */ return /*#__PURE__*/ (0, $a6H0q$react).createElement("div", {
className: "rejt-array-node"
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
onClick: this.handleCollapseMode
}, /*#__PURE__*/ (0, $a6H0q$react).createElement("span", {
className: "rejt-name",
style: style.name
}, name, " : ")), value);
/* eslint-enable */ }
constructor(props){
super(props);
const keyPath = [
...props.keyPath,
props.name,
];
this.state = {
data: props.data,
name: props.name,
keyPath: keyPath,
deep: props.deep,
nextDeep: props.deep + 1,
collapsed: props.isCollapsed(keyPath, props.deep, props.data),
addFormVisible: false
};
// Bind
this.handleCollapseMode = this.handleCollapseMode.bind(this);
this.handleRemoveItem = this.handleRemoveItem.bind(this);
this.handleAddMode = this.handleAddMode.bind(this);
this.handleAddValueAdd = this.handleAddValueAdd.bind(this);
this.handleAddValueCancel = this.handleAddValueCancel.bind(this);
this.handleEditValue = this.handleEditValue.bind(this);
this.onChildUpdate = this.onChildUpdate.bind(this);
this.renderCollapsed = this.renderCollapsed.bind(this);
this.renderNotCollapsed = this.renderNotCollapsed.bind(this);
}
}
// Add prop types
$d75ab2710d4a52f0$var$JsonArray.propTypes = $d75ab2710d4a52f0$var$propTypes;
// Add default props
$d75ab2710d4a52f0$var$JsonArray.defaultProps = $d75ab2710d4a52f0$var$defaultProps;
var /* ************************************* */ /* ******** EXPORTS ******** */ /* ************************************* */ $d75ab2710d4a52f0$export$2e2bcd8739ae039 = $d75ab2710d4a52f0$var$JsonArray;
/*
* Author: Alexandre Havrileck (Oxyno-zeta)
* Date: 22/10/16
* Licence: See Readme
*/ /* ************************************* */ /* ******** IMPORTS ******** */ /* ************************************* */ /* ************************************* */ /* ******** VARIABLES ******** */ /* ************************************* */ const $9f060e374a15eed4$var$basicFunctionPattern = new RegExp(// eslint-disable-next-line prefer-template
"" + /^function/.source + / *([$_a-zA-Z][$\w]*)?/.source // name
+ / *\([ \n]*([$_a-zA-Z][$\w]*(?:[ \n]*,[ \n]*[$_a-zA-Z][$\w]*)*)*?,?[ \n]*\)/.source // params
+ /[ \n]*{\n*(.*?)\n? *}$/.source, "s");
/* ************************************* */ /* ******** PRIVATE FUNCTIONS ******** */ /* ************************************* */ /**
* Try to regex match a string as a javascript function.
* @param functionString {string} string to match
* @param splitParams {boolean} whether to split parameters into an array
* @returns {{name: string, params: string | string[], body: string} | null}
*/ function $9f060e374a15eed4$var$matchFunction(functionString, splitParams = false) {
const match = $9f060e374a15eed4$var$basicFunctionPattern.exec(functionString);
if (match === null) return null;
return {
name: match[1],
params: splitParams ? $9f060e374a15eed4$var$commaSplit(match[2]) : match[2],
body: match[3]
};
}
/**
* Split comma separated strings and trim surrounding whitespace.
* @param string {string | undefined} a string of comma-separated strings
* @returns {string[]} an array of elements that were separated by commas with
* surrounding whitespace trimmed. May be empty.
*/ function $9f060e374a15eed4$var$commaSplit(string) {
if (!string) return [];
return string.split(",").map((x)=>x.trim());
}
/**
* Try creating an anonymous function from a string, or return null if it's
* not a valid function definition.
* Note that this is not a completely safe, there are still security flaws,
* but it is safer than using `exec`.
* @param functionString {string} string to try to parse as a function
* definition
* @returns {Function | null} an anonymous function if the string is a valid
* function definition, else null
*/ function $9f060e374a15eed4$var$createFunction(functionString) {
/* This is not an exhaustive check by any means
* For instance, function names may have a wide variety of
* unicode characters and still be valid... oh well!
*
* TEST CASES:
*
* // Should match (single-line):
* function() {}
* function () {}
* function myFunc(){}
* function myFunc(arg1){}
* function(arg1,arg2, arg3, arg4) {}
* function myFunc(arg1, arg2, arg3){}
* function myFunc(arg1, arg2, arg3){console.log('something');}
* function myFunc(arg1,){}
* function myFunc(arg1, ){}
* function myFunc(arg1) {if (true) {var moreCurlyBraces = 1;}}
*
* // Should match (multi-line):
* function myFunc(arg1, arg2, arg3) {
* console.log('something');
* }
*
* function myFunc() {
* console.log('test');
* if (true) {
* console.log('test2');
* }
* }
*
* // Should not match (single-line):
* anotherFunction()
* function myFunc {}
* function myFunc()); (anotherFunction()
* function myFunc(){}, anotherFunction()
*/ const match = $9f060e374a15eed4$var$matchFunction(functionString, true);
if (!match) return null;
// Here's the security flaw. We want this functionality for supporting
// JSONP, so we've opted for the best attempt at maintaining some amount
// of security. This should be a little better than eval because it
// shouldn't automatically execute code, just create a function which can
// be called later.
// eslint-disable-next-line no-new-func
const func = new Function(...match.params, match.body || "");
func.displayName = match.name;
return func;
}
/* ************************************* */ /* ******** PUBLIC FUNCTIONS ******** */ /* ************************************* */ /**
* Parse a string into either a function or a JSON element.
* @param string {string} string to parse
* @param allowFunctionEvaluation {boolean} whether to parse strings that
* are function definitions as Javascript
* @returns {Function | Object | Array | null | boolean | number | string}
*/ function $9f060e374a15eed4$var$parse(string, allowFunctionEvaluation) {
// Try parsing (and sanitizing) a function
if (allowFunctionEvaluation) {
const func = $9f060e374a15eed4$var$createFunction(string);
if (func !== null) return func;
}
try {
return JSON.parse(string);
} catch (e) {
return string;
}
}
/**
* A different implementation of Function.prototype.toString which tries to get
* a function name using displayN