@es-joy/jsoe 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +15 -0
- package/.eslintignore +7 -0
- package/.eslintrc.cjs +120 -0
- package/CHANGES.md +5 -0
- package/LICENSE-MIT.txt +22 -0
- package/README.md +82 -0
- package/package.json +101 -0
- package/rollup.config.js +29 -0
- package/server.js +25 -0
- package/src/deepEqual.js +72 -0
- package/src/formats/indexedDBKey.js +66 -0
- package/src/formats/json.js +64 -0
- package/src/formats/schemaAndArbitrary.js +20 -0
- package/src/formats/schemaOnly.js +529 -0
- package/src/formats/structuredCloning.js +372 -0
- package/src/formats.js +229 -0
- package/src/fundamentalTypes/BooleanObjectType.js +55 -0
- package/src/fundamentalTypes/NumberObjectType.js +41 -0
- package/src/fundamentalTypes/StringObjectType.js +37 -0
- package/src/fundamentalTypes/arrayReferenceType.js +203 -0
- package/src/fundamentalTypes/arrayType.js +898 -0
- package/src/fundamentalTypes/bigintType.js +53 -0
- package/src/fundamentalTypes/dateType.js +129 -0
- package/src/fundamentalTypes/nullType.js +33 -0
- package/src/fundamentalTypes/numberType.js +56 -0
- package/src/fundamentalTypes/objectReferenceType.js +51 -0
- package/src/fundamentalTypes/objectType.js +30 -0
- package/src/fundamentalTypes/regexpType.js +95 -0
- package/src/fundamentalTypes/sparseUndefinedType.js +43 -0
- package/src/fundamentalTypes/stringType.js +31 -0
- package/src/fundamentalTypes/undefinedType.js +37 -0
- package/src/index.js +7 -0
- package/src/subTypes/blobHTMLType.js +160 -0
- package/src/subTypes/falseType.js +42 -0
- package/src/subTypes/trueType.js +42 -0
- package/src/superTypes/InfinitiesSuperType.js +49 -0
- package/src/superTypes/SpecialNumberSuperType.js +62 -0
- package/src/typeChoices.js +125 -0
- package/src/types.js +665 -0
- package/src/utils/dialogs.js +115 -0
- package/src/utils/jsonPointer.js +89 -0
- package/src/utils/templateUtils.js +106 -0
- package/src/utils/types.js +6 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/* globals sceditor */
|
|
2
|
+
import {jml} from '../../node_modules/jamilih/dist/jml-es.js';
|
|
3
|
+
import {$e} from '../utils/templateUtils.js';
|
|
4
|
+
|
|
5
|
+
import dialogs from '../utils/dialogs.js';
|
|
6
|
+
import {isNullish} from '../utils/types.js';
|
|
7
|
+
|
|
8
|
+
const blobHTMLType = {
|
|
9
|
+
// Todo (low): Support other content-types
|
|
10
|
+
option: ['Blob (text/html)'],
|
|
11
|
+
stringRegex: /^data:text\/html(?:;base64)?,.*$/u,
|
|
12
|
+
valueMatch: (v) => v.type === 'text/html',
|
|
13
|
+
superType: 'blob',
|
|
14
|
+
toValue (s) {
|
|
15
|
+
// Todo (low): `Blob` untested; use https://stackoverflow.com/a/30407840/271577 ?
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param {string} dataURI
|
|
19
|
+
* @returns {Blob}
|
|
20
|
+
*/
|
|
21
|
+
function dataURIToBlob (dataURI) {
|
|
22
|
+
// Adapted from https://stackoverflow.com/a/12300351/271577
|
|
23
|
+
const [mimeInfo, bytes] = dataURI.split(',');
|
|
24
|
+
const [mimeString, encoding] = mimeInfo.split(':')[1].split(';');
|
|
25
|
+
let ab;
|
|
26
|
+
if (encoding === 'base64') {
|
|
27
|
+
const byteString = atob(bytes);
|
|
28
|
+
ab = new ArrayBuffer(byteString.length);
|
|
29
|
+
const ia = new Uint8Array(ab);
|
|
30
|
+
for (let i = 0; i < byteString.length; i++) {
|
|
31
|
+
// eslint-disable-next-line unicorn/prefer-code-point -- Only a byte
|
|
32
|
+
ia[i] = byteString.charCodeAt(i);
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
ab = bytes;
|
|
36
|
+
}
|
|
37
|
+
return new Blob([ab], {type: mimeString});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
value: dataURIToBlob(s)
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
/* istanbul ignore next -- No dupe keys, array refs, or validation */
|
|
44
|
+
getInput ({root}) {
|
|
45
|
+
return $e(root, 'textarea');
|
|
46
|
+
},
|
|
47
|
+
getValue (/* {root} */) {
|
|
48
|
+
return this.toValue(
|
|
49
|
+
'data:text/html,' + this.sceditorInstance.val()
|
|
50
|
+
// this.getInput({root}).value
|
|
51
|
+
).value;
|
|
52
|
+
},
|
|
53
|
+
loadBlob (value) {
|
|
54
|
+
const reader = new FileReader();
|
|
55
|
+
// eslint-disable-next-line promise/avoid-new
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
reader.addEventListener('loadend', () => {
|
|
58
|
+
resolve(reader);
|
|
59
|
+
});
|
|
60
|
+
reader.addEventListener(
|
|
61
|
+
'error',
|
|
62
|
+
/* istanbul ignore next -- How to simulate? */
|
|
63
|
+
(_e) => {
|
|
64
|
+
reject(reader.error);
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
reader.readAsText(value);
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
async setValue ({/* root, */ value}) {
|
|
71
|
+
const {result} = await this.loadBlob(value);
|
|
72
|
+
this.sceditorInstance.val(result);
|
|
73
|
+
// this.getInput({root}).value = result;
|
|
74
|
+
},
|
|
75
|
+
viewUI ({value}) {
|
|
76
|
+
let val;
|
|
77
|
+
const div = jml('div', {dataset: {type: 'blobHTML'}}, [
|
|
78
|
+
'HTML: ',
|
|
79
|
+
['button', {$on: {
|
|
80
|
+
click () {
|
|
81
|
+
dialogs.alert({message: ['div', [
|
|
82
|
+
'Source: ',
|
|
83
|
+
['textarea', {class: 'view-source'}, [val]]
|
|
84
|
+
]]});
|
|
85
|
+
}
|
|
86
|
+
}}, ['View source']]
|
|
87
|
+
]);
|
|
88
|
+
// eslint-disable-next-line promise/prefer-await-to-then
|
|
89
|
+
this.loadBlob(value).then(({
|
|
90
|
+
result
|
|
91
|
+
}) => {
|
|
92
|
+
val = result;
|
|
93
|
+
jml('iframe', {
|
|
94
|
+
sandbox: '',
|
|
95
|
+
srcdoc: val
|
|
96
|
+
}, div);
|
|
97
|
+
return undefined;
|
|
98
|
+
// eslint-disable-next-line promise/prefer-await-to-then
|
|
99
|
+
}).catch(
|
|
100
|
+
/* istanbul ignore next -- How to simulate? */
|
|
101
|
+
() => {
|
|
102
|
+
// Todo: Show an error message?
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
return [div];
|
|
106
|
+
// return ['i', [`data:text/html,${value}`]];
|
|
107
|
+
},
|
|
108
|
+
editUI ({typeNamespace, value}) {
|
|
109
|
+
const textarea = jml('textarea', {name: `${typeNamespace}-blobHTML`});
|
|
110
|
+
const root = jml('div', {dataset: {type: 'blobHTML'}}, [
|
|
111
|
+
textarea
|
|
112
|
+
]);
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
// Push onto these: https://www.sceditor.com/documentation/formats/xhtml/
|
|
115
|
+
// sceditor.formats.xhtml.converters array
|
|
116
|
+
// sceditor.formats.xhtml.allowedAttribs object
|
|
117
|
+
// sceditor.formats.xhtml.disallowedAttribs object
|
|
118
|
+
// sceditor.formats.xhtml.allowedTags array
|
|
119
|
+
// sceditor.formats.xhtml.disallowedTags array
|
|
120
|
+
// console.log(
|
|
121
|
+
// 'sceditor.formats.xhtml.converters',
|
|
122
|
+
// sceditor.formats.xhtml.converters.map((c) => Object.keys(c.tags))
|
|
123
|
+
// );
|
|
124
|
+
// console.log(
|
|
125
|
+
// 'sceditor.formats.xhtml.converters',
|
|
126
|
+
// sceditor.formats.xhtml.converters.map((c) => c.conv.toString())
|
|
127
|
+
// );
|
|
128
|
+
sceditor.create(textarea, {
|
|
129
|
+
// Todo (low): "dragdrop" plugin is for file handling (could
|
|
130
|
+
// treat as Blobs but would need to reference them)
|
|
131
|
+
// "autoyoutube" plugin may be ok
|
|
132
|
+
// toolbarExclude (default of `null` doesn't exclude any)
|
|
133
|
+
// Must also add languages files (after editor files but
|
|
134
|
+
// before editor creation)
|
|
135
|
+
// locale: 'en',
|
|
136
|
+
// emoticons: {}, icons, //
|
|
137
|
+
// width, height, resizeMinWidth, resizeMinHeight, autoExpand: true,
|
|
138
|
+
// autofocus, autofocusEnd
|
|
139
|
+
// id, spellcheck, toolbarContainer, dropDownCss, fonts, colors
|
|
140
|
+
// disableBlockRemove, parserOptions
|
|
141
|
+
width: '1000px',
|
|
142
|
+
height: '225px',
|
|
143
|
+
// auto-updates original textbox when the editor loses focus
|
|
144
|
+
autoUpdate: true,
|
|
145
|
+
resizeMaxHeight: -1,
|
|
146
|
+
resizeMaxWidth: -1,
|
|
147
|
+
plugins: 'xhtml,plaintext,undo',
|
|
148
|
+
emoticonsRoot: 'node_modules/sceditor/',
|
|
149
|
+
style: 'node_modules/sceditor/minified/themes/content/default.min.css'
|
|
150
|
+
});
|
|
151
|
+
this.sceditorInstance = sceditor.instance(textarea);
|
|
152
|
+
if (!isNullish(value)) {
|
|
153
|
+
this.setValue({root, value});
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
return [root];
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export default blobHTMLType;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {TypeObject}
|
|
5
|
+
*/
|
|
6
|
+
const falseType = {
|
|
7
|
+
option: ['Boolean (false)', {value: 'false'}],
|
|
8
|
+
stringRegex: /^false$/u,
|
|
9
|
+
toValue: () => ({value: false}),
|
|
10
|
+
valueMatch: (v) => v === false,
|
|
11
|
+
superType: 'boolean',
|
|
12
|
+
getValue: () => false,
|
|
13
|
+
viewUI () {
|
|
14
|
+
return ['i', {dataset: {type: 'false'}}, ['false']];
|
|
15
|
+
},
|
|
16
|
+
ct: 0,
|
|
17
|
+
/* istanbul ignore next -- No dupe keys, array refs, or validation */
|
|
18
|
+
getInput ({root}) {
|
|
19
|
+
return $e(root, 'input');
|
|
20
|
+
},
|
|
21
|
+
editUI ({typeNamespace}) {
|
|
22
|
+
this.ct++;
|
|
23
|
+
return ['div', {dataset: {type: 'false'}}, [
|
|
24
|
+
['label', [
|
|
25
|
+
'True',
|
|
26
|
+
['input', {
|
|
27
|
+
type: 'radio', name: `${typeNamespace}-false${this.ct}`,
|
|
28
|
+
value: 'true', disabled: true
|
|
29
|
+
}]
|
|
30
|
+
]],
|
|
31
|
+
['label', [
|
|
32
|
+
'False',
|
|
33
|
+
['input', {
|
|
34
|
+
type: 'radio', name: `${typeNamespace}-false${this.ct}`,
|
|
35
|
+
value: 'false', checked: true, disabled: true
|
|
36
|
+
}]
|
|
37
|
+
]]
|
|
38
|
+
]];
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default falseType;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {TypeObject}
|
|
5
|
+
*/
|
|
6
|
+
const trueType = {
|
|
7
|
+
option: ['Boolean (true)', {value: 'true'}],
|
|
8
|
+
stringRegex: /^true$/u,
|
|
9
|
+
toValue: (_s) => ({value: true}),
|
|
10
|
+
valueMatch: (v) => v === true,
|
|
11
|
+
superType: 'boolean',
|
|
12
|
+
getValue: () => true,
|
|
13
|
+
viewUI () {
|
|
14
|
+
return ['i', {dataset: {type: 'true'}}, ['true']];
|
|
15
|
+
},
|
|
16
|
+
ct: 0,
|
|
17
|
+
/* istanbul ignore next -- No dupe keys, array refs, or validation */
|
|
18
|
+
getInput ({root}) {
|
|
19
|
+
return $e(root, 'input');
|
|
20
|
+
},
|
|
21
|
+
editUI ({typeNamespace}) {
|
|
22
|
+
this.ct++;
|
|
23
|
+
return ['div', {dataset: {type: 'true'}}, [
|
|
24
|
+
['label', [
|
|
25
|
+
'True',
|
|
26
|
+
['input', {
|
|
27
|
+
type: 'radio', name: `${typeNamespace}-true${this.ct}`,
|
|
28
|
+
value: 'true', checked: true, disabled: true
|
|
29
|
+
}]
|
|
30
|
+
]],
|
|
31
|
+
['label', [
|
|
32
|
+
'False',
|
|
33
|
+
['input', {
|
|
34
|
+
type: 'radio', name: `${typeNamespace}-true${this.ct}`,
|
|
35
|
+
value: 'false', disabled: true
|
|
36
|
+
}]
|
|
37
|
+
]]
|
|
38
|
+
]];
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default trueType;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {SuperTypeObject}
|
|
5
|
+
*/
|
|
6
|
+
const InfinitiesSuperType = {
|
|
7
|
+
option: ['Infinities', {title: '`Infinity`, `-Infinity`'}],
|
|
8
|
+
childTypes: ['infinity', 'negativeInfinity'],
|
|
9
|
+
stringRegex: /^-?Infinity$/u,
|
|
10
|
+
toValue (s) {
|
|
11
|
+
return {
|
|
12
|
+
value: s === 'Infinity'
|
|
13
|
+
? Number.POSITIVE_INFINITY
|
|
14
|
+
: Number.NEGATIVE_INFINITY
|
|
15
|
+
};
|
|
16
|
+
},
|
|
17
|
+
getSelect ({root}) {
|
|
18
|
+
return $e(root, 'select');
|
|
19
|
+
},
|
|
20
|
+
getValue ({root}) {
|
|
21
|
+
return this.toValue(this.getSelect({root}).value).value;
|
|
22
|
+
},
|
|
23
|
+
setValue ({root, value}) {
|
|
24
|
+
this.getSelect({root}).value = String(value);
|
|
25
|
+
},
|
|
26
|
+
viewUI ({value}) {
|
|
27
|
+
return ['i', {dataset: {type: 'Infinities'}}, [String(value)]];
|
|
28
|
+
},
|
|
29
|
+
getInput ({root}) {
|
|
30
|
+
return $e(root, 'select');
|
|
31
|
+
},
|
|
32
|
+
editUI ({typeNamespace, value = Number.POSITIVE_INFINITY}) {
|
|
33
|
+
return ['div', {dataset: {type: 'Infinities'}}, [
|
|
34
|
+
['label', [
|
|
35
|
+
'Infinities: ',
|
|
36
|
+
['select', {name: `${typeNamespace}-Infinities`}, [
|
|
37
|
+
['option', {
|
|
38
|
+
value: 'Infinity', selected: value === Number.POSITIVE_INFINITY
|
|
39
|
+
}, ['Infinity']],
|
|
40
|
+
['option', {
|
|
41
|
+
value: '-Infinity', selected: value === Number.NEGATIVE_INFINITY
|
|
42
|
+
}, ['-Infinity']]
|
|
43
|
+
]]
|
|
44
|
+
]]
|
|
45
|
+
]];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default InfinitiesSuperType;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {$e} from '../utils/templateUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {TypeObject} SuperTypeObject
|
|
5
|
+
* @property {string[]} childTypes
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @type {SuperTypeObject}
|
|
10
|
+
*/
|
|
11
|
+
const SpecialNumberSuperType = {
|
|
12
|
+
option: ['SpecialNumber', {title: '`NaN`, `Infinity`, `-Infinity`'}],
|
|
13
|
+
childTypes: ['infinity', 'negativeInfinity', 'nan'],
|
|
14
|
+
stringRegex: /^(?:NaN|-?Infinity)$/u,
|
|
15
|
+
toValue (s) {
|
|
16
|
+
return {
|
|
17
|
+
value: s === 'NaN'
|
|
18
|
+
? Number.NaN
|
|
19
|
+
: s === 'Infinity'
|
|
20
|
+
? Number.POSITIVE_INFINITY
|
|
21
|
+
: Number.NEGATIVE_INFINITY
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
getSelect ({root}) {
|
|
25
|
+
return $e(root, 'select');
|
|
26
|
+
},
|
|
27
|
+
/* istanbul ignore next -- No dupe keys, array refs, or validation */
|
|
28
|
+
getInput ({root}) {
|
|
29
|
+
return $e(root, 'select');
|
|
30
|
+
},
|
|
31
|
+
getValue ({root}) {
|
|
32
|
+
return this.toValue(this.getSelect({root}).value).value;
|
|
33
|
+
},
|
|
34
|
+
setValue ({root, value}) {
|
|
35
|
+
this.getSelect({root}).value = String(value);
|
|
36
|
+
},
|
|
37
|
+
viewUI ({value}) {
|
|
38
|
+
return ['i', {dataset: {type: 'SpecialNumber'}}, [String(value)]];
|
|
39
|
+
},
|
|
40
|
+
editUI ({typeNamespace, value = Number.NaN}) {
|
|
41
|
+
return ['div', {dataset: {type: 'SpecialNumber'}}, [
|
|
42
|
+
['label', [
|
|
43
|
+
'Special number: ',
|
|
44
|
+
['select', {
|
|
45
|
+
name: `${typeNamespace}-SpecialNumber`
|
|
46
|
+
}, [
|
|
47
|
+
['option', {
|
|
48
|
+
value: 'NaN', selected: Number.isNaN(value)
|
|
49
|
+
}, ['NaN']],
|
|
50
|
+
['option', {
|
|
51
|
+
value: 'Infinity', selected: value === Number.POSITIVE_INFINITY
|
|
52
|
+
}, ['Infinity']],
|
|
53
|
+
['option', {
|
|
54
|
+
value: '-Infinity', selected: value === Number.NEGATIVE_INFINITY
|
|
55
|
+
}, ['-Infinity']]
|
|
56
|
+
]]
|
|
57
|
+
]]
|
|
58
|
+
]];
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export default SpecialNumberSuperType;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import {jml} from '../node_modules/jamilih/dist/jml-es.js';
|
|
2
|
+
import Formats from './formats.js';
|
|
3
|
+
import {$e, DOM} from './utils/templateUtils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @todo Compose from format metadata, so can make user customizable.
|
|
7
|
+
* @param {object} cfg
|
|
8
|
+
* @param {string} cfg.schema
|
|
9
|
+
* @param {boolean} cfg.hasKeyPath
|
|
10
|
+
* @returns {JamilihArray[]}
|
|
11
|
+
*/
|
|
12
|
+
export const getFormatAndSchemaChoices = ({schema, hasKeyPath}) => {
|
|
13
|
+
const hasSchema = typeof schema === 'string';
|
|
14
|
+
return [
|
|
15
|
+
['JSON only', {value: 'json'}],
|
|
16
|
+
...(hasKeyPath
|
|
17
|
+
? []
|
|
18
|
+
: [['IndexedDB key', {value: 'indexedDBKey'}]]),
|
|
19
|
+
['Structured Clone (via Typeson JSON)', {
|
|
20
|
+
value: 'structuredCloning', selected: !hasSchema
|
|
21
|
+
}]
|
|
22
|
+
/* schema:
|
|
23
|
+
...(hasSchema
|
|
24
|
+
? [
|
|
25
|
+
[`Schema + arbitrary: ${schema}`, {
|
|
26
|
+
value: 'schemaAndArbitrary',
|
|
27
|
+
dataset: {schema}
|
|
28
|
+
}],
|
|
29
|
+
[`Schema only: ${schema}`, {
|
|
30
|
+
value: 'schemaOnly',
|
|
31
|
+
dataset: {schema},
|
|
32
|
+
selected: hasSchema
|
|
33
|
+
}]
|
|
34
|
+
]
|
|
35
|
+
: []
|
|
36
|
+
)
|
|
37
|
+
*/
|
|
38
|
+
/*
|
|
39
|
+
// This can be supported for editing only
|
|
40
|
+
['Arbitrary (Non-Typeson-serializable will be read-only)', {
|
|
41
|
+
value: 'arbitrary',
|
|
42
|
+
title: 'Any value that the typeson-registry supports ' +
|
|
43
|
+
'for structured cloning'
|
|
44
|
+
}]
|
|
45
|
+
*/
|
|
46
|
+
].map(([optText, optAtts]) => {
|
|
47
|
+
return ['option', optAtts, [optText]];
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Builds a selector and container for types.
|
|
53
|
+
* @param {object} cfg
|
|
54
|
+
* @param {string} cfg.schema The schema name
|
|
55
|
+
* @param {object} cfg.schemaContent The schema content
|
|
56
|
+
* @param {boolean} cfg.hasValue If false and `hasKeyPath` is `true`,
|
|
57
|
+
* will initialize with an object
|
|
58
|
+
* @param {boolean} cfg.singleValue
|
|
59
|
+
* @param {boolean} cfg.hasKeyPath
|
|
60
|
+
* @param {string} cfg.typeNamespace
|
|
61
|
+
* @returns {{
|
|
62
|
+
* mainTypeChoices: HTMLSelectElement,
|
|
63
|
+
* typesHolder: HTMLDivElement
|
|
64
|
+
* }} The selector for types and the container for them
|
|
65
|
+
*/
|
|
66
|
+
function typeChoices ({
|
|
67
|
+
schema,
|
|
68
|
+
schemaContent,
|
|
69
|
+
hasValue,
|
|
70
|
+
singleValue,
|
|
71
|
+
hasKeyPath,
|
|
72
|
+
typeNamespace
|
|
73
|
+
}) {
|
|
74
|
+
const mainTypeChoices = jml('select', {
|
|
75
|
+
class: 'mainTypeChoices',
|
|
76
|
+
hidden: singleValue,
|
|
77
|
+
// is: 'main-type-choices',
|
|
78
|
+
$custom: {
|
|
79
|
+
$setFormat (valueFormat) {
|
|
80
|
+
this.value = valueFormat;
|
|
81
|
+
this.$buildTypeChoices();
|
|
82
|
+
},
|
|
83
|
+
$buildTypeChoices () {
|
|
84
|
+
const typesHolder = this.nextElementSibling;
|
|
85
|
+
DOM.removeChildren(typesHolder);
|
|
86
|
+
jml({'#': Formats.buildTypeChoices({
|
|
87
|
+
topRoot: $e(typesHolder, 'div[data-type]'),
|
|
88
|
+
resultType: 'both',
|
|
89
|
+
format: this.value,
|
|
90
|
+
typeNamespace,
|
|
91
|
+
requireObject: hasKeyPath,
|
|
92
|
+
objectHasValue: hasValue,
|
|
93
|
+
schema,
|
|
94
|
+
schemaContent
|
|
95
|
+
})}, typesHolder);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
$on: {change () {
|
|
99
|
+
this.$buildTypeChoices();
|
|
100
|
+
}}
|
|
101
|
+
}, getFormatAndSchemaChoices({schema, hasKeyPath}));
|
|
102
|
+
const typesHolder = jml('div', {class: 'typesHolder', $custom: {
|
|
103
|
+
$getTypeRoot () {
|
|
104
|
+
return $e(this, 'div[data-type]');
|
|
105
|
+
},
|
|
106
|
+
$getTypeSelect () {
|
|
107
|
+
return $e(this, `.typeChoices-${typeNamespace}`);
|
|
108
|
+
}
|
|
109
|
+
}});
|
|
110
|
+
|
|
111
|
+
jml({'#': Formats.buildTypeChoices({
|
|
112
|
+
resultType: 'both',
|
|
113
|
+
topRoot: $e(typesHolder, 'div[data-type]'),
|
|
114
|
+
format: 'structuredCloning',
|
|
115
|
+
typeNamespace,
|
|
116
|
+
requireObject: hasKeyPath,
|
|
117
|
+
objectHasValue: hasValue,
|
|
118
|
+
schema,
|
|
119
|
+
schemaContent
|
|
120
|
+
})}, typesHolder);
|
|
121
|
+
|
|
122
|
+
return {mainTypeChoices, typesHolder};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export default typeChoices;
|