jedison 1.5.1 → 1.6.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/CHANGELOG.md +15 -0
- package/dist/cjs/jedison.cjs +1 -1
- package/dist/cjs/jedison.cjs.map +1 -1
- package/dist/esm/jedison.js +850 -148
- package/dist/esm/jedison.js.map +1 -1
- package/dist/umd/jedison.umd.js +1 -1
- package/dist/umd/jedison.umd.js.map +1 -1
- package/package.json +5 -4
package/dist/esm/jedison.js
CHANGED
|
@@ -32,7 +32,7 @@ function replaceAll(str, find, replace) {
|
|
|
32
32
|
return str.replace(new RegExp(escapeRegExp(find), "g"), replace);
|
|
33
33
|
}
|
|
34
34
|
function pathToAttribute(path) {
|
|
35
|
-
return replaceAll(replaceAll(path, "#", "root"), "/", "-");
|
|
35
|
+
return replaceAll(replaceAll(path, "#", "root"), "/", "-").replace(/[^a-zA-Z0-9_-]/g, "");
|
|
36
36
|
}
|
|
37
37
|
function hasOwn(obj, prop) {
|
|
38
38
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
@@ -220,6 +220,19 @@ function removeDuplicatesFromArray(arr) {
|
|
|
220
220
|
}
|
|
221
221
|
return uniqueObjects;
|
|
222
222
|
}
|
|
223
|
+
function resolveInstancePath(currentPath, sourcePath) {
|
|
224
|
+
if (sourcePath.startsWith("#")) return sourcePath;
|
|
225
|
+
const parts = currentPath.split("/");
|
|
226
|
+
parts.pop();
|
|
227
|
+
for (const part of sourcePath.split("/")) {
|
|
228
|
+
if (part === "..") {
|
|
229
|
+
if (parts.length > 1) parts.pop();
|
|
230
|
+
} else if (part !== "." && part !== "") {
|
|
231
|
+
parts.push(part);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return parts.join("/");
|
|
235
|
+
}
|
|
223
236
|
function generateRandomID(maxLength2) {
|
|
224
237
|
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
225
238
|
let randomID = "";
|
|
@@ -510,14 +523,33 @@ function allOf(context) {
|
|
|
510
523
|
let errors = [];
|
|
511
524
|
const allOf2 = getSchemaAllOf(context.schema);
|
|
512
525
|
if (isSet(allOf2)) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
526
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
527
|
+
if (enableSubErrors) {
|
|
528
|
+
const schemaResults = [];
|
|
529
|
+
allOf2.forEach((schema, index2) => {
|
|
530
|
+
const subSchemaErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
531
|
+
if (subSchemaErrors.length > 0) {
|
|
532
|
+
schemaResults.push({ schemaIndex: index2, errors: subSchemaErrors });
|
|
533
|
+
}
|
|
517
534
|
});
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
535
|
+
if (schemaResults.length > 0) {
|
|
536
|
+
errors.push({
|
|
537
|
+
type: "error",
|
|
538
|
+
path: context.path,
|
|
539
|
+
constraint: "allOf",
|
|
540
|
+
subErrors: schemaResults
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
} else {
|
|
544
|
+
allOf2.forEach((schema) => {
|
|
545
|
+
const subSchemaErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
546
|
+
subSchemaErrors.forEach((error) => {
|
|
547
|
+
error.path = context.path;
|
|
548
|
+
});
|
|
549
|
+
errors.push(...subSchemaErrors);
|
|
550
|
+
});
|
|
551
|
+
errors = removeDuplicatesFromArray(errors);
|
|
552
|
+
}
|
|
521
553
|
}
|
|
522
554
|
return errors;
|
|
523
555
|
}
|
|
@@ -546,23 +578,46 @@ function anyOf(context) {
|
|
|
546
578
|
const errors = [];
|
|
547
579
|
const anyOf2 = getSchemaAnyOf(context.schema);
|
|
548
580
|
if (isSet(anyOf2)) {
|
|
581
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
549
582
|
let valid = false;
|
|
550
|
-
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
errors.push({
|
|
559
|
-
type: "error",
|
|
560
|
-
path: context.path,
|
|
561
|
-
constraint: "anyOf",
|
|
562
|
-
messages: [
|
|
563
|
-
context.translator.translate("errorAnyOf")
|
|
564
|
-
]
|
|
583
|
+
if (enableSubErrors) {
|
|
584
|
+
const schemaResults = [];
|
|
585
|
+
anyOf2.forEach((schema, index2) => {
|
|
586
|
+
const anyOfErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
587
|
+
if (anyOfErrors.length === 0) {
|
|
588
|
+
valid = true;
|
|
589
|
+
}
|
|
590
|
+
schemaResults.push({ schemaIndex: index2, errors: anyOfErrors });
|
|
565
591
|
});
|
|
592
|
+
if (!valid) {
|
|
593
|
+
errors.push({
|
|
594
|
+
type: "error",
|
|
595
|
+
path: context.path,
|
|
596
|
+
constraint: "anyOf",
|
|
597
|
+
messages: [
|
|
598
|
+
context.translator.translate("errorAnyOf")
|
|
599
|
+
],
|
|
600
|
+
subErrors: schemaResults.filter((r) => r.errors.length > 0)
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
} else {
|
|
604
|
+
for (const schema of anyOf2) {
|
|
605
|
+
const anyOfErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
606
|
+
if (anyOfErrors.length === 0) {
|
|
607
|
+
valid = true;
|
|
608
|
+
break;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
if (!valid) {
|
|
612
|
+
errors.push({
|
|
613
|
+
type: "error",
|
|
614
|
+
path: context.path,
|
|
615
|
+
constraint: "anyOf",
|
|
616
|
+
messages: [
|
|
617
|
+
context.translator.translate("errorAnyOf")
|
|
618
|
+
]
|
|
619
|
+
});
|
|
620
|
+
}
|
|
566
621
|
}
|
|
567
622
|
}
|
|
568
623
|
return errors;
|
|
@@ -630,10 +685,8 @@ function exclusiveMinimum(context) {
|
|
|
630
685
|
function format(context) {
|
|
631
686
|
const errors = [];
|
|
632
687
|
const format2 = getSchemaFormat(context.schema);
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
assertFormat = context.schema.options.assertFormat;
|
|
636
|
-
}
|
|
688
|
+
const xAssertFormat = getSchemaXOption(context.schema, "assertFormat");
|
|
689
|
+
const assertFormat = xAssertFormat !== void 0 ? xAssertFormat : context.validator.assertFormat;
|
|
637
690
|
if (isSet(format2) && isString(context.value) && assertFormat) {
|
|
638
691
|
let regexp;
|
|
639
692
|
if (format2 === "email") {
|
|
@@ -673,18 +726,23 @@ function items(context) {
|
|
|
673
726
|
messages: [context.translator.translate("errorItems")]
|
|
674
727
|
});
|
|
675
728
|
} else if (isObject(items2)) {
|
|
729
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
676
730
|
context.value.slice(prefixItemsSchemasCount).forEach((itemValue, i) => {
|
|
677
731
|
const index2 = prefixItemsSchemasCount + i;
|
|
678
732
|
const tmpErrors = context.validator.getErrors(itemValue, items2, index2, context.path + "/" + index2);
|
|
679
733
|
if (tmpErrors.length > 0) {
|
|
680
|
-
|
|
734
|
+
const error = {
|
|
681
735
|
type: "error",
|
|
682
736
|
path: context.path,
|
|
683
737
|
constraint: "items",
|
|
684
738
|
messages: [
|
|
685
739
|
compileTemplate(context.translator.translate("errorItems"), { index: index2 })
|
|
686
740
|
]
|
|
687
|
-
}
|
|
741
|
+
};
|
|
742
|
+
if (enableSubErrors) {
|
|
743
|
+
error.subErrors = tmpErrors;
|
|
744
|
+
}
|
|
745
|
+
errors.push(error);
|
|
688
746
|
}
|
|
689
747
|
});
|
|
690
748
|
}
|
|
@@ -862,23 +920,64 @@ function oneOf(context) {
|
|
|
862
920
|
const oneOf2 = getSchemaOneOf(context.schema);
|
|
863
921
|
if (isSet(oneOf2)) {
|
|
864
922
|
let counter = 0;
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
923
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
924
|
+
if (enableSubErrors) {
|
|
925
|
+
const schemaResults = [];
|
|
926
|
+
oneOf2.forEach((schema, index2) => {
|
|
927
|
+
const oneOfErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
928
|
+
if (oneOfErrors.length === 0) {
|
|
929
|
+
counter++;
|
|
930
|
+
schemaResults.push({ schemaIndex: index2, matched: true, errors: [] });
|
|
931
|
+
} else {
|
|
932
|
+
schemaResults.push({ schemaIndex: index2, matched: false, errors: oneOfErrors });
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
if (counter !== 1) {
|
|
936
|
+
const error = {
|
|
937
|
+
type: "error",
|
|
938
|
+
path: context.path,
|
|
939
|
+
constraint: "oneOf",
|
|
940
|
+
messages: [
|
|
941
|
+
compileTemplate(context.translator.translate("errorOneOf"), {
|
|
942
|
+
counter
|
|
943
|
+
})
|
|
944
|
+
]
|
|
945
|
+
};
|
|
946
|
+
if (counter === 0) {
|
|
947
|
+
error.subErrors = schemaResults.filter((r) => !r.matched).map((r) => ({
|
|
948
|
+
schemaIndex: r.schemaIndex,
|
|
949
|
+
errors: r.errors
|
|
950
|
+
}));
|
|
951
|
+
} else {
|
|
952
|
+
error.matchingSchemas = schemaResults.filter((r) => r.matched).map((r) => r.schemaIndex);
|
|
953
|
+
}
|
|
954
|
+
errors.push(error);
|
|
869
955
|
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
counter
|
|
879
|
-
})
|
|
880
|
-
]
|
|
956
|
+
} else {
|
|
957
|
+
const matchingSchemas = [];
|
|
958
|
+
oneOf2.forEach((schema, index2) => {
|
|
959
|
+
const oneOfErrors = context.validator.getErrors(context.value, schema, context.key, context.path);
|
|
960
|
+
if (oneOfErrors.length === 0) {
|
|
961
|
+
counter++;
|
|
962
|
+
matchingSchemas.push(index2);
|
|
963
|
+
}
|
|
881
964
|
});
|
|
965
|
+
if (counter !== 1) {
|
|
966
|
+
const error = {
|
|
967
|
+
type: "error",
|
|
968
|
+
path: context.path,
|
|
969
|
+
constraint: "oneOf",
|
|
970
|
+
messages: [
|
|
971
|
+
compileTemplate(context.translator.translate("errorOneOf"), {
|
|
972
|
+
counter
|
|
973
|
+
})
|
|
974
|
+
]
|
|
975
|
+
};
|
|
976
|
+
if (counter > 0) {
|
|
977
|
+
error.matchingSchemas = matchingSchemas;
|
|
978
|
+
}
|
|
979
|
+
errors.push(error);
|
|
980
|
+
}
|
|
882
981
|
}
|
|
883
982
|
}
|
|
884
983
|
return errors;
|
|
@@ -931,6 +1030,8 @@ function patternProperties(context) {
|
|
|
931
1030
|
function properties(context) {
|
|
932
1031
|
const schemaProperties = getSchemaProperties(context.schema);
|
|
933
1032
|
const invalidProperties = [];
|
|
1033
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
1034
|
+
const propertySubErrors = [];
|
|
934
1035
|
if (isObject(context.value) && isSet(schemaProperties)) {
|
|
935
1036
|
Object.keys(schemaProperties).forEach((propertyName) => {
|
|
936
1037
|
if (hasOwn(context.value, propertyName)) {
|
|
@@ -943,19 +1044,26 @@ function properties(context) {
|
|
|
943
1044
|
);
|
|
944
1045
|
if (propertyErrors.length > 0) {
|
|
945
1046
|
invalidProperties.push(propertyName);
|
|
1047
|
+
if (enableSubErrors) {
|
|
1048
|
+
propertySubErrors.push({ property: propertyName, errors: propertyErrors });
|
|
1049
|
+
}
|
|
946
1050
|
}
|
|
947
1051
|
}
|
|
948
1052
|
});
|
|
949
1053
|
}
|
|
950
1054
|
if (invalidProperties.length > 0) {
|
|
951
|
-
|
|
1055
|
+
const error = {
|
|
952
1056
|
type: "error",
|
|
953
1057
|
path: context.path,
|
|
954
1058
|
constraint: "properties",
|
|
955
1059
|
messages: [
|
|
956
1060
|
compileTemplate(context.translator.translate("errorProperties"), { properties: invalidProperties.join(", ") })
|
|
957
1061
|
]
|
|
958
|
-
}
|
|
1062
|
+
};
|
|
1063
|
+
if (enableSubErrors) {
|
|
1064
|
+
error.subErrors = propertySubErrors;
|
|
1065
|
+
}
|
|
1066
|
+
return [error];
|
|
959
1067
|
}
|
|
960
1068
|
return [];
|
|
961
1069
|
}
|
|
@@ -1232,9 +1340,11 @@ function dependentRequired(context) {
|
|
|
1232
1340
|
Object.keys(dependentRequired2).forEach((key) => {
|
|
1233
1341
|
if (isSet(context.value[key])) {
|
|
1234
1342
|
const requiredProperties = dependentRequired2[key];
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1343
|
+
if (isArray(requiredProperties)) {
|
|
1344
|
+
missingProperties = requiredProperties.filter((property) => {
|
|
1345
|
+
return !hasOwn(context.value, property);
|
|
1346
|
+
});
|
|
1347
|
+
}
|
|
1238
1348
|
}
|
|
1239
1349
|
});
|
|
1240
1350
|
const invalid = missingProperties.length > 0;
|
|
@@ -1293,12 +1403,13 @@ function prefixItems(context) {
|
|
|
1293
1403
|
const errors = [];
|
|
1294
1404
|
const prefixItems2 = getSchemaPrefixItems(context.schema);
|
|
1295
1405
|
if (isArray(context.value) && isSet(prefixItems2)) {
|
|
1406
|
+
const enableSubErrors = getSchemaXOption(context.schema, "subErrors") ?? context.validator.subErrors;
|
|
1296
1407
|
prefixItems2.forEach((itemSchema, index2) => {
|
|
1297
1408
|
const itemValue = context.value[index2];
|
|
1298
1409
|
if (isSet(itemValue)) {
|
|
1299
1410
|
const tmpErrors = context.validator.getErrors(itemValue, itemSchema, index2, context.path + "/" + index2);
|
|
1300
1411
|
if (tmpErrors.length > 0) {
|
|
1301
|
-
|
|
1412
|
+
const error = {
|
|
1302
1413
|
type: "error",
|
|
1303
1414
|
path: context.path,
|
|
1304
1415
|
constraint: "prefixItems",
|
|
@@ -1307,7 +1418,11 @@ function prefixItems(context) {
|
|
|
1307
1418
|
index: index2
|
|
1308
1419
|
})
|
|
1309
1420
|
]
|
|
1310
|
-
}
|
|
1421
|
+
};
|
|
1422
|
+
if (enableSubErrors) {
|
|
1423
|
+
error.subErrors = tmpErrors;
|
|
1424
|
+
}
|
|
1425
|
+
errors.push(error);
|
|
1311
1426
|
}
|
|
1312
1427
|
}
|
|
1313
1428
|
});
|
|
@@ -1538,6 +1653,7 @@ class Validator {
|
|
|
1538
1653
|
this.constraints = config.constraints ?? {};
|
|
1539
1654
|
this.assertFormat = config.assertFormat ? config.assertFormat : false;
|
|
1540
1655
|
this.translator = config.translator ? config.translator : false;
|
|
1656
|
+
this.subErrors = config.subErrors ?? false;
|
|
1541
1657
|
this.draft = draft202012;
|
|
1542
1658
|
this.jsonSchemaDrafts = {
|
|
1543
1659
|
"http://json-schema.org/draft-04/schema#": draft04,
|
|
@@ -2123,11 +2239,13 @@ class Editor {
|
|
|
2123
2239
|
});
|
|
2124
2240
|
this.control.messages.innerHTML = "";
|
|
2125
2241
|
this.showingValidationErrors = false;
|
|
2242
|
+
this.setAriaInvalid(false);
|
|
2126
2243
|
const neverShowErrors = this.instance.jedison.options.showErrors === "never" || getSchemaXOption(this.instance.schema, "showErrors") === "never";
|
|
2127
2244
|
if (neverShowErrors && !force || errors.length === 0) {
|
|
2128
2245
|
return;
|
|
2129
2246
|
}
|
|
2130
2247
|
const muteValidationMessages = getSchemaXOption(this.instance.schema, "muteValidationMessages") ?? this.instance.jedison.options.muteValidationMessages ?? [];
|
|
2248
|
+
let hasErrors = false;
|
|
2131
2249
|
errors.forEach((error) => {
|
|
2132
2250
|
if (muteValidationMessages.includes(error.constraint)) {
|
|
2133
2251
|
return;
|
|
@@ -2135,6 +2253,7 @@ class Editor {
|
|
|
2135
2253
|
error.messages.forEach((message) => {
|
|
2136
2254
|
let invalidFeedback;
|
|
2137
2255
|
if (error.type === "error") {
|
|
2256
|
+
hasErrors = true;
|
|
2138
2257
|
invalidFeedback = this.getErrorFeedback({
|
|
2139
2258
|
message
|
|
2140
2259
|
});
|
|
@@ -2146,8 +2265,20 @@ class Editor {
|
|
|
2146
2265
|
this.control.messages.appendChild(invalidFeedback);
|
|
2147
2266
|
});
|
|
2148
2267
|
});
|
|
2268
|
+
if (hasErrors) {
|
|
2269
|
+
this.setAriaInvalid(true);
|
|
2270
|
+
}
|
|
2149
2271
|
this.showingValidationErrors = true;
|
|
2150
2272
|
}
|
|
2273
|
+
setAriaInvalid(invalid) {
|
|
2274
|
+
if (this.control.input) {
|
|
2275
|
+
if (invalid) {
|
|
2276
|
+
this.control.input.setAttribute("aria-invalid", "true");
|
|
2277
|
+
} else {
|
|
2278
|
+
this.control.input.removeAttribute("aria-invalid");
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2151
2282
|
/**
|
|
2152
2283
|
* Get an error message container
|
|
2153
2284
|
*/
|
|
@@ -2234,6 +2365,8 @@ class Editor {
|
|
|
2234
2365
|
}
|
|
2235
2366
|
return schemaInfo;
|
|
2236
2367
|
}
|
|
2368
|
+
refreshLegendWarning() {
|
|
2369
|
+
}
|
|
2237
2370
|
/**
|
|
2238
2371
|
* Updates control UI when its state changes
|
|
2239
2372
|
*/
|
|
@@ -2294,6 +2427,24 @@ class Editor {
|
|
|
2294
2427
|
this.control.jsonData.input.value = JSON.stringify(this.instance.getValue(), null, 2);
|
|
2295
2428
|
}
|
|
2296
2429
|
}
|
|
2430
|
+
getNextChildPath(path) {
|
|
2431
|
+
const currentDepth = this.instance.path.split(this.instance.jedison.pathSeparator).length;
|
|
2432
|
+
const targetSegments = path.split(this.instance.jedison.pathSeparator);
|
|
2433
|
+
if (targetSegments.length <= currentDepth) return null;
|
|
2434
|
+
return targetSegments.slice(0, currentDepth + 1).join(this.instance.jedison.pathSeparator);
|
|
2435
|
+
}
|
|
2436
|
+
navigateTo(path) {
|
|
2437
|
+
if (path === this.instance.path) {
|
|
2438
|
+
this.control.container.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
2439
|
+
return;
|
|
2440
|
+
}
|
|
2441
|
+
const nextChildPath = this.getNextChildPath(path);
|
|
2442
|
+
if (!nextChildPath) return;
|
|
2443
|
+
const child = this.instance.children.find((c) => c.path === nextChildPath);
|
|
2444
|
+
if (child == null ? void 0 : child.ui) {
|
|
2445
|
+
child.ui.navigateTo(path);
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2297
2448
|
/**
|
|
2298
2449
|
* Destroys the editor
|
|
2299
2450
|
*/
|
|
@@ -2635,6 +2786,21 @@ class InstanceMultiple extends Instance {
|
|
|
2635
2786
|
* Returns the index of the instance that has less validation errors
|
|
2636
2787
|
*/
|
|
2637
2788
|
getFittestIndex(value) {
|
|
2789
|
+
const discriminator = getSchemaXOption(this.schema, "discriminator");
|
|
2790
|
+
if (isSet(discriminator) && isObject(value)) {
|
|
2791
|
+
const propName = isString(discriminator) ? discriminator : discriminator.propertyName;
|
|
2792
|
+
const discriminatorValue = value[propName];
|
|
2793
|
+
if (isSet(discriminatorValue)) {
|
|
2794
|
+
for (let index2 = 0; index2 < this.schemas.length; index2++) {
|
|
2795
|
+
const schema = this.schemas[index2];
|
|
2796
|
+
const propSchema = schema.properties && schema.properties[propName];
|
|
2797
|
+
if (propSchema) {
|
|
2798
|
+
const propErrors = this.jedison.validator.getErrors(discriminatorValue, propSchema, propName, this.path);
|
|
2799
|
+
if (propErrors.length === 0) return index2;
|
|
2800
|
+
}
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2638
2804
|
let fittestIndex;
|
|
2639
2805
|
let championErrors;
|
|
2640
2806
|
for (let index2 = 0; index2 < this.instances.length; index2++) {
|
|
@@ -2761,9 +2927,11 @@ class InstanceObject extends Instance {
|
|
|
2761
2927
|
Object.keys(dependentRequired2).forEach((key) => {
|
|
2762
2928
|
if (isSet(this.value[key])) {
|
|
2763
2929
|
const requiredProperties = dependentRequired2[key];
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2930
|
+
if (isArray(requiredProperties)) {
|
|
2931
|
+
missingProperties = requiredProperties.filter((property2) => {
|
|
2932
|
+
return !hasOwn(this.value, property2);
|
|
2933
|
+
});
|
|
2934
|
+
}
|
|
2767
2935
|
}
|
|
2768
2936
|
});
|
|
2769
2937
|
return missingProperties.includes(property);
|
|
@@ -3149,6 +3317,15 @@ class EditorRadios extends EditorBoolean {
|
|
|
3149
3317
|
radio.checked = radioValue === this.instance.getValue();
|
|
3150
3318
|
});
|
|
3151
3319
|
}
|
|
3320
|
+
setAriaInvalid(invalid) {
|
|
3321
|
+
this.control.radios.forEach((radio) => {
|
|
3322
|
+
if (invalid) {
|
|
3323
|
+
radio.setAttribute("aria-invalid", "true");
|
|
3324
|
+
} else {
|
|
3325
|
+
radio.removeAttribute("aria-invalid");
|
|
3326
|
+
}
|
|
3327
|
+
});
|
|
3328
|
+
}
|
|
3152
3329
|
}
|
|
3153
3330
|
class EditorBooleanSelect extends EditorBoolean {
|
|
3154
3331
|
static resolves(schema) {
|
|
@@ -3218,18 +3395,86 @@ class EditorStringRadios extends EditorString {
|
|
|
3218
3395
|
static resolves(schema) {
|
|
3219
3396
|
return getSchemaType(schema) === "string" && (getSchemaXOption(schema, "format") === "radios" || getSchemaXOption(schema, "format") === "radios-inline");
|
|
3220
3397
|
}
|
|
3398
|
+
init() {
|
|
3399
|
+
super.init();
|
|
3400
|
+
this.setupEnumSource();
|
|
3401
|
+
}
|
|
3402
|
+
setupEnumSource() {
|
|
3403
|
+
const enumSourceRaw = getSchemaXOption(this.instance.schema, "enumSource");
|
|
3404
|
+
if (!isSet(enumSourceRaw)) return;
|
|
3405
|
+
const enumSource = resolveInstancePath(this.instance.path, enumSourceRaw);
|
|
3406
|
+
const src = this.instance.jedison.getInstance(enumSource);
|
|
3407
|
+
if (src) this.enumSourceValues = src.getValue();
|
|
3408
|
+
this.instance.jedison.watch(enumSource, () => {
|
|
3409
|
+
if (!this.control) return;
|
|
3410
|
+
const s = this.instance.jedison.getInstance(enumSource);
|
|
3411
|
+
if (s) {
|
|
3412
|
+
this.enumSourceValues = s.getValue();
|
|
3413
|
+
this.refreshOptions();
|
|
3414
|
+
}
|
|
3415
|
+
});
|
|
3416
|
+
}
|
|
3417
|
+
getEnumSourceValues() {
|
|
3418
|
+
if (this.enumSourceValues !== void 0) {
|
|
3419
|
+
if (isArray(this.enumSourceValues)) return this.enumSourceValues;
|
|
3420
|
+
if (isObject(this.enumSourceValues)) return Object.keys(this.enumSourceValues);
|
|
3421
|
+
return [];
|
|
3422
|
+
}
|
|
3423
|
+
return getSchemaEnum(this.instance.schema) || [];
|
|
3424
|
+
}
|
|
3221
3425
|
build() {
|
|
3426
|
+
const values = this.getEnumSourceValues();
|
|
3222
3427
|
this.control = this.theme.getRadiosControl({
|
|
3223
3428
|
title: this.getTitle(),
|
|
3224
3429
|
description: this.getDescription(),
|
|
3225
|
-
values
|
|
3226
|
-
titles: getSchemaXOption(this.instance.schema, "enumTitles") ||
|
|
3430
|
+
values,
|
|
3431
|
+
titles: getSchemaXOption(this.instance.schema, "enumTitles") || values,
|
|
3227
3432
|
id: this.getIdFromPath(this.instance.path),
|
|
3228
3433
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
3229
3434
|
inline: getSchemaXOption(this.instance.schema, "format") === "radios-inline",
|
|
3230
3435
|
info: this.getInfo()
|
|
3231
3436
|
});
|
|
3232
3437
|
}
|
|
3438
|
+
refreshOptions() {
|
|
3439
|
+
const values = this.getEnumSourceValues();
|
|
3440
|
+
const titles = getSchemaXOption(this.instance.schema, "enumTitles") || values;
|
|
3441
|
+
const id = this.getIdFromPath(this.instance.path);
|
|
3442
|
+
const messagesId = id + "-messages";
|
|
3443
|
+
const descriptionId = id + "-description";
|
|
3444
|
+
const describedBy = messagesId + " " + descriptionId;
|
|
3445
|
+
this.control.radioControls.forEach((rc) => {
|
|
3446
|
+
if (rc.parentNode) rc.parentNode.removeChild(rc);
|
|
3447
|
+
});
|
|
3448
|
+
this.control.radios = [];
|
|
3449
|
+
this.control.labels = [];
|
|
3450
|
+
this.control.radioControls = [];
|
|
3451
|
+
this.control.labelTexts = [];
|
|
3452
|
+
values.forEach((value, index2) => {
|
|
3453
|
+
const radioControl = document.createElement("div");
|
|
3454
|
+
const radio = document.createElement("input");
|
|
3455
|
+
const label = document.createElement("label");
|
|
3456
|
+
const labelText = document.createElement("span");
|
|
3457
|
+
radio.setAttribute("type", "radio");
|
|
3458
|
+
radio.setAttribute("id", id + "-" + index2);
|
|
3459
|
+
radio.setAttribute("name", id);
|
|
3460
|
+
radio.setAttribute("value", value);
|
|
3461
|
+
radio.setAttribute("aria-describedby", describedBy);
|
|
3462
|
+
label.setAttribute("for", id + "-" + index2);
|
|
3463
|
+
label.classList.add("jedi-title");
|
|
3464
|
+
label.classList.add("jedi-label");
|
|
3465
|
+
labelText.textContent = titles && titles[index2] !== void 0 ? titles[index2] : value;
|
|
3466
|
+
radioControl.appendChild(radio);
|
|
3467
|
+
radioControl.appendChild(label);
|
|
3468
|
+
label.appendChild(labelText);
|
|
3469
|
+
this.control.radios.push(radio);
|
|
3470
|
+
this.control.labels.push(label);
|
|
3471
|
+
this.control.labelTexts.push(labelText);
|
|
3472
|
+
this.control.radioControls.push(radioControl);
|
|
3473
|
+
this.control.fieldset.insertBefore(radioControl, this.control.description);
|
|
3474
|
+
});
|
|
3475
|
+
this.addEventListeners();
|
|
3476
|
+
this.refreshUI();
|
|
3477
|
+
}
|
|
3233
3478
|
adaptForTable() {
|
|
3234
3479
|
this.theme.adaptForTableRadiosControl(this.control);
|
|
3235
3480
|
}
|
|
@@ -3246,23 +3491,73 @@ class EditorStringRadios extends EditorString {
|
|
|
3246
3491
|
radio.checked = radio.value === this.instance.getValue();
|
|
3247
3492
|
});
|
|
3248
3493
|
}
|
|
3494
|
+
setAriaInvalid(invalid) {
|
|
3495
|
+
this.control.radios.forEach((radio) => {
|
|
3496
|
+
if (invalid) {
|
|
3497
|
+
radio.setAttribute("aria-invalid", "true");
|
|
3498
|
+
} else {
|
|
3499
|
+
radio.removeAttribute("aria-invalid");
|
|
3500
|
+
}
|
|
3501
|
+
});
|
|
3502
|
+
}
|
|
3249
3503
|
}
|
|
3250
3504
|
class EditorStringSelect extends EditorString {
|
|
3251
3505
|
static resolves(schema) {
|
|
3252
|
-
return getSchemaType(schema) === "string" && isSet(getSchemaEnum(schema));
|
|
3506
|
+
return getSchemaType(schema) === "string" && (isSet(getSchemaEnum(schema)) || isSet(getSchemaXOption(schema, "enumSource")));
|
|
3507
|
+
}
|
|
3508
|
+
init() {
|
|
3509
|
+
super.init();
|
|
3510
|
+
this.setupEnumSource();
|
|
3511
|
+
}
|
|
3512
|
+
setupEnumSource() {
|
|
3513
|
+
const enumSourceRaw = getSchemaXOption(this.instance.schema, "enumSource");
|
|
3514
|
+
if (!isSet(enumSourceRaw)) return;
|
|
3515
|
+
const enumSource = resolveInstancePath(this.instance.path, enumSourceRaw);
|
|
3516
|
+
const src = this.instance.jedison.getInstance(enumSource);
|
|
3517
|
+
if (src) this.enumSourceValues = src.getValue();
|
|
3518
|
+
this.instance.jedison.watch(enumSource, () => {
|
|
3519
|
+
if (!this.control) return;
|
|
3520
|
+
const s = this.instance.jedison.getInstance(enumSource);
|
|
3521
|
+
if (s) {
|
|
3522
|
+
this.enumSourceValues = s.getValue();
|
|
3523
|
+
this.refreshOptions();
|
|
3524
|
+
}
|
|
3525
|
+
});
|
|
3526
|
+
}
|
|
3527
|
+
getEnumSourceValues() {
|
|
3528
|
+
if (this.enumSourceValues !== void 0) {
|
|
3529
|
+
if (isArray(this.enumSourceValues)) return this.enumSourceValues;
|
|
3530
|
+
if (isObject(this.enumSourceValues)) return Object.keys(this.enumSourceValues);
|
|
3531
|
+
return [];
|
|
3532
|
+
}
|
|
3533
|
+
return getSchemaEnum(this.instance.schema) || [];
|
|
3253
3534
|
}
|
|
3254
3535
|
build() {
|
|
3536
|
+
const values = this.getEnumSourceValues();
|
|
3255
3537
|
this.control = this.theme.getSelectControl({
|
|
3256
3538
|
title: this.getTitle(),
|
|
3257
3539
|
description: this.getDescription(),
|
|
3258
|
-
values
|
|
3259
|
-
titles: getSchemaXOption(this.instance.schema, "enumTitles") ||
|
|
3540
|
+
values,
|
|
3541
|
+
titles: getSchemaXOption(this.instance.schema, "enumTitles") || values,
|
|
3260
3542
|
id: this.getIdFromPath(this.instance.path),
|
|
3261
3543
|
titleIconClass: getSchemaXOption(this.instance.schema, "titleIconClass"),
|
|
3262
3544
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
3263
3545
|
info: this.getInfo()
|
|
3264
3546
|
});
|
|
3265
3547
|
}
|
|
3548
|
+
refreshOptions() {
|
|
3549
|
+
const values = this.getEnumSourceValues();
|
|
3550
|
+
const titles = getSchemaXOption(this.instance.schema, "enumTitles") || values;
|
|
3551
|
+
const select = this.control.input;
|
|
3552
|
+
select.innerHTML = "";
|
|
3553
|
+
values.forEach((value, i) => {
|
|
3554
|
+
const option = document.createElement("option");
|
|
3555
|
+
option.setAttribute("value", value);
|
|
3556
|
+
option.textContent = titles && titles[i] !== void 0 ? titles[i] : value;
|
|
3557
|
+
select.appendChild(option);
|
|
3558
|
+
});
|
|
3559
|
+
this.refreshUI();
|
|
3560
|
+
}
|
|
3266
3561
|
adaptForTable() {
|
|
3267
3562
|
this.theme.adaptForTableSelectControl(this.control);
|
|
3268
3563
|
}
|
|
@@ -3504,25 +3799,75 @@ class EditorNumberRadios extends EditorNumber {
|
|
|
3504
3799
|
radio.checked = Number(radio.value) === Number(this.instance.getValue());
|
|
3505
3800
|
});
|
|
3506
3801
|
}
|
|
3802
|
+
setAriaInvalid(invalid) {
|
|
3803
|
+
this.control.radios.forEach((radio) => {
|
|
3804
|
+
if (invalid) {
|
|
3805
|
+
radio.setAttribute("aria-invalid", "true");
|
|
3806
|
+
} else {
|
|
3807
|
+
radio.removeAttribute("aria-invalid");
|
|
3808
|
+
}
|
|
3809
|
+
});
|
|
3810
|
+
}
|
|
3507
3811
|
}
|
|
3508
3812
|
class EditorNumberSelect extends EditorNumber {
|
|
3509
3813
|
static resolves(schema) {
|
|
3510
3814
|
const schemaType = getSchemaType(schema);
|
|
3511
3815
|
const typeIsNumeric = schemaType === "number" || schemaType === "integer";
|
|
3512
|
-
return typeIsNumeric && isSet(getSchemaEnum(schema));
|
|
3816
|
+
return typeIsNumeric && (isSet(getSchemaEnum(schema)) || isSet(getSchemaXOption(schema, "enumSource")));
|
|
3817
|
+
}
|
|
3818
|
+
init() {
|
|
3819
|
+
super.init();
|
|
3820
|
+
this.setupEnumSource();
|
|
3821
|
+
}
|
|
3822
|
+
setupEnumSource() {
|
|
3823
|
+
const enumSourceRaw = getSchemaXOption(this.instance.schema, "enumSource");
|
|
3824
|
+
if (!isSet(enumSourceRaw)) return;
|
|
3825
|
+
const enumSource = resolveInstancePath(this.instance.path, enumSourceRaw);
|
|
3826
|
+
const src = this.instance.jedison.getInstance(enumSource);
|
|
3827
|
+
if (src) this.enumSourceValues = src.getValue();
|
|
3828
|
+
this.instance.jedison.watch(enumSource, () => {
|
|
3829
|
+
if (!this.control) return;
|
|
3830
|
+
const s = this.instance.jedison.getInstance(enumSource);
|
|
3831
|
+
if (s) {
|
|
3832
|
+
this.enumSourceValues = s.getValue();
|
|
3833
|
+
this.refreshOptions();
|
|
3834
|
+
}
|
|
3835
|
+
});
|
|
3836
|
+
}
|
|
3837
|
+
getEnumSourceValues() {
|
|
3838
|
+
if (this.enumSourceValues !== void 0) {
|
|
3839
|
+
if (isArray(this.enumSourceValues)) return this.enumSourceValues;
|
|
3840
|
+
if (isObject(this.enumSourceValues)) return Object.keys(this.enumSourceValues);
|
|
3841
|
+
return [];
|
|
3842
|
+
}
|
|
3843
|
+
return getSchemaEnum(this.instance.schema) || [];
|
|
3513
3844
|
}
|
|
3514
3845
|
build() {
|
|
3846
|
+
const values = this.getEnumSourceValues();
|
|
3515
3847
|
this.control = this.theme.getSelectControl({
|
|
3516
3848
|
title: this.getTitle(),
|
|
3517
3849
|
description: this.getDescription(),
|
|
3518
|
-
values
|
|
3519
|
-
titles: getSchemaXOption(this.instance.schema, "enumTitles") ||
|
|
3850
|
+
values,
|
|
3851
|
+
titles: getSchemaXOption(this.instance.schema, "enumTitles") || values,
|
|
3520
3852
|
id: this.getIdFromPath(this.instance.path),
|
|
3521
3853
|
titleIconClass: getSchemaXOption(this.instance.schema, "titleIconClass"),
|
|
3522
3854
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
3523
3855
|
info: this.getInfo()
|
|
3524
3856
|
});
|
|
3525
3857
|
}
|
|
3858
|
+
refreshOptions() {
|
|
3859
|
+
const values = this.getEnumSourceValues();
|
|
3860
|
+
const titles = getSchemaXOption(this.instance.schema, "enumTitles") || values;
|
|
3861
|
+
const select = this.control.input;
|
|
3862
|
+
select.innerHTML = "";
|
|
3863
|
+
values.forEach((value, i) => {
|
|
3864
|
+
const option = document.createElement("option");
|
|
3865
|
+
option.setAttribute("value", value);
|
|
3866
|
+
option.textContent = titles && titles[i] !== void 0 ? titles[i] : value;
|
|
3867
|
+
select.appendChild(option);
|
|
3868
|
+
});
|
|
3869
|
+
this.refreshUI();
|
|
3870
|
+
}
|
|
3526
3871
|
adaptForTable() {
|
|
3527
3872
|
this.theme.adaptForTableSelectControl(this.control);
|
|
3528
3873
|
}
|
|
@@ -3645,6 +3990,10 @@ class EditorObject extends Editor {
|
|
|
3645
3990
|
if (isSet(additionalProperties2) && additionalProperties2 === false) {
|
|
3646
3991
|
addProperty = false;
|
|
3647
3992
|
}
|
|
3993
|
+
const objectAdd = getSchemaXOption(this.instance.schema, "objectAdd") ?? this.instance.jedison.options.objectAdd;
|
|
3994
|
+
if (isSet(objectAdd) && objectAdd === false) {
|
|
3995
|
+
addProperty = false;
|
|
3996
|
+
}
|
|
3648
3997
|
let enablePropertiesToggle = false;
|
|
3649
3998
|
if (isSet(this.instance.jedison.options.enablePropertiesToggle)) {
|
|
3650
3999
|
enablePropertiesToggle = this.instance.jedison.options.enablePropertiesToggle;
|
|
@@ -3671,30 +4020,30 @@ class EditorObject extends Editor {
|
|
|
3671
4020
|
});
|
|
3672
4021
|
this.control.jsonData.input.value = JSON.stringify(this.instance.getValue(), null, 2);
|
|
3673
4022
|
}
|
|
4023
|
+
announcePropertyAdded(propertyName, child) {
|
|
4024
|
+
const schemaTitle = getSchemaTitle(child.schema);
|
|
4025
|
+
const label = isSet(schemaTitle) ? schemaTitle : propertyName;
|
|
4026
|
+
const ariaLiveMessage = this.theme.getAriaLiveMessage();
|
|
4027
|
+
ariaLiveMessage.textContent = label + " " + this.instance.jedison.translator.translate("objectPropertyAdded");
|
|
4028
|
+
this.control.ariaLive.appendChild(ariaLiveMessage);
|
|
4029
|
+
}
|
|
4030
|
+
addProperty(input, postAction) {
|
|
4031
|
+
const propertyName = input.value.split(" ").join("");
|
|
4032
|
+
if (propertyName.length === 0) return;
|
|
4033
|
+
if (isSet(this.instance.value[propertyName])) return;
|
|
4034
|
+
const schema = this.instance.getPropertySchema(propertyName);
|
|
4035
|
+
const child = this.instance.createChild(schema, propertyName);
|
|
4036
|
+
child.activate();
|
|
4037
|
+
this.instance.setValue(this.instance.value, true, "user");
|
|
4038
|
+
input.value = "";
|
|
4039
|
+
this.announcePropertyAdded(propertyName, child);
|
|
4040
|
+
postAction();
|
|
4041
|
+
}
|
|
3674
4042
|
addEventListeners() {
|
|
3675
|
-
this.control.
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
return;
|
|
3680
|
-
}
|
|
3681
|
-
const propertyExist = isSet(this.instance.value[propertyName]);
|
|
3682
|
-
if (propertyExist) {
|
|
3683
|
-
return;
|
|
3684
|
-
}
|
|
3685
|
-
const schema = this.instance.getPropertySchema(propertyName);
|
|
3686
|
-
const child = this.instance.createChild(schema, propertyName);
|
|
3687
|
-
child.activate();
|
|
3688
|
-
this.instance.setValue(this.instance.value, true, "user");
|
|
3689
|
-
this.control.addPropertyControl.input.value = "";
|
|
3690
|
-
const ariaLive = this.control.ariaLive;
|
|
3691
|
-
const schemaTitle = getSchemaTitle(child.schema);
|
|
3692
|
-
const label = isSet(schemaTitle) ? schemaTitle : propertyName;
|
|
3693
|
-
const ariaLiveMessage = this.theme.getAriaLiveMessage();
|
|
3694
|
-
ariaLiveMessage.textContent = label + " " + this.instance.jedison.translator.translate("objectPropertyAdded");
|
|
3695
|
-
ariaLive.appendChild(ariaLiveMessage);
|
|
3696
|
-
this.control.propertiesContainer.close();
|
|
3697
|
-
this.control.propertiesContainer.showModal();
|
|
4043
|
+
this.control.quickAddPropertyBtn.addEventListener("click", () => {
|
|
4044
|
+
this.addProperty(this.control.quickAddPropertyControl.input, () => {
|
|
4045
|
+
this.control.quickAddPropertyContainer.close();
|
|
4046
|
+
});
|
|
3698
4047
|
});
|
|
3699
4048
|
this.control.jsonData.saveBtn.addEventListener("click", () => {
|
|
3700
4049
|
try {
|
|
@@ -3724,9 +4073,7 @@ class EditorObject extends Editor {
|
|
|
3724
4073
|
const declaredProperties = Object.keys(this.instance.properties);
|
|
3725
4074
|
const instanceProperties = this.instance.children.map((child) => child.getKey());
|
|
3726
4075
|
const properties2 = [.../* @__PURE__ */ new Set([...declaredProperties, ...instanceProperties])];
|
|
3727
|
-
|
|
3728
|
-
this.control.propertiesActivators.removeChild(this.control.propertiesActivators.firstChild);
|
|
3729
|
-
}
|
|
4076
|
+
this.control.propertiesActivators.replaceChildren();
|
|
3730
4077
|
const {
|
|
3731
4078
|
container: defaultGroupContainer,
|
|
3732
4079
|
group: defaultGroup
|
|
@@ -3783,12 +4130,28 @@ class EditorObject extends Editor {
|
|
|
3783
4130
|
checkbox.disabled = this.disabled || isRequired;
|
|
3784
4131
|
checkbox.checked = hasOwn(currentValue, property);
|
|
3785
4132
|
});
|
|
4133
|
+
const propGroupOrder = getSchemaXOption(this.instance.schema, "propGroupOrder");
|
|
4134
|
+
if (isSet(propGroupOrder) && Array.isArray(propGroupOrder)) {
|
|
4135
|
+
const orderedContainers = [defaultGroupContainer];
|
|
4136
|
+
propGroupOrder.forEach((groupName) => {
|
|
4137
|
+
if (isSet(propertiesGroups[groupName])) {
|
|
4138
|
+
orderedContainers.push(propertiesGroups[groupName].container);
|
|
4139
|
+
}
|
|
4140
|
+
});
|
|
4141
|
+
Object.keys(propertiesGroups).forEach((groupName) => {
|
|
4142
|
+
if (!propGroupOrder.includes(groupName)) {
|
|
4143
|
+
orderedContainers.push(propertiesGroups[groupName].container);
|
|
4144
|
+
}
|
|
4145
|
+
});
|
|
4146
|
+
this.control.propertiesActivators.replaceChildren();
|
|
4147
|
+
orderedContainers.forEach((container) => {
|
|
4148
|
+
this.control.propertiesActivators.appendChild(container);
|
|
4149
|
+
});
|
|
4150
|
+
}
|
|
3786
4151
|
}
|
|
3787
4152
|
}
|
|
3788
4153
|
refreshEditors() {
|
|
3789
|
-
|
|
3790
|
-
this.control.childrenSlot.removeChild(this.control.childrenSlot.firstChild);
|
|
3791
|
-
}
|
|
4154
|
+
this.control.childrenSlot.replaceChildren();
|
|
3792
4155
|
this.instance.children.forEach((child) => {
|
|
3793
4156
|
const optIn = this.theme.getCheckboxControl({
|
|
3794
4157
|
id: child.path + "-opt-in",
|
|
@@ -3822,11 +4185,32 @@ class EditorObject extends Editor {
|
|
|
3822
4185
|
}
|
|
3823
4186
|
});
|
|
3824
4187
|
}
|
|
4188
|
+
refreshLegendWarning() {
|
|
4189
|
+
if (!this.control.legendText) return;
|
|
4190
|
+
const navWarning = getSchemaXOption(this.instance.schema, "navWarning") ?? true;
|
|
4191
|
+
const hasErrors = navWarning && this.instance.hasNestedValidationErrors();
|
|
4192
|
+
const existing = this.control.legendText.querySelector(".jedi-legend-warning");
|
|
4193
|
+
if (existing) existing.parentNode.removeChild(existing);
|
|
4194
|
+
if (hasErrors) {
|
|
4195
|
+
const warning = document.createElement("span");
|
|
4196
|
+
warning.classList.add("jedi-legend-warning");
|
|
4197
|
+
warning.textContent = "⚠";
|
|
4198
|
+
const navWarningMessage = getSchemaXOption(this.instance.schema, "navWarningMessage");
|
|
4199
|
+
if (navWarningMessage) warning.setAttribute("title", navWarningMessage);
|
|
4200
|
+
this.theme.styleLegendWarning(warning);
|
|
4201
|
+
this.control.legendText.appendChild(warning);
|
|
4202
|
+
}
|
|
4203
|
+
}
|
|
4204
|
+
showValidationErrors(errors, force = false) {
|
|
4205
|
+
super.showValidationErrors(errors, force);
|
|
4206
|
+
this.refreshLegendWarning();
|
|
4207
|
+
}
|
|
3825
4208
|
refreshUI() {
|
|
3826
4209
|
super.refreshUI();
|
|
3827
4210
|
this.refreshPropertiesSlot();
|
|
3828
4211
|
this.refreshEditors();
|
|
3829
4212
|
this.refreshJsonData();
|
|
4213
|
+
this.refreshLegendWarning();
|
|
3830
4214
|
}
|
|
3831
4215
|
}
|
|
3832
4216
|
class EditorObjectGrid extends EditorObject {
|
|
@@ -3877,6 +4261,29 @@ class EditorObjectCategories extends EditorObject {
|
|
|
3877
4261
|
super.init();
|
|
3878
4262
|
this.activeCategoryName = null;
|
|
3879
4263
|
}
|
|
4264
|
+
navigateTo(path) {
|
|
4265
|
+
const nextChildPath = this.getNextChildPath(path);
|
|
4266
|
+
if (nextChildPath) {
|
|
4267
|
+
const child = this.instance.children.find((c) => c.path === nextChildPath);
|
|
4268
|
+
if (child) {
|
|
4269
|
+
const defaultLabel = getSchemaXOption(this.instance.schema, "categoriesDefaultLabel") ?? "Basic";
|
|
4270
|
+
const childSchemaType = getSchemaType(child.schema);
|
|
4271
|
+
const xCategory = getSchemaXOption(child.schema, "category");
|
|
4272
|
+
let categoryName;
|
|
4273
|
+
if (isSet(xCategory)) {
|
|
4274
|
+
categoryName = xCategory;
|
|
4275
|
+
} else if (childSchemaType === "object" || childSchemaType === "array") {
|
|
4276
|
+
const schemaTitle = getSchemaTitle(child.schema);
|
|
4277
|
+
categoryName = isSet(schemaTitle) ? schemaTitle : child.getKey();
|
|
4278
|
+
} else {
|
|
4279
|
+
categoryName = defaultLabel;
|
|
4280
|
+
}
|
|
4281
|
+
this.activeCategoryName = categoryName;
|
|
4282
|
+
this.refreshUI();
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
super.navigateTo(path);
|
|
4286
|
+
}
|
|
3880
4287
|
refreshEditors() {
|
|
3881
4288
|
while (this.control.childrenSlot.firstChild) {
|
|
3882
4289
|
this.control.childrenSlot.removeChild(this.control.childrenSlot.lastChild);
|
|
@@ -3981,6 +4388,17 @@ class EditorObjectNav extends EditorObject {
|
|
|
3981
4388
|
this.activeTabIndex = visibleIndices[0] ?? 0;
|
|
3982
4389
|
}
|
|
3983
4390
|
}
|
|
4391
|
+
navigateTo(path) {
|
|
4392
|
+
const nextChildPath = this.getNextChildPath(path);
|
|
4393
|
+
if (nextChildPath) {
|
|
4394
|
+
const childIndex = this.instance.children.findIndex((c) => c.path === nextChildPath);
|
|
4395
|
+
if (childIndex !== -1) {
|
|
4396
|
+
this.activeTabIndex = childIndex;
|
|
4397
|
+
this.refreshUI();
|
|
4398
|
+
}
|
|
4399
|
+
}
|
|
4400
|
+
super.navigateTo(path);
|
|
4401
|
+
}
|
|
3984
4402
|
refreshEditors() {
|
|
3985
4403
|
while (this.control.childrenSlot.firstChild) {
|
|
3986
4404
|
this.control.childrenSlot.removeChild(this.control.childrenSlot.lastChild);
|
|
@@ -4105,10 +4523,19 @@ class EditorArray extends Editor {
|
|
|
4105
4523
|
});
|
|
4106
4524
|
const btnGroup = this.theme.getBtnGroup();
|
|
4107
4525
|
deleteBtn.addEventListener("click", () => {
|
|
4108
|
-
const
|
|
4109
|
-
|
|
4526
|
+
const schemaConfirm = getSchemaXOption(this.instance.schema, "arrayDeleteConfirm");
|
|
4527
|
+
const globalConfirm = this.instance.jedison.options.arrayDeleteConfirm;
|
|
4528
|
+
const shouldConfirm = isSet(schemaConfirm) ? schemaConfirm : globalConfirm;
|
|
4529
|
+
const doDelete = () => {
|
|
4110
4530
|
this.activeItemIndex = clamp(index2 - 1, 0, this.instance.value.length - 1);
|
|
4111
4531
|
this.instance.deleteItem(index2, "user");
|
|
4532
|
+
};
|
|
4533
|
+
if (shouldConfirm) {
|
|
4534
|
+
if (window.confirm(this.instance.jedison.translator.translate("arrayConfirmDelete"))) {
|
|
4535
|
+
doDelete();
|
|
4536
|
+
}
|
|
4537
|
+
} else {
|
|
4538
|
+
doDelete();
|
|
4112
4539
|
}
|
|
4113
4540
|
});
|
|
4114
4541
|
moveUpBtn.addEventListener("click", () => {
|
|
@@ -4201,6 +4628,27 @@ class EditorArray extends Editor {
|
|
|
4201
4628
|
});
|
|
4202
4629
|
this.refreshAddBtn();
|
|
4203
4630
|
this.refreshJsonData();
|
|
4631
|
+
this.refreshLegendWarning();
|
|
4632
|
+
}
|
|
4633
|
+
refreshLegendWarning() {
|
|
4634
|
+
if (!this.control.legendText) return;
|
|
4635
|
+
const navWarning = getSchemaXOption(this.instance.schema, "navWarning") ?? true;
|
|
4636
|
+
const hasErrors = navWarning && this.instance.hasNestedValidationErrors();
|
|
4637
|
+
const existing = this.control.legendText.querySelector(".jedi-legend-warning");
|
|
4638
|
+
if (existing) existing.parentNode.removeChild(existing);
|
|
4639
|
+
if (hasErrors) {
|
|
4640
|
+
const warning = document.createElement("span");
|
|
4641
|
+
warning.classList.add("jedi-legend-warning");
|
|
4642
|
+
warning.textContent = "⚠";
|
|
4643
|
+
const navWarningMessage = getSchemaXOption(this.instance.schema, "navWarningMessage");
|
|
4644
|
+
if (navWarningMessage) warning.setAttribute("title", navWarningMessage);
|
|
4645
|
+
this.theme.styleLegendWarning(warning);
|
|
4646
|
+
this.control.legendText.appendChild(warning);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
showValidationErrors(errors, force = false) {
|
|
4650
|
+
super.showValidationErrors(errors, force);
|
|
4651
|
+
this.refreshLegendWarning();
|
|
4204
4652
|
}
|
|
4205
4653
|
}
|
|
4206
4654
|
class EditorArrayTuple extends EditorArray {
|
|
@@ -4275,20 +4723,22 @@ class EditorArrayTable extends EditorArray {
|
|
|
4275
4723
|
if (this.instance.children.length) {
|
|
4276
4724
|
const schemaItems = getSchemaItems(this.instance.schema);
|
|
4277
4725
|
const thTitle = this.theme.getTableHeader();
|
|
4278
|
-
if (schemaItems
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4726
|
+
if (schemaItems) {
|
|
4727
|
+
if (schemaItems.title) {
|
|
4728
|
+
const fakeLabel = this.theme.getFakeLabel({
|
|
4729
|
+
content: schemaItems.title
|
|
4730
|
+
});
|
|
4731
|
+
thTitle.appendChild(fakeLabel.label);
|
|
4732
|
+
}
|
|
4733
|
+
const schemaXInfo = getSchemaXOption(schemaItems, "info");
|
|
4734
|
+
if (isSet(schemaXInfo)) {
|
|
4735
|
+
const infoContent = this.getInfo(schemaItems);
|
|
4736
|
+
const info = this.theme.getInfo(infoContent);
|
|
4737
|
+
if (schemaXInfo.variant === "modal") {
|
|
4738
|
+
this.theme.infoAsModal(info, this.getIdFromPath(this.instance.path), infoContent);
|
|
4739
|
+
}
|
|
4740
|
+
thTitle.appendChild(info.container);
|
|
4290
4741
|
}
|
|
4291
|
-
thTitle.appendChild(info.container);
|
|
4292
4742
|
}
|
|
4293
4743
|
table.thead.appendChild(thTitle);
|
|
4294
4744
|
}
|
|
@@ -4508,6 +4958,45 @@ class EditorArrayChoices extends Editor {
|
|
|
4508
4958
|
const hasValidItemType = isSet(schemaItems) && isSet(schemaItemsType) && (validTypes.includes(schemaItemsType) || isArray(schemaItemsType) && schemaItemsType.some((type2) => validTypes.includes(type2)));
|
|
4509
4959
|
return hasChoicesFormat && choicesInstalled && isArrayType && isUniqueItems && hasTypes && hasValidItemType;
|
|
4510
4960
|
}
|
|
4961
|
+
init() {
|
|
4962
|
+
super.init();
|
|
4963
|
+
this.setupEnumSource();
|
|
4964
|
+
}
|
|
4965
|
+
setupEnumSource() {
|
|
4966
|
+
const enumSourceRaw = getSchemaXOption(this.instance.schema, "enumSource");
|
|
4967
|
+
if (!isSet(enumSourceRaw)) return;
|
|
4968
|
+
const enumSource = resolveInstancePath(this.instance.path, enumSourceRaw);
|
|
4969
|
+
const src = this.instance.jedison.getInstance(enumSource);
|
|
4970
|
+
if (src) this.enumSourceValues = src.getValue();
|
|
4971
|
+
this.instance.jedison.watch(enumSource, () => {
|
|
4972
|
+
if (!this.control) return;
|
|
4973
|
+
const s = this.instance.jedison.getInstance(enumSource);
|
|
4974
|
+
if (s) {
|
|
4975
|
+
this.enumSourceValues = s.getValue();
|
|
4976
|
+
this.refreshOptions();
|
|
4977
|
+
}
|
|
4978
|
+
});
|
|
4979
|
+
}
|
|
4980
|
+
getEnumSourceValues() {
|
|
4981
|
+
if (this.enumSourceValues !== void 0) {
|
|
4982
|
+
if (isArray(this.enumSourceValues)) return this.enumSourceValues;
|
|
4983
|
+
if (isObject(this.enumSourceValues)) return Object.keys(this.enumSourceValues);
|
|
4984
|
+
return [];
|
|
4985
|
+
}
|
|
4986
|
+
return this.instance.schema.items && this.instance.schema.items.enum || [];
|
|
4987
|
+
}
|
|
4988
|
+
refreshOptions() {
|
|
4989
|
+
if (!this.choicesInstance) return;
|
|
4990
|
+
const values = this.getEnumSourceValues();
|
|
4991
|
+
const currentValue = this.instance.getValue();
|
|
4992
|
+
const itemEnumTitles = getSchemaXOption(this.instance.schema.items || {}, "enumTitles") || [];
|
|
4993
|
+
const choices = values.map((item, index2) => ({
|
|
4994
|
+
value: item,
|
|
4995
|
+
label: itemEnumTitles[index2] || item,
|
|
4996
|
+
selected: isArray(currentValue) && currentValue.includes(item)
|
|
4997
|
+
}));
|
|
4998
|
+
this.choicesInstance.setChoices(choices, "value", "label", true);
|
|
4999
|
+
}
|
|
4511
5000
|
build() {
|
|
4512
5001
|
this.control = this.theme.getSelectControl({
|
|
4513
5002
|
title: this.getTitle(),
|
|
@@ -4522,8 +5011,8 @@ class EditorArrayChoices extends Editor {
|
|
|
4522
5011
|
this.control.input.setAttribute("multiple", "");
|
|
4523
5012
|
try {
|
|
4524
5013
|
const value = this.instance.getValue();
|
|
4525
|
-
const itemEnum = this.
|
|
4526
|
-
const itemEnumTitles = getSchemaXOption(this.instance.schema.items, "enumTitles")
|
|
5014
|
+
const itemEnum = this.getEnumSourceValues();
|
|
5015
|
+
const itemEnumTitles = getSchemaXOption(this.instance.schema.items || {}, "enumTitles") || [];
|
|
4527
5016
|
const choicesOptions = getSchemaXOption(this.instance.schema, "choicesOptions") ?? {};
|
|
4528
5017
|
if (this.choicesInstance) {
|
|
4529
5018
|
this.choicesInstance.destroy();
|
|
@@ -4580,6 +5069,17 @@ class EditorArrayNav extends EditorArray {
|
|
|
4580
5069
|
const hasNavFormat = regex.test(format2);
|
|
4581
5070
|
return getSchemaType(schema) === "array" && hasNavFormat;
|
|
4582
5071
|
}
|
|
5072
|
+
navigateTo(path) {
|
|
5073
|
+
const nextChildPath = this.getNextChildPath(path);
|
|
5074
|
+
if (nextChildPath) {
|
|
5075
|
+
const childIndex = this.instance.children.findIndex((c) => c.path === nextChildPath);
|
|
5076
|
+
if (childIndex !== -1) {
|
|
5077
|
+
this.activeItemIndex = childIndex;
|
|
5078
|
+
this.refreshUI();
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
super.navigateTo(path);
|
|
5082
|
+
}
|
|
4583
5083
|
addEventListeners() {
|
|
4584
5084
|
this.control.addBtn.addEventListener("click", () => {
|
|
4585
5085
|
this.activeItemIndex = this.instance.value.length;
|
|
@@ -4678,6 +5178,7 @@ class EditorMultiple extends Editor {
|
|
|
4678
5178
|
}
|
|
4679
5179
|
build() {
|
|
4680
5180
|
this.switcherInput = getSchemaXOption(this.instance.schema, "switcherInput") ?? this.instance.jedison.options.switcherInput;
|
|
5181
|
+
this.embedSwitcher = getSchemaXOption(this.instance.schema, "embedSwitcher") ?? this.instance.jedison.options.embedSwitcher;
|
|
4681
5182
|
this.control = this.theme.getMultipleControl({
|
|
4682
5183
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
4683
5184
|
id: this.getIdFromPath(this.instance.path),
|
|
@@ -4686,6 +5187,9 @@ class EditorMultiple extends Editor {
|
|
|
4686
5187
|
switcher: this.switcherInput,
|
|
4687
5188
|
readOnly: this.instance.isReadOnly()
|
|
4688
5189
|
});
|
|
5190
|
+
if (this.embedSwitcher) {
|
|
5191
|
+
this.control.header.style.display = "none";
|
|
5192
|
+
}
|
|
4689
5193
|
}
|
|
4690
5194
|
adaptForTable(td) {
|
|
4691
5195
|
this.theme.adaptForTableMultipleControl(this.control, td);
|
|
@@ -4710,6 +5214,17 @@ class EditorMultiple extends Editor {
|
|
|
4710
5214
|
this.refreshDisabledState();
|
|
4711
5215
|
this.control.childrenSlot.innerHTML = "";
|
|
4712
5216
|
this.control.childrenSlot.appendChild(this.instance.activeInstance.ui.control.container);
|
|
5217
|
+
if (this.embedSwitcher) {
|
|
5218
|
+
const slot = this.instance.activeInstance.ui.control.switcherSlot;
|
|
5219
|
+
if (slot) {
|
|
5220
|
+
slot.innerHTML = "";
|
|
5221
|
+
slot.appendChild(this.control.switcher.container);
|
|
5222
|
+
this.control.header.style.display = "none";
|
|
5223
|
+
} else {
|
|
5224
|
+
this.control.header.style.display = "";
|
|
5225
|
+
this.control.header.appendChild(this.control.switcher.container);
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
4713
5228
|
if (this.switcherInput === "select") {
|
|
4714
5229
|
this.control.switcher.input.value = this.instance.index;
|
|
4715
5230
|
}
|
|
@@ -5079,6 +5594,38 @@ class EditorNumberRaty extends EditorNumber {
|
|
|
5079
5594
|
this.raty.score(this.instance.getValue());
|
|
5080
5595
|
}
|
|
5081
5596
|
}
|
|
5597
|
+
class EditorAnyJson extends Editor {
|
|
5598
|
+
static resolves(schema) {
|
|
5599
|
+
return getSchemaXOption(schema, "format") === "json";
|
|
5600
|
+
}
|
|
5601
|
+
build() {
|
|
5602
|
+
this.control = this.theme.getTextareaControl({
|
|
5603
|
+
title: this.getTitle(),
|
|
5604
|
+
description: this.getDescription(),
|
|
5605
|
+
id: this.getIdFromPath(this.instance.path),
|
|
5606
|
+
titleIconClass: getSchemaXOption(this.instance.schema, "titleIconClass"),
|
|
5607
|
+
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
5608
|
+
info: this.getInfo()
|
|
5609
|
+
});
|
|
5610
|
+
this.jsonErrorEl = document.createElement("div");
|
|
5611
|
+
this.jsonErrorEl.style.color = "red";
|
|
5612
|
+
this.control.container.appendChild(this.jsonErrorEl);
|
|
5613
|
+
}
|
|
5614
|
+
addEventListeners() {
|
|
5615
|
+
this.control.input.addEventListener("change", () => {
|
|
5616
|
+
try {
|
|
5617
|
+
const parsed = JSON.parse(this.control.input.value);
|
|
5618
|
+
this.jsonErrorEl.textContent = "";
|
|
5619
|
+
this.instance.setValue(parsed, true, "user");
|
|
5620
|
+
} catch (e) {
|
|
5621
|
+
this.jsonErrorEl.textContent = e.message;
|
|
5622
|
+
}
|
|
5623
|
+
});
|
|
5624
|
+
}
|
|
5625
|
+
refreshUI() {
|
|
5626
|
+
this.control.input.value = JSON.stringify(this.instance.getValue(), null, 2);
|
|
5627
|
+
}
|
|
5628
|
+
}
|
|
5082
5629
|
class EditorArrayCheckboxes extends Editor {
|
|
5083
5630
|
static resolves(schema) {
|
|
5084
5631
|
const schemaType = getSchemaType(schema);
|
|
@@ -5088,22 +5635,93 @@ class EditorArrayCheckboxes extends Editor {
|
|
|
5088
5635
|
const isUniqueItems = getSchemaUniqueItems(schema) === true;
|
|
5089
5636
|
const hasEnum = isSet(schemaItems) && isSet(getSchemaEnum(schema.items));
|
|
5090
5637
|
const hasTypes = isSet(schemaItems) && isSet(schemaItemsType);
|
|
5638
|
+
const hasEnumSource = isSet(getSchemaXOption(schema, "enumSource"));
|
|
5091
5639
|
const validTypes = ["string", "number", "integer"];
|
|
5092
5640
|
const hasValidItemType = isSet(schemaItems) && isSet(schemaItemsType) && (validTypes.includes(schemaItemsType) || isArray(schemaItemsType) && schemaItemsType.some((type2) => validTypes.includes(type2)));
|
|
5093
|
-
return isArrayType && isUniqueItems && hasEnum && hasTypes && hasValidItemType;
|
|
5641
|
+
return isArrayType && isUniqueItems && (hasEnumSource || hasEnum && hasTypes && hasValidItemType);
|
|
5642
|
+
}
|
|
5643
|
+
init() {
|
|
5644
|
+
super.init();
|
|
5645
|
+
this.setupEnumSource();
|
|
5646
|
+
}
|
|
5647
|
+
setupEnumSource() {
|
|
5648
|
+
const enumSourceRaw = getSchemaXOption(this.instance.schema, "enumSource");
|
|
5649
|
+
if (!isSet(enumSourceRaw)) return;
|
|
5650
|
+
const enumSource = resolveInstancePath(this.instance.path, enumSourceRaw);
|
|
5651
|
+
const src = this.instance.jedison.getInstance(enumSource);
|
|
5652
|
+
if (src) this.enumSourceValues = src.getValue();
|
|
5653
|
+
this.instance.jedison.watch(enumSource, () => {
|
|
5654
|
+
if (!this.control) return;
|
|
5655
|
+
const s = this.instance.jedison.getInstance(enumSource);
|
|
5656
|
+
if (s) {
|
|
5657
|
+
this.enumSourceValues = s.getValue();
|
|
5658
|
+
this.refreshOptions();
|
|
5659
|
+
}
|
|
5660
|
+
});
|
|
5661
|
+
}
|
|
5662
|
+
getEnumSourceValues() {
|
|
5663
|
+
if (this.enumSourceValues !== void 0) {
|
|
5664
|
+
if (isArray(this.enumSourceValues)) return this.enumSourceValues;
|
|
5665
|
+
if (isObject(this.enumSourceValues)) return Object.keys(this.enumSourceValues);
|
|
5666
|
+
return [];
|
|
5667
|
+
}
|
|
5668
|
+
return getSchemaEnum(this.instance.schema.items) || [];
|
|
5094
5669
|
}
|
|
5095
5670
|
build() {
|
|
5671
|
+
const values = this.getEnumSourceValues();
|
|
5672
|
+
const schemaItems = this.instance.schema.items || {};
|
|
5673
|
+
const titles = getSchemaXOption(schemaItems, "enumTitles") || values;
|
|
5096
5674
|
this.control = this.theme.getCheckboxesControl({
|
|
5097
5675
|
title: this.getTitle(),
|
|
5098
5676
|
description: this.getDescription(),
|
|
5099
|
-
values
|
|
5100
|
-
titles
|
|
5677
|
+
values,
|
|
5678
|
+
titles,
|
|
5101
5679
|
id: this.getIdFromPath(this.instance.path),
|
|
5102
5680
|
titleHidden: getSchemaXOption(this.instance.schema, "titleHidden"),
|
|
5103
5681
|
inline: getSchemaXOption(this.instance.schema, "format") === "checkboxes-inline",
|
|
5104
5682
|
info: this.getInfo()
|
|
5105
5683
|
});
|
|
5106
5684
|
}
|
|
5685
|
+
refreshOptions() {
|
|
5686
|
+
const values = this.getEnumSourceValues();
|
|
5687
|
+
const schemaItems = this.instance.schema.items || {};
|
|
5688
|
+
const titles = getSchemaXOption(schemaItems, "enumTitles") || values;
|
|
5689
|
+
const id = this.getIdFromPath(this.instance.path);
|
|
5690
|
+
const messagesId = id + "-messages";
|
|
5691
|
+
const descriptionId = id + "-description";
|
|
5692
|
+
const describedBy = messagesId + " " + descriptionId;
|
|
5693
|
+
this.control.checkboxControls.forEach((cc) => {
|
|
5694
|
+
if (cc.parentNode) cc.parentNode.removeChild(cc);
|
|
5695
|
+
});
|
|
5696
|
+
this.control.checkboxes = [];
|
|
5697
|
+
this.control.labels = [];
|
|
5698
|
+
this.control.checkboxControls = [];
|
|
5699
|
+
this.control.labelTexts = [];
|
|
5700
|
+
values.forEach((value, index2) => {
|
|
5701
|
+
const checkboxId = id + "-" + index2;
|
|
5702
|
+
const checkboxControl = document.createElement("div");
|
|
5703
|
+
const checkbox = document.createElement("input");
|
|
5704
|
+
const label = document.createElement("label");
|
|
5705
|
+
const labelText = document.createElement("span");
|
|
5706
|
+
checkbox.setAttribute("type", "checkbox");
|
|
5707
|
+
checkbox.setAttribute("id", checkboxId);
|
|
5708
|
+
checkbox.setAttribute("name", id);
|
|
5709
|
+
checkbox.setAttribute("value", value);
|
|
5710
|
+
checkbox.setAttribute("aria-describedby", describedBy);
|
|
5711
|
+
label.setAttribute("for", checkboxId);
|
|
5712
|
+
labelText.textContent = titles && titles[index2] !== void 0 ? titles[index2] : value;
|
|
5713
|
+
checkboxControl.appendChild(checkbox);
|
|
5714
|
+
checkboxControl.appendChild(label);
|
|
5715
|
+
label.appendChild(labelText);
|
|
5716
|
+
this.control.checkboxes.push(checkbox);
|
|
5717
|
+
this.control.labels.push(label);
|
|
5718
|
+
this.control.labelTexts.push(labelText);
|
|
5719
|
+
this.control.checkboxControls.push(checkboxControl);
|
|
5720
|
+
this.control.fieldset.insertBefore(checkboxControl, this.control.description);
|
|
5721
|
+
});
|
|
5722
|
+
this.addEventListeners();
|
|
5723
|
+
this.refreshUI();
|
|
5724
|
+
}
|
|
5107
5725
|
adaptForTable(td) {
|
|
5108
5726
|
this.theme.adaptForTableCheckboxesControl(this.control, td);
|
|
5109
5727
|
}
|
|
@@ -5136,6 +5754,15 @@ class EditorArrayCheckboxes extends Editor {
|
|
|
5136
5754
|
checkbox.checked = value.includes(checkbox.value);
|
|
5137
5755
|
});
|
|
5138
5756
|
}
|
|
5757
|
+
setAriaInvalid(invalid) {
|
|
5758
|
+
this.control.checkboxes.forEach((checkbox) => {
|
|
5759
|
+
if (invalid) {
|
|
5760
|
+
checkbox.setAttribute("aria-invalid", "true");
|
|
5761
|
+
} else {
|
|
5762
|
+
checkbox.removeAttribute("aria-invalid");
|
|
5763
|
+
}
|
|
5764
|
+
});
|
|
5765
|
+
}
|
|
5139
5766
|
}
|
|
5140
5767
|
class EditorNumberRange extends EditorNumber {
|
|
5141
5768
|
static resolves(schema) {
|
|
@@ -5310,6 +5937,7 @@ class UiResolver {
|
|
|
5310
5937
|
EditorNumberInputNullable,
|
|
5311
5938
|
EditorMultiple,
|
|
5312
5939
|
EditorIfThenElse,
|
|
5940
|
+
EditorAnyJson,
|
|
5313
5941
|
EditorRadios,
|
|
5314
5942
|
EditorBooleanCheckbox,
|
|
5315
5943
|
EditorBooleanSelect,
|
|
@@ -5648,14 +6276,17 @@ class Jedison extends EventEmitter {
|
|
|
5648
6276
|
btnContents: true,
|
|
5649
6277
|
btnIcons: true,
|
|
5650
6278
|
arrayDelete: true,
|
|
6279
|
+
arrayDeleteConfirm: true,
|
|
5651
6280
|
arrayMove: true,
|
|
5652
6281
|
arrayAdd: true,
|
|
6282
|
+
objectAdd: true,
|
|
5653
6283
|
arrayButtonsPosition: "left",
|
|
5654
6284
|
startCollapsed: false,
|
|
5655
6285
|
deactivateNonRequired: false,
|
|
5656
6286
|
schema: {},
|
|
5657
6287
|
showErrors: "change",
|
|
5658
6288
|
switcherInput: "select",
|
|
6289
|
+
embedSwitcher: false,
|
|
5659
6290
|
data: void 0,
|
|
5660
6291
|
assertFormat: false,
|
|
5661
6292
|
customEditors: [],
|
|
@@ -5680,6 +6311,7 @@ class Jedison extends EventEmitter {
|
|
|
5680
6311
|
enforceMinItems: true,
|
|
5681
6312
|
enforceMaxItems: true,
|
|
5682
6313
|
enforceEnum: true,
|
|
6314
|
+
subErrors: false,
|
|
5683
6315
|
debug: false
|
|
5684
6316
|
}, options);
|
|
5685
6317
|
this.rootName = "#";
|
|
@@ -5747,7 +6379,8 @@ class Jedison extends EventEmitter {
|
|
|
5747
6379
|
refParser: this.refParser,
|
|
5748
6380
|
assertFormat: this.options.assertFormat,
|
|
5749
6381
|
translator: this.translator,
|
|
5750
|
-
constraints: this.options.constraints
|
|
6382
|
+
constraints: this.options.constraints,
|
|
6383
|
+
subErrors: this.options.subErrors
|
|
5751
6384
|
});
|
|
5752
6385
|
this.root = this.createInstance({
|
|
5753
6386
|
jedison: this,
|
|
@@ -6010,6 +6643,14 @@ class Jedison extends EventEmitter {
|
|
|
6010
6643
|
getInstance(path) {
|
|
6011
6644
|
return this.instances.get(path);
|
|
6012
6645
|
}
|
|
6646
|
+
/**
|
|
6647
|
+
* Navigates to a specific instance by path, activating any ancestor nav/categories tabs as needed.
|
|
6648
|
+
* @param {string} path - The instance path (e.g. '#/address/street')
|
|
6649
|
+
*/
|
|
6650
|
+
navigateTo(path) {
|
|
6651
|
+
if (!this.isEditor) return;
|
|
6652
|
+
this.root.ui.navigateTo(path);
|
|
6653
|
+
}
|
|
6013
6654
|
/**
|
|
6014
6655
|
* Disables the root instance and it's children user interfaces
|
|
6015
6656
|
*/
|
|
@@ -6299,6 +6940,8 @@ class Theme {
|
|
|
6299
6940
|
const dummyInputId = "legend-dummy-input-" + config.id;
|
|
6300
6941
|
left.classList.add("jedi-editor-legend-left");
|
|
6301
6942
|
right.classList.add("jedi-editor-legend-right");
|
|
6943
|
+
right.style.display = "flex";
|
|
6944
|
+
right.style.alignItems = "center";
|
|
6302
6945
|
legend.classList.add("jedi-editor-legend");
|
|
6303
6946
|
legend.style.fontSize = "inherit";
|
|
6304
6947
|
legend.setAttribute("aria-labelledby", legendLabelId);
|
|
@@ -6514,6 +7157,18 @@ class Theme {
|
|
|
6514
7157
|
});
|
|
6515
7158
|
return toggle;
|
|
6516
7159
|
}
|
|
7160
|
+
getQuickAddPropertyToggle(config) {
|
|
7161
|
+
const toggle = this.getButton(config);
|
|
7162
|
+
toggle.classList.add("jedi-quick-add-property-toggle");
|
|
7163
|
+
toggle.addEventListener("click", () => {
|
|
7164
|
+
if (config.propertiesContainer.open) {
|
|
7165
|
+
config.propertiesContainer.close();
|
|
7166
|
+
} else {
|
|
7167
|
+
config.propertiesContainer.showModal();
|
|
7168
|
+
}
|
|
7169
|
+
});
|
|
7170
|
+
return toggle;
|
|
7171
|
+
}
|
|
6517
7172
|
/**
|
|
6518
7173
|
* Container that will collapse and expand to show and hide it contents
|
|
6519
7174
|
*/
|
|
@@ -6576,6 +7231,17 @@ class Theme {
|
|
|
6576
7231
|
});
|
|
6577
7232
|
return html;
|
|
6578
7233
|
}
|
|
7234
|
+
getQuickAddPropertySlot(config) {
|
|
7235
|
+
const html = document.createElement("dialog");
|
|
7236
|
+
html.classList.add("jedi-quick-add-property-slot");
|
|
7237
|
+
html.setAttribute("id", config.id);
|
|
7238
|
+
window.addEventListener("click", (event) => {
|
|
7239
|
+
if (event.target === html) {
|
|
7240
|
+
html.close();
|
|
7241
|
+
}
|
|
7242
|
+
});
|
|
7243
|
+
return html;
|
|
7244
|
+
}
|
|
6579
7245
|
/**
|
|
6580
7246
|
* Container for properties editing elements like property activators
|
|
6581
7247
|
*/
|
|
@@ -6928,17 +7594,25 @@ class Theme {
|
|
|
6928
7594
|
collapse,
|
|
6929
7595
|
startCollapsed: config.startCollapsed
|
|
6930
7596
|
});
|
|
6931
|
-
const
|
|
7597
|
+
const quickAddPropertyContainer = this.getQuickAddPropertySlot({
|
|
7598
|
+
id: "quick-add-property-slot-" + config.id
|
|
7599
|
+
});
|
|
7600
|
+
const quickAddPropertyControl = this.getInputControl({
|
|
6932
7601
|
type: "text",
|
|
6933
|
-
id: "jedi-add-property-input-" + config.id,
|
|
7602
|
+
id: "jedi-quick-add-property-input-" + config.id,
|
|
6934
7603
|
title: config.addPropertyContent
|
|
6935
7604
|
});
|
|
6936
|
-
const
|
|
7605
|
+
const quickAddPropertyBtn = this.getAddPropertyButton({
|
|
6937
7606
|
content: config.addPropertyContent,
|
|
6938
7607
|
icon: "add"
|
|
6939
7608
|
});
|
|
7609
|
+
const quickAddPropertyToggle = this.getQuickAddPropertyToggle({
|
|
7610
|
+
content: config.addPropertyContent,
|
|
7611
|
+
icon: "add",
|
|
7612
|
+
propertiesContainer: quickAddPropertyContainer
|
|
7613
|
+
});
|
|
6940
7614
|
const fieldset = this.getFieldset();
|
|
6941
|
-
const { legend, infoContainer, legendText } = this.getLegend({
|
|
7615
|
+
const { legend, infoContainer, legendText, right } = this.getLegend({
|
|
6942
7616
|
content: config.title,
|
|
6943
7617
|
id: config.id,
|
|
6944
7618
|
titleHidden: config.titleHidden
|
|
@@ -6946,9 +7620,13 @@ class Theme {
|
|
|
6946
7620
|
if (((_a = config == null ? void 0 : config.info) == null ? void 0 : _a.variant) === "modal") {
|
|
6947
7621
|
this.infoAsModal(info, config.id, config.info);
|
|
6948
7622
|
}
|
|
6949
|
-
addPropertyBtn.classList.add("jedi-object-add");
|
|
6950
7623
|
container.appendChild(fieldset);
|
|
6951
7624
|
container.appendChild(propertiesContainer);
|
|
7625
|
+
container.appendChild(quickAddPropertyContainer);
|
|
7626
|
+
if (config.addProperty) {
|
|
7627
|
+
quickAddPropertyContainer.appendChild(quickAddPropertyControl.container);
|
|
7628
|
+
quickAddPropertyContainer.appendChild(quickAddPropertyBtn);
|
|
7629
|
+
}
|
|
6952
7630
|
if (config.editJsonData) {
|
|
6953
7631
|
container.appendChild(jsonData.dialog);
|
|
6954
7632
|
}
|
|
@@ -6962,18 +7640,19 @@ class Theme {
|
|
|
6962
7640
|
body.appendChild(description);
|
|
6963
7641
|
}
|
|
6964
7642
|
body.appendChild(messages);
|
|
7643
|
+
const switcherSlot = document.createElement("div");
|
|
7644
|
+
switcherSlot.classList.add("jedi-switcher-slot");
|
|
6965
7645
|
if (config.readOnly === false) {
|
|
6966
|
-
|
|
7646
|
+
right.appendChild(switcherSlot);
|
|
7647
|
+
right.appendChild(actions);
|
|
6967
7648
|
}
|
|
6968
7649
|
body.appendChild(childrenSlot);
|
|
6969
|
-
if (config.addProperty) {
|
|
6970
|
-
propertiesContainer.appendChild(addPropertyControl.container);
|
|
6971
|
-
propertiesContainer.appendChild(addPropertyBtn);
|
|
6972
|
-
propertiesContainer.appendChild(document.createElement("hr"));
|
|
6973
|
-
}
|
|
6974
7650
|
if (config.editJsonData) {
|
|
6975
7651
|
actions.appendChild(jsonData.toggle);
|
|
6976
7652
|
}
|
|
7653
|
+
if (config.addProperty) {
|
|
7654
|
+
actions.appendChild(quickAddPropertyToggle);
|
|
7655
|
+
}
|
|
6977
7656
|
if (config.enablePropertiesToggle) {
|
|
6978
7657
|
actions.appendChild(propertiesToggle);
|
|
6979
7658
|
propertiesContainer.appendChild(ariaLive);
|
|
@@ -6994,13 +7673,17 @@ class Theme {
|
|
|
6994
7673
|
propertiesToggle,
|
|
6995
7674
|
jsonData,
|
|
6996
7675
|
propertiesContainer,
|
|
6997
|
-
|
|
6998
|
-
|
|
7676
|
+
quickAddPropertyContainer,
|
|
7677
|
+
quickAddPropertyControl,
|
|
7678
|
+
quickAddPropertyBtn,
|
|
7679
|
+
quickAddPropertyToggle,
|
|
6999
7680
|
ariaLive,
|
|
7000
7681
|
propertiesActivators,
|
|
7001
7682
|
legend,
|
|
7002
7683
|
legendText,
|
|
7003
|
-
infoContainer
|
|
7684
|
+
infoContainer,
|
|
7685
|
+
right,
|
|
7686
|
+
switcherSlot
|
|
7004
7687
|
};
|
|
7005
7688
|
}
|
|
7006
7689
|
/**
|
|
@@ -7021,7 +7704,7 @@ class Theme {
|
|
|
7021
7704
|
});
|
|
7022
7705
|
const fieldset = this.getFieldset();
|
|
7023
7706
|
const info = this.getInfo(config.info);
|
|
7024
|
-
const { legend, legendText, infoContainer } = this.getLegend({
|
|
7707
|
+
const { legend, legendText, infoContainer, right } = this.getLegend({
|
|
7025
7708
|
content: config.title,
|
|
7026
7709
|
id: config.id,
|
|
7027
7710
|
titleHidden: config.titleHidden
|
|
@@ -7061,7 +7744,12 @@ class Theme {
|
|
|
7061
7744
|
body.appendChild(description);
|
|
7062
7745
|
}
|
|
7063
7746
|
body.appendChild(messages);
|
|
7064
|
-
|
|
7747
|
+
const switcherSlot = document.createElement("div");
|
|
7748
|
+
switcherSlot.classList.add("jedi-switcher-slot");
|
|
7749
|
+
if (config.readOnly === false) {
|
|
7750
|
+
right.appendChild(switcherSlot);
|
|
7751
|
+
right.appendChild(actions);
|
|
7752
|
+
}
|
|
7065
7753
|
actions.appendChild(btnGroup);
|
|
7066
7754
|
if (config.editJsonData) {
|
|
7067
7755
|
btnGroup.appendChild(jsonData.toggle);
|
|
@@ -7085,7 +7773,8 @@ class Theme {
|
|
|
7085
7773
|
addBtn,
|
|
7086
7774
|
jsonData,
|
|
7087
7775
|
legend,
|
|
7088
|
-
legendText
|
|
7776
|
+
legendText,
|
|
7777
|
+
switcherSlot
|
|
7089
7778
|
};
|
|
7090
7779
|
}
|
|
7091
7780
|
getArrayItem(config = {}) {
|
|
@@ -7121,8 +7810,10 @@ class Theme {
|
|
|
7121
7810
|
const messages = this.getMessagesSlot();
|
|
7122
7811
|
const childrenSlot = this.getChildrenSlot();
|
|
7123
7812
|
const randomId = generateRandomID(5);
|
|
7813
|
+
const knownSwitchers = ["select", "radios", "radios-inline"];
|
|
7814
|
+
const switcherType = knownSwitchers.includes(config.switcher) ? config.switcher : "select";
|
|
7124
7815
|
let switcher;
|
|
7125
|
-
if (
|
|
7816
|
+
if (switcherType === "select") {
|
|
7126
7817
|
switcher = this.getSwitcherSelect({
|
|
7127
7818
|
values: config.switcherOptionValues,
|
|
7128
7819
|
titles: config.switcherOptionsLabels,
|
|
@@ -7130,10 +7821,11 @@ class Theme {
|
|
|
7130
7821
|
id: config.id + "-switcher-" + randomId,
|
|
7131
7822
|
label: config.id + "-switcher-" + randomId,
|
|
7132
7823
|
titleHidden: true,
|
|
7133
|
-
readOnly: config.readOnly
|
|
7824
|
+
readOnly: config.readOnly,
|
|
7825
|
+
noSpacing: true
|
|
7134
7826
|
});
|
|
7135
7827
|
}
|
|
7136
|
-
if (
|
|
7828
|
+
if (switcherType === "radios" || switcherType === "radios-inline") {
|
|
7137
7829
|
switcher = this.getSwitcherRadios({
|
|
7138
7830
|
values: config.switcherOptionValues,
|
|
7139
7831
|
titles: config.switcherOptionsLabels,
|
|
@@ -7142,7 +7834,8 @@ class Theme {
|
|
|
7142
7834
|
label: config.id + "-switcher-" + randomId,
|
|
7143
7835
|
titleHidden: true,
|
|
7144
7836
|
readOnly: config.readOnly,
|
|
7145
|
-
inline:
|
|
7837
|
+
inline: switcherType === "radios-inline",
|
|
7838
|
+
noSpacing: true
|
|
7146
7839
|
});
|
|
7147
7840
|
}
|
|
7148
7841
|
switcher.container.classList.add("jedi-switcher");
|
|
@@ -7680,6 +8373,8 @@ class Theme {
|
|
|
7680
8373
|
tabList.classList.add("jedi-nav-list");
|
|
7681
8374
|
return tabList;
|
|
7682
8375
|
}
|
|
8376
|
+
styleLegendWarning(span) {
|
|
8377
|
+
}
|
|
7683
8378
|
/**
|
|
7684
8379
|
* A Tab is a wrapper for content
|
|
7685
8380
|
*/
|
|
@@ -7991,7 +8686,9 @@ class ThemeBootstrap3 extends Theme {
|
|
|
7991
8686
|
getSelectControl(config) {
|
|
7992
8687
|
const control = super.getSelectControl(config);
|
|
7993
8688
|
const { container, input, label } = control;
|
|
7994
|
-
|
|
8689
|
+
if (!config.noSpacing) {
|
|
8690
|
+
container.classList.add("form-group");
|
|
8691
|
+
}
|
|
7995
8692
|
input.classList.add("form-control");
|
|
7996
8693
|
if (config.titleHidden) {
|
|
7997
8694
|
this.visuallyHidden(label);
|
|
@@ -8091,10 +8788,8 @@ class ThemeBootstrap3 extends Theme {
|
|
|
8091
8788
|
setTabPaneAttributes(element, active, id) {
|
|
8092
8789
|
super.setTabPaneAttributes(element, active, id);
|
|
8093
8790
|
element.classList.add("tab-pane");
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
element.classList.add("active");
|
|
8097
|
-
}
|
|
8791
|
+
element.classList.toggle("in", active);
|
|
8792
|
+
element.classList.toggle("active", active);
|
|
8098
8793
|
}
|
|
8099
8794
|
infoAsModal(info, id, config = {}) {
|
|
8100
8795
|
const modal = document.createElement("div");
|
|
@@ -8291,7 +8986,9 @@ class ThemeBootstrap4 extends Theme {
|
|
|
8291
8986
|
getRadiosControl(config) {
|
|
8292
8987
|
const control = super.getRadiosControl(config);
|
|
8293
8988
|
const { container, fieldset, radios, labels, labelTexts, radioControls, description, messages } = control;
|
|
8294
|
-
|
|
8989
|
+
if (!config.noSpacing) {
|
|
8990
|
+
container.classList.add("form-group");
|
|
8991
|
+
}
|
|
8295
8992
|
radioControls.forEach((radioControl, index2) => {
|
|
8296
8993
|
radioControl.classList.add("form-check");
|
|
8297
8994
|
radios[index2].classList.add("form-check-input");
|
|
@@ -8363,7 +9060,9 @@ class ThemeBootstrap4 extends Theme {
|
|
|
8363
9060
|
getSelectControl(config) {
|
|
8364
9061
|
const control = super.getSelectControl(config);
|
|
8365
9062
|
const { container, input } = control;
|
|
8366
|
-
|
|
9063
|
+
if (!config.noSpacing) {
|
|
9064
|
+
container.classList.add("form-group");
|
|
9065
|
+
}
|
|
8367
9066
|
input.classList.add("form-control");
|
|
8368
9067
|
return control;
|
|
8369
9068
|
}
|
|
@@ -8468,9 +9167,7 @@ class ThemeBootstrap4 extends Theme {
|
|
|
8468
9167
|
setTabPaneAttributes(element, active, id) {
|
|
8469
9168
|
super.setTabPaneAttributes(element, active, id);
|
|
8470
9169
|
element.classList.add("tab-pane");
|
|
8471
|
-
|
|
8472
|
-
element.classList.add("active");
|
|
8473
|
-
}
|
|
9170
|
+
element.classList.toggle("active", active);
|
|
8474
9171
|
}
|
|
8475
9172
|
infoAsModal(info, id, config = {}) {
|
|
8476
9173
|
const modal = document.createElement("div");
|
|
@@ -8572,6 +9269,9 @@ class ThemeBootstrap5 extends Theme {
|
|
|
8572
9269
|
legend.classList.add("py-2");
|
|
8573
9270
|
return superLegend;
|
|
8574
9271
|
}
|
|
9272
|
+
styleLegendWarning(span) {
|
|
9273
|
+
span.classList.add("ms-1");
|
|
9274
|
+
}
|
|
8575
9275
|
getLabel(config) {
|
|
8576
9276
|
const labelObj = super.getLabel(config);
|
|
8577
9277
|
if (labelObj.icon.classList) {
|
|
@@ -8670,7 +9370,9 @@ class ThemeBootstrap5 extends Theme {
|
|
|
8670
9370
|
getRadiosControl(config) {
|
|
8671
9371
|
const control = super.getRadiosControl(config);
|
|
8672
9372
|
const { container, fieldset, radios, labels, labelTexts, radioControls, description, messages } = control;
|
|
8673
|
-
|
|
9373
|
+
if (!config.noSpacing) {
|
|
9374
|
+
container.classList.add("mb-3");
|
|
9375
|
+
}
|
|
8674
9376
|
radioControls.forEach((radioControl, index2) => {
|
|
8675
9377
|
radioControl.classList.add("form-check");
|
|
8676
9378
|
radios[index2].classList.add("form-check-input");
|
|
@@ -8735,7 +9437,9 @@ class ThemeBootstrap5 extends Theme {
|
|
|
8735
9437
|
getSelectControl(config) {
|
|
8736
9438
|
const control = super.getSelectControl(config);
|
|
8737
9439
|
const { container, input } = control;
|
|
8738
|
-
|
|
9440
|
+
if (!config.noSpacing) {
|
|
9441
|
+
container.classList.add("mb-3");
|
|
9442
|
+
}
|
|
8739
9443
|
input.classList.add("form-select");
|
|
8740
9444
|
return control;
|
|
8741
9445
|
}
|
|
@@ -8837,9 +9541,7 @@ class ThemeBootstrap5 extends Theme {
|
|
|
8837
9541
|
setTabPaneAttributes(element, active, id) {
|
|
8838
9542
|
super.setTabPaneAttributes(element, active, id);
|
|
8839
9543
|
element.classList.add("tab-pane");
|
|
8840
|
-
|
|
8841
|
-
element.classList.add("active");
|
|
8842
|
-
}
|
|
9544
|
+
element.classList.toggle("active", active);
|
|
8843
9545
|
}
|
|
8844
9546
|
infoAsModal(info, id, config = {}) {
|
|
8845
9547
|
const modal = document.createElement("div");
|