@es-joy/jsoe 0.1.0 → 0.2.0
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/.eslintrc.cjs +1 -1
- package/CHANGES.md +8 -0
- package/README.md +2 -2
- package/demo/index.html +1 -0
- package/demo/index.js +147 -14
- package/index.html +10 -0
- package/package.json +1 -1
- package/src/formatAndTypeChoices.js +245 -0
- package/src/formats/indexedDBKey.js +1 -1
- package/src/formats/json.js +1 -1
- package/src/formats/schemaAndArbitrary.js +1 -1
- package/src/formats/schemaOnly.js +1 -1
- package/src/formats/structuredCloning.js +4 -22
- package/src/formats.js +17 -206
- package/src/fundamentalTypes/BooleanObjectType.js +1 -1
- package/src/fundamentalTypes/NumberObjectType.js +1 -1
- package/src/fundamentalTypes/StringObjectType.js +1 -1
- package/src/fundamentalTypes/arrayReferenceType.js +1 -1
- package/src/fundamentalTypes/arrayType.js +3 -3
- package/src/fundamentalTypes/bigintType.js +1 -1
- package/src/fundamentalTypes/dateType.js +1 -1
- package/src/fundamentalTypes/nullType.js +1 -1
- package/src/fundamentalTypes/numberType.js +1 -1
- package/src/fundamentalTypes/objectReferenceType.js +1 -1
- package/src/fundamentalTypes/objectType.js +1 -1
- package/src/fundamentalTypes/regexpType.js +1 -1
- package/src/fundamentalTypes/sparseUndefinedType.js +1 -1
- package/src/fundamentalTypes/stringType.js +1 -1
- package/src/fundamentalTypes/undefinedType.js +1 -1
- package/src/index.js +7 -2
- package/src/jsoe.css +58 -0
- package/src/subTypes/falseType.js +1 -1
- package/src/subTypes/trueType.js +1 -1
- package/src/typeChoices.js +229 -117
- package/src/types.js +53 -35
package/src/typeChoices.js
CHANGED
|
@@ -1,137 +1,249 @@
|
|
|
1
|
+
import Formats, {getControlsForFormatAndValue} from './formats.js';
|
|
2
|
+
import Types from './types.js';
|
|
1
3
|
import {jml} from '../vendor/jamilih/dist/jml-es.js';
|
|
2
|
-
|
|
4
|
+
|
|
3
5
|
import {$e, DOM} from './utils/templateUtils.js';
|
|
6
|
+
import dialogs from './utils/dialogs.js';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @
|
|
8
|
-
* @param {object} cfg
|
|
9
|
-
* @param {string} [cfg.schema] (NOT IN USE)
|
|
10
|
-
* @param {boolean} [cfg.hasKeyPath] Whether or not a key path is expected; if
|
|
11
|
-
* true, an indexedDB key is not allowed here as a key does not support
|
|
12
|
-
* the object type which is needed for a key path.
|
|
13
|
-
* @returns {DocumentFragment}
|
|
9
|
+
* An arbitrary Structured Clone, JSON, etc. value.
|
|
10
|
+
* @typedef {any} StructuredCloneValue
|
|
14
11
|
*/
|
|
15
|
-
export const getFormatAndSchemaChoices = ({schema, hasKeyPath} = {}) => {
|
|
16
|
-
const hasSchema = typeof schema === 'string';
|
|
17
|
-
return [
|
|
18
|
-
['JSON only', {value: 'json'}],
|
|
19
|
-
...(hasKeyPath
|
|
20
|
-
? []
|
|
21
|
-
: [['IndexedDB key', {value: 'indexedDBKey'}]]),
|
|
22
|
-
['Structured Clone (via Typeson JSON)', {
|
|
23
|
-
value: 'structuredCloning', selected: !hasSchema
|
|
24
|
-
}]
|
|
25
|
-
/* schema:
|
|
26
|
-
...(hasSchema
|
|
27
|
-
? [
|
|
28
|
-
[`Schema + arbitrary: ${schema}`, {
|
|
29
|
-
value: 'schemaAndArbitrary',
|
|
30
|
-
dataset: {schema}
|
|
31
|
-
}],
|
|
32
|
-
[`Schema only: ${schema}`, {
|
|
33
|
-
value: 'schemaOnly',
|
|
34
|
-
dataset: {schema},
|
|
35
|
-
selected: hasSchema
|
|
36
|
-
}]
|
|
37
|
-
]
|
|
38
|
-
: []
|
|
39
|
-
)
|
|
40
|
-
*/
|
|
41
|
-
/*
|
|
42
|
-
// This can be supported for editing only
|
|
43
|
-
['Arbitrary (Non-Typeson-serializable will be read-only)', {
|
|
44
|
-
value: 'arbitrary',
|
|
45
|
-
title: 'Any value that the typeson-registry supports ' +
|
|
46
|
-
'for structured cloning'
|
|
47
|
-
}]
|
|
48
|
-
*/
|
|
49
|
-
].map(([optText, optAtts]) => {
|
|
50
|
-
return jml('option', optAtts, [optText]);
|
|
51
|
-
}).reduce((frag, option) => {
|
|
52
|
-
frag.append(option);
|
|
53
|
-
return frag;
|
|
54
|
-
}, document.createDocumentFragment());
|
|
55
|
-
};
|
|
56
12
|
|
|
57
13
|
/**
|
|
58
|
-
*
|
|
14
|
+
* @callback BuildTypeChoices
|
|
59
15
|
* @param {object} cfg
|
|
60
|
-
* @param {string}
|
|
61
|
-
* @param {
|
|
62
|
-
* @param {
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* @param {
|
|
66
|
-
* @param {boolean}
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* @
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
*
|
|
76
|
-
* ]} The selector for types and the container for them. Both should be
|
|
77
|
-
* added to the page.
|
|
16
|
+
* @param {string} cfg.format
|
|
17
|
+
* @param {string} cfg.typeNamespace
|
|
18
|
+
* @param {StructuredCloneValue} cfg.value
|
|
19
|
+
* @param {boolean} [cfg.setValue=false]
|
|
20
|
+
* @param {string} cfg.state
|
|
21
|
+
* @param {string} cfg.keySelectClass
|
|
22
|
+
* @param {boolean} cfg.requireObject
|
|
23
|
+
* @param {boolean} cfg.objectHasValue
|
|
24
|
+
* @param {RootElement} cfg.topRoot Always a `div` element?
|
|
25
|
+
* @param {string} cfg.schema Schema name
|
|
26
|
+
* @param {string} cfg.schemaContent Schema contents
|
|
27
|
+
* @returns {[select: Element, typeContainer: Element]}
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @type {BuildTypeChoices}
|
|
78
32
|
*/
|
|
79
|
-
|
|
33
|
+
export const buildTypeChoices = ({
|
|
34
|
+
format,
|
|
35
|
+
typeNamespace,
|
|
36
|
+
value,
|
|
37
|
+
setValue = false,
|
|
38
|
+
state,
|
|
39
|
+
// itemIndex = 0,
|
|
40
|
+
keySelectClass,
|
|
41
|
+
requireObject,
|
|
42
|
+
objectHasValue,
|
|
43
|
+
topRoot,
|
|
80
44
|
schema,
|
|
81
|
-
schemaContent
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
45
|
+
schemaContent
|
|
46
|
+
}) => {
|
|
47
|
+
// console.log('format', format, 'state', state, 'path', typeNamespace);
|
|
48
|
+
const typeOptions = requireObject
|
|
49
|
+
? [Types.getOptionForType('object')]
|
|
50
|
+
: Types.getTypeOptionsForFormatAndState(format, state);
|
|
51
|
+
|
|
52
|
+
let editUI;
|
|
53
|
+
const sel = jml('select', {
|
|
54
|
+
hidden: requireObject,
|
|
55
|
+
class: `typeChoices-${typeNamespace}${keySelectClass
|
|
56
|
+
? ' ' + keySelectClass
|
|
57
|
+
: ''
|
|
58
|
+
}`,
|
|
59
|
+
// is: 'type-choices',
|
|
91
60
|
$custom: {
|
|
92
|
-
$
|
|
93
|
-
this.value =
|
|
94
|
-
this.$
|
|
61
|
+
$setType ({type, baseValue, bringIntoFocus}) {
|
|
62
|
+
this.value = type;
|
|
63
|
+
this.$setStyles();
|
|
64
|
+
this.$addAndValidateEditUI({baseValue, bringIntoFocus});
|
|
65
|
+
},
|
|
66
|
+
$setTypeNoEditUI ({type}) {
|
|
67
|
+
this.value = type;
|
|
68
|
+
this.$setStyles();
|
|
69
|
+
},
|
|
70
|
+
$setStyles () {
|
|
71
|
+
const {value: type} = this;
|
|
72
|
+
this.dataset.type = type; // Used for styling
|
|
73
|
+
const parEl = this.parentElement;
|
|
74
|
+
if (parEl.nodeName.toLowerCase() === 'fieldset') {
|
|
75
|
+
parEl.dataset.type = type;
|
|
76
|
+
DOM.filterChildElements(parEl, 'legend').forEach((legend) => {
|
|
77
|
+
legend.dataset.type = type;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
$getTypeRoot () {
|
|
82
|
+
const container = this.$getContainer();
|
|
83
|
+
/* istanbul ignore if -- How to replicate? */
|
|
84
|
+
if (!container) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return $e(container, 'div[data-type]');
|
|
95
88
|
},
|
|
96
|
-
$
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
89
|
+
$addAndValidateEditUI ({baseValue, bringIntoFocus} = {}) {
|
|
90
|
+
const {value: type} = this;
|
|
91
|
+
|
|
92
|
+
if (!type) { return; }
|
|
93
|
+
let topRoot = this.$getTopRoot();
|
|
94
|
+
|
|
95
|
+
// Todo (low): Try to avoid need for `baseValue`
|
|
96
|
+
// (needed by arrayNonindexKeys for setting an array
|
|
97
|
+
// length and avoiding errors); could set all
|
|
98
|
+
// values through here?
|
|
99
|
+
editUI = Types.getUIForModeAndType({
|
|
100
|
+
readonly: false,
|
|
102
101
|
typeNamespace,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
type,
|
|
103
|
+
bringIntoFocus,
|
|
104
|
+
hasValue: type === 'arrayNonindexKeys' && baseValue,
|
|
105
|
+
value: baseValue,
|
|
106
|
+
buildTypeChoices,
|
|
107
|
+
format,
|
|
108
|
+
topRoot
|
|
109
|
+
});
|
|
110
|
+
this.$addEditUI({editUI});
|
|
111
|
+
this.$validate();
|
|
112
|
+
topRoot = this.$getTopRoot(); // May be existing now
|
|
113
|
+
// Needed; Array/object ref somewhere could now be valid or invalid
|
|
114
|
+
Types.validateAllReferences({topRoot});
|
|
115
|
+
},
|
|
116
|
+
$addTypeAndEditUI ({type, editUI}) {
|
|
117
|
+
this.$setTypeNoEditUI({type});
|
|
118
|
+
this.$addEditUI({editUI});
|
|
119
|
+
},
|
|
120
|
+
$addEditUI ({editUI}) {
|
|
121
|
+
const container = this.$getContainer();
|
|
122
|
+
DOM.removeChildren(container);
|
|
123
|
+
jml(editUI, container);
|
|
124
|
+
},
|
|
125
|
+
$getContainer () {
|
|
126
|
+
return this.nextElementSibling;
|
|
127
|
+
},
|
|
128
|
+
$getTopRoot () {
|
|
129
|
+
return topRoot || this.$getTypeRoot();
|
|
130
|
+
},
|
|
131
|
+
$validate () {
|
|
132
|
+
const {value: type} = this;
|
|
133
|
+
const container = this.$getContainer();
|
|
134
|
+
if (!container.firstElementChild) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const editUI = container.firstElementChild;
|
|
138
|
+
return Types.validate({
|
|
139
|
+
type, root: editUI, topRoot: this.$getTopRoot()
|
|
140
|
+
});
|
|
108
141
|
}
|
|
109
142
|
},
|
|
110
|
-
$on: {change () {
|
|
111
|
-
|
|
143
|
+
$on: {change (e) {
|
|
144
|
+
// We don't want form `onchange` to run `$checkForKeyDuplicates`
|
|
145
|
+
// again (through `addAndValidateEditUI`->`validateAllReferences`)
|
|
146
|
+
e.stopPropagation();
|
|
147
|
+
this.$addAndValidateEditUI();
|
|
148
|
+
this.$setStyles();
|
|
112
149
|
}}
|
|
113
|
-
}, [
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
150
|
+
}, [
|
|
151
|
+
['option', {value: ''}, [
|
|
152
|
+
'(Choose a type)'
|
|
153
|
+
]],
|
|
154
|
+
...typeOptions.map(
|
|
155
|
+
([optText, optAtts]) => [
|
|
156
|
+
'option',
|
|
157
|
+
optAtts ||
|
|
158
|
+
/* istanbul ignore next -- Should always have atts */
|
|
159
|
+
{},
|
|
160
|
+
[optText]
|
|
161
|
+
]
|
|
162
|
+
)
|
|
163
|
+
]);
|
|
164
|
+
if (setValue || (requireObject && !objectHasValue)) {
|
|
165
|
+
setTimeout(async () => {
|
|
166
|
+
if (!setValue) { // if (requireObject && !objectHasValue) {
|
|
167
|
+
// Todo (low): We could auto-populate keypath if has
|
|
168
|
+
// keypath (and we probably also only want if
|
|
169
|
+
// not autoincrement)
|
|
170
|
+
value = {};
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const rootEditUI = await Formats.availableFormats[format].iterate(
|
|
174
|
+
value,
|
|
175
|
+
{
|
|
176
|
+
readonly: false,
|
|
177
|
+
typeNamespace,
|
|
178
|
+
schema,
|
|
179
|
+
schemaContent
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
const type = Types.getTypeForRoot(rootEditUI);
|
|
183
|
+
sel.$addTypeAndEditUI({type, editUI: rootEditUI});
|
|
184
|
+
} catch (err) {
|
|
185
|
+
/* istanbul ignore next -- At least some errors handled earlier */
|
|
186
|
+
dialogs.alert({
|
|
187
|
+
message: 'The object to be added had types not supported ' +
|
|
188
|
+
'by the current format.'
|
|
189
|
+
});
|
|
190
|
+
/* istanbul ignore next -- How to trigger? */
|
|
191
|
+
console.log('err', err);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const typeContainer = jml('div', {class: 'typeContainer'});
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
domArray: [
|
|
200
|
+
sel,
|
|
201
|
+
typeContainer
|
|
202
|
+
],
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @param {import('./types.js').StateObject} [stateObj] Will
|
|
206
|
+
* auto-set `typeNamespace` and `format`
|
|
207
|
+
* @param {string} [currentPath]
|
|
208
|
+
* @returns {StructuredCloneValue}
|
|
209
|
+
*/
|
|
210
|
+
getValue (stateObj, currentPath) {
|
|
211
|
+
const root = $e(typeContainer, 'div[data-type]');
|
|
212
|
+
return Types.getValueForRoot(root, {
|
|
213
|
+
typeNamespace,
|
|
214
|
+
format,
|
|
215
|
+
...stateObj
|
|
216
|
+
}, currentPath);
|
|
117
217
|
},
|
|
118
|
-
$getTypeSelect () {
|
|
119
|
-
return $e(this, `.typeChoices-${typeNamespace}`);
|
|
120
|
-
}
|
|
121
|
-
}});
|
|
122
218
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
schema,
|
|
131
|
-
schemaContent
|
|
132
|
-
})}, typesHolder);
|
|
219
|
+
/**
|
|
220
|
+
* @returns {string|undefined}
|
|
221
|
+
*/
|
|
222
|
+
getType () {
|
|
223
|
+
const root = $e(typeContainer, 'div[data-type]');
|
|
224
|
+
return Types.getTypeForRoot(root);
|
|
225
|
+
},
|
|
133
226
|
|
|
134
|
-
|
|
135
|
-
}
|
|
227
|
+
/**
|
|
228
|
+
* @returns {boolean}
|
|
229
|
+
*/
|
|
230
|
+
validValuesSet () {
|
|
231
|
+
const root = $e(typeContainer, 'div[data-type]');
|
|
232
|
+
const form = root.closest('form');
|
|
233
|
+
return Types.validValuesSet({form, typeNamespace});
|
|
234
|
+
},
|
|
136
235
|
|
|
137
|
-
|
|
236
|
+
/**
|
|
237
|
+
* @param {StructuredCloneValue} value
|
|
238
|
+
* @param {import('./types.js').StateObject} stateObj
|
|
239
|
+
* @returns {Promise<void>}
|
|
240
|
+
*/
|
|
241
|
+
async setValue (value, stateObj) {
|
|
242
|
+
const rootEditUI = await getControlsForFormatAndValue(
|
|
243
|
+
format, value, stateObj
|
|
244
|
+
);
|
|
245
|
+
const type = Types.getTypeForRoot(rootEditUI);
|
|
246
|
+
sel.$addTypeAndEditUI({type, editUI: rootEditUI});
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
};
|
package/src/types.js
CHANGED
|
@@ -29,6 +29,7 @@ import InfinitiesSuperType from './superTypes/InfinitiesSuperType.js';
|
|
|
29
29
|
import SpecialNumberSuperType from './superTypes/SpecialNumberSuperType.js';
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
|
+
* Utility to retrieve the property value given a legend element.
|
|
32
33
|
* @param {HTMLLegendElement} legend
|
|
33
34
|
* @returns {string}
|
|
34
35
|
*/
|
|
@@ -54,42 +55,34 @@ const Types = {};
|
|
|
54
55
|
* present, use `stringRegex`
|
|
55
56
|
* @property {RegExp} [stringRegexEnd] Used for string parsing. If not
|
|
56
57
|
* present, use `stringRegex`
|
|
57
|
-
* @property {
|
|
58
|
-
*
|
|
59
|
-
* } [valueMatch] Function to check whether this subtype matches
|
|
58
|
+
* @property {(ArbitraryValue) => boolean} [valueMatch] Function to
|
|
59
|
+
* check whether this subtype matches
|
|
60
60
|
* @property {string} [superType] The greater fundamental type to which
|
|
61
61
|
* the type belongs
|
|
62
62
|
* @property {(s: string) => ArbitraryValue} toValue Converts from
|
|
63
63
|
* string to value. May use `stringRegex` to find components.
|
|
64
|
-
* @property {
|
|
65
|
-
*
|
|
64
|
+
* @property {(info: {root?: HTMLDivElement}) =>
|
|
65
|
+
* ArbitraryValue
|
|
66
66
|
* } getValue Gets the value for the type
|
|
67
|
-
* @property {
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* @property {
|
|
87
|
-
* (info: {root: HTMLDivElement}) =>
|
|
88
|
-
* HTMLInputElement|HTMLTextareaElement|HTMLSelectElement
|
|
89
|
-
* } getInput Gets the form control (with `value`)
|
|
90
|
-
* @property {
|
|
91
|
-
* (path: string, value: ArbitraryValue) => ArbitraryValue
|
|
92
|
-
* } [resolveReference] Gets the reference. For array and object
|
|
67
|
+
* @property {(info: {root?: HTMLDivElement}) => void} [setValue] Should set
|
|
68
|
+
* the value of the form's `getInput` element
|
|
69
|
+
* @property {(info: {
|
|
70
|
+
* value?: ArbitraryValue,
|
|
71
|
+
* typeNamespace?: string,
|
|
72
|
+
* type?: string,
|
|
73
|
+
* topRoot?: HTMLDivElement,
|
|
74
|
+
* resultType?: "keys"|"values"|"both",
|
|
75
|
+
* format?: string
|
|
76
|
+
* }) => JamilihArray} viewUI
|
|
77
|
+
* @property {(info: {
|
|
78
|
+
* value?: ArbitraryValue,
|
|
79
|
+
* typeNamespace?: string,
|
|
80
|
+
* }) => JamilihArray} editUI
|
|
81
|
+
* @property {(info: {root: HTMLDivElement}) =>
|
|
82
|
+
* HTMLInputElement|HTMLTextareaElement|HTMLSelectElement} getInput Gets the
|
|
83
|
+
* form control (with `value`)
|
|
84
|
+
* @property {(path: string, value: ArbitraryValue) =>
|
|
85
|
+
* ArbitraryValue} [resolveReference] Gets the reference. For array and object
|
|
93
86
|
* references types only
|
|
94
87
|
* @property {(info: {root: HTMLDivElement, topRoot?: HTMLDivElement}) => {
|
|
95
88
|
* message: string,
|
|
@@ -240,28 +233,52 @@ copyTypeObjs([
|
|
|
240
233
|
]);
|
|
241
234
|
|
|
242
235
|
/**
|
|
236
|
+
* Utility to retrieve the type out of a type root element.
|
|
243
237
|
* @public
|
|
244
|
-
* @param {RootElement} root
|
|
245
|
-
* @returns {string|
|
|
238
|
+
* @param {?RootElement} root
|
|
239
|
+
* @returns {string|undefined} Why would it not exist?
|
|
246
240
|
*/
|
|
247
241
|
Types.getTypeForRoot = (root) => {
|
|
248
242
|
return root && root.dataset.type;
|
|
249
243
|
};
|
|
250
244
|
|
|
251
245
|
/**
|
|
246
|
+
* @typedef {{
|
|
247
|
+
* typeNamespace: string,
|
|
248
|
+
* "readonly": boolean,
|
|
249
|
+
* format: string,
|
|
250
|
+
* error: Error,
|
|
251
|
+
* rootUI: Element,
|
|
252
|
+
* schemaContent: string,
|
|
253
|
+
* getPossibleSchemasForPathAndType: (
|
|
254
|
+
* keypath: string,
|
|
255
|
+
* parentPath: string,
|
|
256
|
+
* arrayOrObjectPropertyName: string,
|
|
257
|
+
* valueType: string
|
|
258
|
+
* ) => StateObject
|
|
259
|
+
* }} StateObject
|
|
260
|
+
*/
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Utility to get the value out of a type root element with a given
|
|
264
|
+
* state and path.
|
|
252
265
|
* @public
|
|
253
266
|
* @param {RootElement} root
|
|
254
267
|
* @param {StateObject} stateObj
|
|
255
|
-
* @param {string} currentPath
|
|
268
|
+
* @param {string} [currentPath]
|
|
256
269
|
* @returns {StructuredCloneValue}
|
|
257
270
|
*/
|
|
258
271
|
Types.getValueForRoot = (root, stateObj, currentPath) => {
|
|
259
|
-
|
|
272
|
+
const typeObject = /** @type {TypeObject} */ (
|
|
273
|
+
Types.availableTypes[Types.getTypeForRoot(root)]
|
|
274
|
+
);
|
|
275
|
+
return typeObject.getValue({
|
|
260
276
|
root, stateObj, currentPath
|
|
261
277
|
});
|
|
262
278
|
};
|
|
263
279
|
|
|
264
280
|
/**
|
|
281
|
+
* Utility to get the form control (e.g., input element) for a root.
|
|
265
282
|
* @public
|
|
266
283
|
* @param {RootElement} root
|
|
267
284
|
* @returns {null|HTMLInputElement}
|
|
@@ -276,6 +293,7 @@ Types.getFormControlForRoot = (root) => {
|
|
|
276
293
|
};
|
|
277
294
|
|
|
278
295
|
/**
|
|
296
|
+
* Utility to get the value for a root using its ancestor and state.
|
|
279
297
|
* @public
|
|
280
298
|
* @param {string|Element} selOrEl
|
|
281
299
|
* @param {StateObject} stateObj
|