Refactored the internal data structure
This commit is contained in:
parent
224e436828
commit
38250a38ba
|
@ -47,7 +47,7 @@ export default class JSONNode extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONObject ({path, data, options, events}) {
|
renderJSONObject ({path, data, options, events}) {
|
||||||
const childCount = data.childs.length
|
const childCount = data.props.length
|
||||||
const contents = [
|
const contents = [
|
||||||
h('div', {class: 'jsoneditor-node jsoneditor-object'}, [
|
h('div', {class: 'jsoneditor-node jsoneditor-object'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
|
@ -59,23 +59,23 @@ export default class JSONNode extends Component {
|
||||||
]
|
]
|
||||||
|
|
||||||
if (data.expanded) {
|
if (data.expanded) {
|
||||||
const childs = data.childs.map(child => {
|
const props = data.props.map(prop => {
|
||||||
return h(JSONNode, {
|
return h(JSONNode, {
|
||||||
path: path.concat(child.prop),
|
path: path.concat(prop.name),
|
||||||
data: child,
|
data: prop.value,
|
||||||
options,
|
options,
|
||||||
events
|
events
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
contents.push(h('ul', {class: 'jsoneditor-list'}, childs))
|
contents.push(h('ul', {class: 'jsoneditor-list'}, props))
|
||||||
}
|
}
|
||||||
|
|
||||||
return h('li', {}, contents)
|
return h('li', {}, contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderJSONArray ({path, data, options, events}) {
|
renderJSONArray ({path, data, options, events}) {
|
||||||
const childCount = data.childs.length
|
const childCount = data.items.length
|
||||||
const contents = [
|
const contents = [
|
||||||
h('div', {class: 'jsoneditor-node jsoneditor-array'}, [
|
h('div', {class: 'jsoneditor-node jsoneditor-array'}, [
|
||||||
this.renderExpandButton(),
|
this.renderExpandButton(),
|
||||||
|
@ -87,7 +87,7 @@ export default class JSONNode extends Component {
|
||||||
]
|
]
|
||||||
|
|
||||||
if (data.expanded) {
|
if (data.expanded) {
|
||||||
const childs = data.childs.map((child, index) => {
|
const items = data.items.map((child, index) => {
|
||||||
return h(JSONNode, {
|
return h(JSONNode, {
|
||||||
path: path.concat(index),
|
path: path.concat(index),
|
||||||
data: child,
|
data: child,
|
||||||
|
@ -96,7 +96,7 @@ export default class JSONNode extends Component {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
contents.push(h('ul', {class: 'jsoneditor-list'}, childs))
|
contents.push(h('ul', {class: 'jsoneditor-list'}, items))
|
||||||
}
|
}
|
||||||
|
|
||||||
return h('li', {}, contents)
|
return h('li', {}, contents)
|
||||||
|
@ -259,31 +259,31 @@ export default class JSONNode extends Component {
|
||||||
title: 'Insert a new item with type \'value\' after this item (Ctrl+Ins)',
|
title: 'Insert a new item with type \'value\' after this item (Ctrl+Ins)',
|
||||||
submenuTitle: 'Select the type of the item to be inserted',
|
submenuTitle: 'Select the type of the item to be inserted',
|
||||||
className: 'jsoneditor-insert',
|
className: 'jsoneditor-insert',
|
||||||
click: () => events.onInsert(path, '', ''),
|
click: () => events.onInsert(path, 'value'),
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
text: 'Value',
|
text: 'Value',
|
||||||
className: 'jsoneditor-type-value',
|
className: 'jsoneditor-type-value',
|
||||||
title: TYPE_TITLES.value,
|
title: TYPE_TITLES.value,
|
||||||
click: () => events.onInsert(path, '', '')
|
click: () => events.onInsert(path, 'value')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Array',
|
text: 'Array',
|
||||||
className: 'jsoneditor-type-array',
|
className: 'jsoneditor-type-array',
|
||||||
title: TYPE_TITLES.array,
|
title: TYPE_TITLES.array,
|
||||||
click: () => events.onInsert(path, '', [])
|
click: () => events.onInsert(path, 'array')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Object',
|
text: 'Object',
|
||||||
className: 'jsoneditor-type-object',
|
className: 'jsoneditor-type-object',
|
||||||
title: TYPE_TITLES.object,
|
title: TYPE_TITLES.object,
|
||||||
click: () => events.onInsert(path, '', {})
|
click: () => events.onInsert(path, 'object')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'String',
|
text: 'String',
|
||||||
className: 'jsoneditor-type-string',
|
className: 'jsoneditor-type-string',
|
||||||
title: TYPE_TITLES.string,
|
title: TYPE_TITLES.string,
|
||||||
click: () => events.onInsert(path, '', '', 'string')
|
click: () => events.onInsert(path, 'string')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
@ -326,7 +326,7 @@ export default class JSONNode extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeProperty (event) {
|
handleChangeProperty (event) {
|
||||||
const oldProp = this.props.data.prop
|
const oldProp = last(this.props.path)
|
||||||
const newProp = unescapeHTML(getInnerText(event.target))
|
const newProp = unescapeHTML(getInnerText(event.target))
|
||||||
|
|
||||||
// remove last entry from the path to get the path of the parent object
|
// remove last entry from the path to get the path of the parent object
|
||||||
|
|
364
src/Main.js
364
src/Main.js
|
@ -23,7 +23,7 @@ export default class Main extends Component {
|
||||||
data: {
|
data: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
expanded: true,
|
expanded: true,
|
||||||
childs: []
|
props: []
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
|
@ -73,8 +73,7 @@ export default class Main extends Component {
|
||||||
const index = this._findIndex(path, oldProp)
|
const index = this._findIndex(path, oldProp)
|
||||||
const newPath = path.concat(newProp)
|
const newPath = path.concat(newProp)
|
||||||
|
|
||||||
this._setIn(path, ['childs', index, 'path'], newPath)
|
this._setIn(path, ['props', index, 'name'], newProp)
|
||||||
this._setIn(path, ['childs', index, 'prop'], newProp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChangeType (path, type) {
|
handleChangeType (path, type) {
|
||||||
|
@ -83,8 +82,8 @@ export default class Main extends Component {
|
||||||
this._setIn(path, ['type'], type)
|
this._setIn(path, ['type'], type)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInsert (path, prop, value, type) {
|
handleInsert (path, type) {
|
||||||
console.log('handleInsert', path, prop, value, type)
|
console.log('handleInsert', path, type)
|
||||||
|
|
||||||
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
||||||
|
|
||||||
|
@ -94,25 +93,29 @@ export default class Main extends Component {
|
||||||
const parentPath = path.slice(0, path.length - 1)
|
const parentPath = path.slice(0, path.length - 1)
|
||||||
const parent = this._getIn(parentPath)
|
const parent = this._getIn(parentPath)
|
||||||
|
|
||||||
const index = parent.type === 'array'
|
if (parent.type === 'array') {
|
||||||
? parseInt(afterProp)
|
this._updateIn(parentPath, ['items'], (items) => {
|
||||||
: this._findIndex(parentPath, afterProp)
|
const index = parseInt(afterProp)
|
||||||
|
const updated = items.slice(0)
|
||||||
|
|
||||||
this._updateIn(parentPath, ['childs'], function (childs) {
|
updated.splice(index + 1, 0, createDataEntry(type))
|
||||||
const updated = childs.slice(0)
|
|
||||||
const type = isObject(value) ? 'object' : Array.isArray(value) ? 'array' : (type || 'value')
|
|
||||||
const newEntry = {
|
|
||||||
expanded: true,
|
|
||||||
type,
|
|
||||||
prop,
|
|
||||||
value,
|
|
||||||
childs: []
|
|
||||||
}
|
|
||||||
|
|
||||||
updated.splice(index + 1, 0, newEntry)
|
return updated
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else { // parent.type === 'object'
|
||||||
|
this._updateIn(parentPath, ['props'], (props) => {
|
||||||
|
const index = this._findIndex(parentPath, afterProp)
|
||||||
|
const updated = props.slice(0)
|
||||||
|
|
||||||
return updated
|
updated.splice(index + 1, 0, {
|
||||||
})
|
name: '',
|
||||||
|
value: createDataEntry(type)
|
||||||
|
})
|
||||||
|
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDuplicate (path) {
|
handleDuplicate (path) {
|
||||||
|
@ -126,19 +129,30 @@ export default class Main extends Component {
|
||||||
const parentPath = path.slice(0, path.length - 1)
|
const parentPath = path.slice(0, path.length - 1)
|
||||||
const parent = this._getIn(parentPath)
|
const parent = this._getIn(parentPath)
|
||||||
|
|
||||||
const index = parent.type === 'array'
|
if (parent.type === 'array') {
|
||||||
? parseInt(prop)
|
this._updateIn(parentPath, ['items'], (items) => {
|
||||||
: this._findIndex(parentPath, prop)
|
const index = parseInt(prop)
|
||||||
|
const updated = items.slice(0)
|
||||||
|
const original = items[index]
|
||||||
|
const duplicate = cloneDeep(original)
|
||||||
|
|
||||||
this._updateIn(parentPath, ['childs'], function (childs) {
|
updated.splice(index + 1, 0, duplicate)
|
||||||
const updated = childs.slice(0)
|
|
||||||
const original = childs[index]
|
|
||||||
const duplicate = cloneDeep(original)
|
|
||||||
|
|
||||||
updated.splice(index + 1, 0, duplicate)
|
return updated
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else { // parent.type === 'object'
|
||||||
|
this._updateIn(parentPath, ['props'], (props) => {
|
||||||
|
const index = this._findIndex(parentPath, prop)
|
||||||
|
const updated = props.slice(0)
|
||||||
|
const original = props[index]
|
||||||
|
const duplicate = cloneDeep(original)
|
||||||
|
|
||||||
return updated
|
updated.splice(index + 1, 0, duplicate)
|
||||||
})
|
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRemove (path) {
|
handleRemove (path) {
|
||||||
|
@ -146,11 +160,29 @@ export default class Main extends Component {
|
||||||
|
|
||||||
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
||||||
|
|
||||||
this._deleteIn(path)
|
const parentPath = path.slice(0, path.length - 1)
|
||||||
|
const parent = this._getIn(parentPath)
|
||||||
|
|
||||||
|
if (parent.type === 'array') {
|
||||||
|
const dataPath = toDataPath(this.state.data, path)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
data: deleteIn(this.state.data, dataPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else { // parent.type === 'object'
|
||||||
|
const dataPath = toDataPath(this.state.data, path)
|
||||||
|
|
||||||
|
dataPath.pop() // remove the 'value' property, we want to remove the whole object property
|
||||||
|
this.setState({
|
||||||
|
data: deleteIn(this.state.data, dataPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order the childs of an array in ascending or descending order
|
* Order the items of an array or the properties of an object in ascending
|
||||||
|
* or descending order
|
||||||
* @param {Array.<string | number>} path
|
* @param {Array.<string | number>} path
|
||||||
* @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering
|
* @param {'asc' | 'desc' | null} [order=null] If not provided, will toggle current ordering
|
||||||
*/
|
*/
|
||||||
|
@ -159,7 +191,7 @@ export default class Main extends Component {
|
||||||
|
|
||||||
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
this.handleHideContextMenu() // TODO: should be handled by the contextmenu itself
|
||||||
|
|
||||||
const entry = this._getIn(path)
|
const object = this._getIn(path)
|
||||||
|
|
||||||
let _order
|
let _order
|
||||||
if (order === 'asc' || order === 'desc') {
|
if (order === 'asc' || order === 'desc') {
|
||||||
|
@ -167,23 +199,30 @@ export default class Main extends Component {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// toggle previous order
|
// toggle previous order
|
||||||
_order = entry.order !== 'asc' ? 'asc' : 'desc'
|
_order = object.order !== 'asc' ? 'asc' : 'desc'
|
||||||
this._setIn(path, ['order'], _order)
|
this._setIn(path, ['order'], _order)
|
||||||
}
|
}
|
||||||
|
|
||||||
this._updateIn(path, ['childs'], function (childs) {
|
if (object.type === 'array') {
|
||||||
const ordered = childs.slice(0)
|
this._updateIn(path, ['items'], function (items) {
|
||||||
const compare = _order === 'desc' ? compareDesc : compareAsc
|
const ordered = items.slice(0)
|
||||||
|
const compare = _order === 'desc' ? compareDesc : compareAsc
|
||||||
|
|
||||||
if (entry.type === 'array') {
|
|
||||||
ordered.sort((a, b) => compare(a.value, b.value))
|
ordered.sort((a, b) => compare(a.value, b.value))
|
||||||
}
|
|
||||||
else { // entry.type === 'object'
|
|
||||||
ordered.sort((a, b) => compare(a.prop, b.prop))
|
|
||||||
}
|
|
||||||
|
|
||||||
return ordered
|
return ordered
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
else { // object.type === 'object'
|
||||||
|
this._updateIn(path, ['props'], function (props) {
|
||||||
|
const ordered = props.slice(0)
|
||||||
|
const compare = _order === 'desc' ? compareDesc : compareAsc
|
||||||
|
|
||||||
|
ordered.sort((a, b) => compare(a.name, b.name))
|
||||||
|
|
||||||
|
return ordered
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleExpand(path, expand) {
|
handleExpand(path, expand) {
|
||||||
|
@ -223,50 +262,42 @@ export default class Main extends Component {
|
||||||
this.handleShowContextMenu({})
|
this.handleShowContextMenu({})
|
||||||
}
|
}
|
||||||
|
|
||||||
_getIn (path, modelProps = []) {
|
_getIn (path, dataProps = []) {
|
||||||
const modelPath = Main._pathToModelPath(this.state.data, path)
|
const dataPath = toDataPath(this.state.data, path)
|
||||||
|
|
||||||
return getIn(this.state.data, modelPath.concat(modelProps))
|
return getIn(this.state.data, dataPath.concat(dataProps))
|
||||||
}
|
}
|
||||||
|
|
||||||
_setIn (path, modelProps = [], value) {
|
_setIn (path, dataProps = [], value) {
|
||||||
const modelPath = Main._pathToModelPath(this.state.data, path)
|
const dataPath = toDataPath(this.state.data, path)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
data: setIn(this.state.data, modelPath.concat(modelProps), value)
|
data: setIn(this.state.data, dataPath.concat(dataProps), value)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateIn (path, modelProps = [], callback) {
|
_updateIn (path, dataProps = [], callback) {
|
||||||
const modelPath = Main._pathToModelPath(this.state.data, path)
|
const dataPath = toDataPath(this.state.data, path)
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
data: updateIn(this.state.data, modelPath.concat(modelProps), callback)
|
data: updateIn(this.state.data, dataPath.concat(dataProps), callback)
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
_deleteIn (path, modelProps = []) {
|
|
||||||
const modelPath = Main._pathToModelPath(this.state.data, path)
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
data: deleteIn(this.state.data, modelPath.concat(modelProps))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_findIndex(path, prop) {
|
_findIndex(path, prop) {
|
||||||
const object = this._getIn(path)
|
const object = this._getIn(path)
|
||||||
return object.childs.findIndex(child => child.prop === prop)
|
return object.props.findIndex(p => p.name === prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: comment
|
// TODO: comment
|
||||||
get () {
|
get () {
|
||||||
return Main._modelToJson(this.state.data)
|
return dataToJson(this.state.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: comment
|
// TODO: comment
|
||||||
set (json) {
|
set (json) {
|
||||||
this.setState({
|
this.setState({
|
||||||
data: Main._jsonToModel([], null, json, this.state.options.expand)
|
data: jsonToData([], json, this.state.options.expand)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,92 +313,119 @@ export default class Main extends Component {
|
||||||
return path.length === 0
|
return path.length === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* Convert a path of a JSON object into a path in the corresponding data model
|
|
||||||
* @param {Model} model
|
/**
|
||||||
* @param {Array.<string | number>} path
|
* Convert a path of a JSON object into a path in the corresponding data model
|
||||||
* @return {Array.<string | number>} modelPath
|
* @param {Data} data
|
||||||
* @private
|
* @param {Array.<string | number>} path
|
||||||
*/
|
* @return {Array.<string | number>} dataPath
|
||||||
static _pathToModelPath (model, path) {
|
* @private
|
||||||
if (path.length === 0) {
|
*/
|
||||||
return []
|
function toDataPath (data, path) {
|
||||||
}
|
if (path.length === 0) {
|
||||||
|
return []
|
||||||
let index
|
}
|
||||||
if (typeof path[0] === 'number') {
|
|
||||||
// index of an array
|
let index
|
||||||
index = path[0]
|
if (data.type === 'array') {
|
||||||
}
|
// index of an array
|
||||||
else {
|
index = path[0]
|
||||||
// object property. find the index of this property
|
|
||||||
index = model.childs.findIndex(child => child.prop === path[0])
|
return ['items', index].concat(toDataPath(data.items[index], path.slice(1)))
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
return ['childs', index]
|
// object property. find the index of this property
|
||||||
.concat(Main._pathToModelPath(model.childs[index], path.slice(1)))
|
index = data.props.findIndex(prop => prop.name === path[0])
|
||||||
}
|
|
||||||
|
return ['props', index, 'value'].concat(toDataPath(data.props[index].value, path.slice(1)))
|
||||||
/**
|
}
|
||||||
* Convert a JSON object into the internally used data model
|
}
|
||||||
* @param {Array.<string | number>} path
|
|
||||||
* @param {string | null} prop
|
/**
|
||||||
* @param {Object | Array | string | number | boolean | null} value
|
* Convert a JSON object into the internally used data model
|
||||||
* @param {function(path: Array.<string | number>)} expand
|
* @param {Array.<string | number>} path
|
||||||
* @return {Model}
|
* @param {Object | Array | string | number | boolean | null} json
|
||||||
* @private
|
* @param {function(path: Array.<string | number>)} expand
|
||||||
*/
|
* @return {Data}
|
||||||
static _jsonToModel (path, prop, value, expand) {
|
*/
|
||||||
if (Array.isArray(value)) {
|
function jsonToData (path, json, expand) {
|
||||||
return {
|
if (Array.isArray(json)) {
|
||||||
type: 'array',
|
return {
|
||||||
expanded: expand(path),
|
type: 'array',
|
||||||
prop,
|
expanded: expand(path),
|
||||||
childs: value.map((child, index) => Main._jsonToModel(path.concat(index), null, child, expand))
|
items: json.map((child, index) => jsonToData(path.concat(index), child, expand))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isObject(value)) {
|
else if (isObject(json)) {
|
||||||
return {
|
return {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
expanded: expand(path),
|
expanded: expand(path),
|
||||||
prop,
|
props: Object.keys(json).map(name => {
|
||||||
childs: Object.keys(value).map(prop => {
|
return {
|
||||||
return Main._jsonToModel(path.concat(prop), prop, value[prop], expand)
|
name,
|
||||||
})
|
value: jsonToData(path.concat(name), json[name], expand)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
else {
|
}
|
||||||
return {
|
}
|
||||||
type: 'value',
|
else {
|
||||||
prop,
|
return {
|
||||||
value
|
type: 'json',
|
||||||
}
|
value: json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Convert the internal data model to a regular JSON object
|
/**
|
||||||
* @param {Model} model
|
* Convert the internal data model to a regular JSON object
|
||||||
* @return {Object | Array | string | number | boolean | null} json
|
* @param {Data} data
|
||||||
* @private
|
* @return {Object | Array | string | number | boolean | null} json
|
||||||
*/
|
*/
|
||||||
static _modelToJson (model) {
|
function dataToJson (data) {
|
||||||
if (model.type === 'array') {
|
if (data.type === 'array') {
|
||||||
return model.childs.map(Main._modelToJson)
|
return data.items.map(dataToJson)
|
||||||
}
|
}
|
||||||
else if (model.type === 'object') {
|
else if (data.type === 'object') {
|
||||||
const object = {}
|
const object = {}
|
||||||
|
|
||||||
model.childs.forEach(child => {
|
data.props.forEach(prop => {
|
||||||
object[child.prop] = Main._modelToJson(child)
|
object[prop.name] = dataToJson(prop.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
return object
|
return object
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// type 'value' or 'string'
|
// type 'value' or 'string'
|
||||||
return model.value
|
return data.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new data entry
|
||||||
|
* @param {'object' | 'array' | 'value' | 'string'} [type]
|
||||||
|
* @return {*}
|
||||||
|
*/
|
||||||
|
function createDataEntry (type) {
|
||||||
|
if (type === 'array') {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
expanded: true,
|
||||||
|
items: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'object') {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
expanded: true,
|
||||||
|
props: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,13 +4,25 @@
|
||||||
* type: string,
|
* type: string,
|
||||||
* expanded: boolean?,
|
* expanded: boolean?,
|
||||||
* menu: boolean?,
|
* menu: boolean?,
|
||||||
* prop: string?,
|
* props: Array.<{name: string, value: Data}>?
|
||||||
* value: *?,
|
* }} ObjectData
|
||||||
* childs: Model[]?
|
*
|
||||||
* }} Model
|
* @typedef {{
|
||||||
*/
|
* type: string,
|
||||||
|
* expanded: boolean?,
|
||||||
/**
|
* menu: boolean?,
|
||||||
|
* items: Data[]?
|
||||||
|
* }} ArrayData
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* type: string,
|
||||||
|
* expanded: boolean?,
|
||||||
|
* menu: boolean?,
|
||||||
|
* value: *?
|
||||||
|
* }} ValueData
|
||||||
|
*
|
||||||
|
* @typedef {ObjectData | ArrayData | ValueData} Data
|
||||||
|
*
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* name: string?
|
* name: string?
|
||||||
* expand: function?
|
* expand: function?
|
||||||
|
|
Loading…
Reference in New Issue