@elle96/ng-json-schema-manager 0.2.1 → 0.3.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.
|
@@ -579,11 +579,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
579
579
|
}]
|
|
580
580
|
}] });
|
|
581
581
|
|
|
582
|
+
const DEFAULT_LABELS = {
|
|
583
|
+
formTitle: 'Form',
|
|
584
|
+
resolving: 'Resolving schema…',
|
|
585
|
+
schemaErrorsTitle: 'Schema errors',
|
|
586
|
+
schemaErrorsHint: 'The schema has structural issues. Fix them to get a valid form.',
|
|
587
|
+
addItem: 'Add item',
|
|
588
|
+
arrayItem: 'Item {n}',
|
|
589
|
+
remove: 'Remove',
|
|
590
|
+
add: 'Add',
|
|
591
|
+
addProperty: 'Add property',
|
|
592
|
+
propertyName: 'Property name',
|
|
593
|
+
noItems: 'No items yet — click "Add item" to start.',
|
|
594
|
+
mustContain: 'Must contain matching item(s)',
|
|
595
|
+
min: 'min {n}',
|
|
596
|
+
max: 'max {n}',
|
|
597
|
+
option: 'Option {n}',
|
|
598
|
+
section: 'Section {n}',
|
|
599
|
+
example: 'e.g.',
|
|
600
|
+
propertyNameRequired: 'Property name is required.',
|
|
601
|
+
propertyNameInvalid: 'Property name does not match schema constraints.',
|
|
602
|
+
propertyExists: 'Property already exists.',
|
|
603
|
+
propertyNotAllowed: 'This property is not allowed by the schema.',
|
|
604
|
+
errorRequired: 'This field is required',
|
|
605
|
+
errorMinLength: 'Minimum length is {n}',
|
|
606
|
+
errorMaxLength: 'Maximum length is {n}',
|
|
607
|
+
errorMin: 'Minimum value is {n}',
|
|
608
|
+
errorMax: 'Maximum value is {n}',
|
|
609
|
+
errorEmail: 'Invalid email address',
|
|
610
|
+
errorPattern: 'Value does not match the required pattern',
|
|
611
|
+
errorInteger: 'Value must be an integer',
|
|
612
|
+
errorExclusiveMin: 'Value must be greater than the minimum',
|
|
613
|
+
errorExclusiveMax: 'Value must be less than the maximum',
|
|
614
|
+
errorMultipleOf: 'Value must be a multiple of the required number',
|
|
615
|
+
errorMinItems: 'Minimum {n} items required',
|
|
616
|
+
errorMaxItems: 'Maximum {n} items allowed',
|
|
617
|
+
errorUniqueItems: 'Items must be unique',
|
|
618
|
+
};
|
|
619
|
+
/** Replaces `{key}` placeholders in a label template. */
|
|
620
|
+
function formatLabel(template, values = {}) {
|
|
621
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => (key in values ? String(values[key]) : match));
|
|
622
|
+
}
|
|
623
|
+
|
|
582
624
|
/**
|
|
583
625
|
* Options shared by every node of a form. Provided by `jsm-json-schema-form`, so each form instance has its own.
|
|
584
626
|
*/
|
|
585
627
|
class JsonSchemaFormOptions {
|
|
586
628
|
decimalSeparator = '.';
|
|
629
|
+
labels = DEFAULT_LABELS;
|
|
587
630
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JsonSchemaFormOptions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
588
631
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JsonSchemaFormOptions });
|
|
589
632
|
}
|
|
@@ -721,6 +764,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
721
764
|
type: Input
|
|
722
765
|
}] } });
|
|
723
766
|
|
|
767
|
+
let nextNodeId = 0;
|
|
724
768
|
class JsonSchemaNodeComponent {
|
|
725
769
|
schemaService;
|
|
726
770
|
validation;
|
|
@@ -744,6 +788,8 @@ class JsonSchemaNodeComponent {
|
|
|
744
788
|
propertyError = '';
|
|
745
789
|
/** Tracks whether this primitive control has been touched (for OnPush CD). */
|
|
746
790
|
isTouched = false;
|
|
791
|
+
/** Unique DOM id base of this node: links labels, hints and errors to the control (WCAG 1.3.1, 4.1.2). */
|
|
792
|
+
nodeId = `jsm-n${++nextNodeId}`;
|
|
747
793
|
valueSub;
|
|
748
794
|
constructor(schemaService, validation, cdr, options) {
|
|
749
795
|
this.schemaService = schemaService;
|
|
@@ -804,6 +850,74 @@ class JsonSchemaNodeComponent {
|
|
|
804
850
|
get decimalSeparator() {
|
|
805
851
|
return this.options?.decimalSeparator ?? '.';
|
|
806
852
|
}
|
|
853
|
+
/** Texts shown by the form (see `labels` of `jsm-json-schema-form`). */
|
|
854
|
+
get l() {
|
|
855
|
+
return this.options?.labels ?? DEFAULT_LABELS;
|
|
856
|
+
}
|
|
857
|
+
fmt(template, values = {}) {
|
|
858
|
+
return formatLabel(template, values);
|
|
859
|
+
}
|
|
860
|
+
localize(message) {
|
|
861
|
+
return localizeNumbers(message, this.decimalSeparator);
|
|
862
|
+
}
|
|
863
|
+
optionLabel(index) {
|
|
864
|
+
return this.fmt(this.l.option, { n: index + 1 });
|
|
865
|
+
}
|
|
866
|
+
sectionLabel(index) {
|
|
867
|
+
return this.fmt(this.l.section, { n: index + 1 });
|
|
868
|
+
}
|
|
869
|
+
/** DOM id of a dynamic key label (keys may contain characters that are not valid in ids). */
|
|
870
|
+
keyId(key) {
|
|
871
|
+
return `${this.nodeId}-key-${key.replace(/[^A-Za-z0-9_-]/g, (c) => `_${c.charCodeAt(0).toString(16)}`)}`;
|
|
872
|
+
}
|
|
873
|
+
/** True when the error list of this primitive is shown (same gate as the error styling). */
|
|
874
|
+
get visibleError() {
|
|
875
|
+
return this.allErrors.length > 0 && (this.control.dirty || this.isTouched || this.showErrors);
|
|
876
|
+
}
|
|
877
|
+
/** Ids of the hint, example, media type and error texts that describe this control. */
|
|
878
|
+
get describedBy() {
|
|
879
|
+
const ids = [];
|
|
880
|
+
if (this.schema.description)
|
|
881
|
+
ids.push(`${this.nodeId}-hint`);
|
|
882
|
+
if (this.effectiveSchema.examples?.length)
|
|
883
|
+
ids.push(`${this.nodeId}-example`);
|
|
884
|
+
if (this.effectiveSchema.contentMediaType)
|
|
885
|
+
ids.push(`${this.nodeId}-media`);
|
|
886
|
+
if (this.visibleError)
|
|
887
|
+
ids.push(`${this.nodeId}-error`);
|
|
888
|
+
return ids.length ? ids.join(' ') : null;
|
|
889
|
+
}
|
|
890
|
+
selectOneOf(index) {
|
|
891
|
+
this.selectedOneOf = index;
|
|
892
|
+
this.onOneOfChange();
|
|
893
|
+
}
|
|
894
|
+
/** WAI-ARIA tabs keyboard support: arrows, Home and End move between the oneOf options. */
|
|
895
|
+
onOneOfKeydown(event) {
|
|
896
|
+
const count = this.schema.oneOf?.length ?? 0;
|
|
897
|
+
if (!count)
|
|
898
|
+
return;
|
|
899
|
+
let next = this.selectedOneOf;
|
|
900
|
+
switch (event.key) {
|
|
901
|
+
case 'ArrowRight':
|
|
902
|
+
case 'ArrowDown':
|
|
903
|
+
next = (next + 1) % count;
|
|
904
|
+
break;
|
|
905
|
+
case 'ArrowLeft':
|
|
906
|
+
case 'ArrowUp':
|
|
907
|
+
next = (next - 1 + count) % count;
|
|
908
|
+
break;
|
|
909
|
+
case 'Home':
|
|
910
|
+
next = 0;
|
|
911
|
+
break;
|
|
912
|
+
case 'End':
|
|
913
|
+
next = count - 1;
|
|
914
|
+
break;
|
|
915
|
+
default: return;
|
|
916
|
+
}
|
|
917
|
+
event.preventDefault();
|
|
918
|
+
this.selectOneOf(next);
|
|
919
|
+
setTimeout(() => document.getElementById(`${this.nodeId}-tab-${next}`)?.focus());
|
|
920
|
+
}
|
|
807
921
|
/** `multipleOf` of this node's own schema, exposed as step metadata. */
|
|
808
922
|
get numericStep() {
|
|
809
923
|
return this.effectiveSchema.multipleOf ? String(this.effectiveSchema.multipleOf) : 'any';
|
|
@@ -855,34 +969,35 @@ class JsonSchemaNodeComponent {
|
|
|
855
969
|
return ajvErrors;
|
|
856
970
|
const angularErrors = [];
|
|
857
971
|
const errs = ctrl.errors;
|
|
972
|
+
const l = this.l;
|
|
858
973
|
if (errs['required'])
|
|
859
|
-
angularErrors.push(
|
|
974
|
+
angularErrors.push(l.errorRequired);
|
|
860
975
|
if (errs['minlength'])
|
|
861
|
-
angularErrors.push(
|
|
976
|
+
angularErrors.push(this.fmt(l.errorMinLength, { n: errs['minlength'].requiredLength }));
|
|
862
977
|
if (errs['maxlength'])
|
|
863
|
-
angularErrors.push(
|
|
978
|
+
angularErrors.push(this.fmt(l.errorMaxLength, { n: errs['maxlength'].requiredLength }));
|
|
864
979
|
if (errs['min'])
|
|
865
|
-
angularErrors.push(
|
|
980
|
+
angularErrors.push(this.fmt(l.errorMin, { n: errs['min'].min }));
|
|
866
981
|
if (errs['max'])
|
|
867
|
-
angularErrors.push(
|
|
982
|
+
angularErrors.push(this.fmt(l.errorMax, { n: errs['max'].max }));
|
|
868
983
|
if (errs['email'])
|
|
869
|
-
angularErrors.push(
|
|
984
|
+
angularErrors.push(l.errorEmail);
|
|
870
985
|
if (errs['pattern'])
|
|
871
|
-
angularErrors.push(
|
|
986
|
+
angularErrors.push(l.errorPattern);
|
|
872
987
|
if (errs['integer'])
|
|
873
|
-
angularErrors.push(
|
|
988
|
+
angularErrors.push(l.errorInteger);
|
|
874
989
|
if (errs['exclusiveMinimum'])
|
|
875
|
-
angularErrors.push(
|
|
990
|
+
angularErrors.push(l.errorExclusiveMin);
|
|
876
991
|
if (errs['exclusiveMaximum'])
|
|
877
|
-
angularErrors.push(
|
|
992
|
+
angularErrors.push(l.errorExclusiveMax);
|
|
878
993
|
if (errs['multipleOf'])
|
|
879
|
-
angularErrors.push(
|
|
994
|
+
angularErrors.push(l.errorMultipleOf);
|
|
880
995
|
if (errs['minItems'])
|
|
881
|
-
angularErrors.push(
|
|
996
|
+
angularErrors.push(this.fmt(l.errorMinItems, { n: errs['minItems'].requiredLength ?? '' }));
|
|
882
997
|
if (errs['maxItems'])
|
|
883
|
-
angularErrors.push(
|
|
998
|
+
angularErrors.push(this.fmt(l.errorMaxItems, { n: errs['maxItems'].requiredLength ?? '' }));
|
|
884
999
|
if (errs['uniqueItems'])
|
|
885
|
-
angularErrors.push(
|
|
1000
|
+
angularErrors.push(l.errorUniqueItems);
|
|
886
1001
|
// Merge: prefer Ajv messages, fall back to Angular messages for errors not covered by Ajv
|
|
887
1002
|
const messages = ajvErrors.length > 0 ? ajvErrors : angularErrors;
|
|
888
1003
|
return messages.map((message) => localizeNumbers(message, this.decimalSeparator));
|
|
@@ -912,8 +1027,16 @@ class JsonSchemaNodeComponent {
|
|
|
912
1027
|
return this.mergeSchemas([this.schema, ...this.schema.allOf]);
|
|
913
1028
|
return this.effectiveSchema;
|
|
914
1029
|
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Sections rendered for an allOf: the schema's own keywords (without the allOf itself, which would render
|
|
1032
|
+
* this node again forever) when it declares any, followed by every allOf entry.
|
|
1033
|
+
*/
|
|
915
1034
|
get mergedAllOf() {
|
|
916
|
-
|
|
1035
|
+
const { allOf, ...own } = this.schema;
|
|
1036
|
+
if (!allOf?.length)
|
|
1037
|
+
return [this.schema];
|
|
1038
|
+
const declaresOwn = Object.keys(own).some((key) => !['title', 'description', '$id', '$schema', '$comment'].includes(key));
|
|
1039
|
+
return declaresOwn ? [own, ...allOf] : [...allOf];
|
|
917
1040
|
}
|
|
918
1041
|
isRequired(key) { return this.effectiveSchema.required?.includes(key) ?? false; }
|
|
919
1042
|
schemaForKey(key) {
|
|
@@ -927,22 +1050,22 @@ class JsonSchemaNodeComponent {
|
|
|
927
1050
|
this.propertyError = '';
|
|
928
1051
|
const key = this.newPropertyKey.trim();
|
|
929
1052
|
if (!key) {
|
|
930
|
-
this.propertyError =
|
|
1053
|
+
this.propertyError = this.l.propertyNameRequired;
|
|
931
1054
|
return;
|
|
932
1055
|
}
|
|
933
1056
|
if (this.effectiveSchema.propertyNames) {
|
|
934
1057
|
if (this.validation.validate(this.effectiveSchema.propertyNames, key).length) {
|
|
935
|
-
this.propertyError =
|
|
1058
|
+
this.propertyError = this.l.propertyNameInvalid;
|
|
936
1059
|
return;
|
|
937
1060
|
}
|
|
938
1061
|
}
|
|
939
1062
|
if (this.controlAsGroup.contains(key)) {
|
|
940
|
-
this.propertyError =
|
|
1063
|
+
this.propertyError = this.l.propertyExists;
|
|
941
1064
|
return;
|
|
942
1065
|
}
|
|
943
1066
|
const s = this.schemaService.resolveDynamicSchema(this.effectiveSchema, key);
|
|
944
1067
|
if (!s) {
|
|
945
|
-
this.propertyError =
|
|
1068
|
+
this.propertyError = this.l.propertyNotAllowed;
|
|
946
1069
|
return;
|
|
947
1070
|
}
|
|
948
1071
|
this.controlAsGroup.addControl(key, this.schemaService.buildControl(s, undefined, false));
|
|
@@ -1077,14 +1200,17 @@ class JsonSchemaNodeComponent {
|
|
|
1077
1200
|
</div>
|
|
1078
1201
|
<span class="jsm-combinator-badge jsm-badge--oneof">oneOf</span>
|
|
1079
1202
|
</div>
|
|
1080
|
-
<div class="jsm-oneof-tabs">
|
|
1081
|
-
<button *ngFor="let option of schema.oneOf; let i = index" type="button"
|
|
1203
|
+
<div class="jsm-oneof-tabs" role="tablist" [attr.aria-label]="schema.title || label || null" (keydown)="onOneOfKeydown($event)">
|
|
1204
|
+
<button *ngFor="let option of schema.oneOf; let i = index" type="button" role="tab"
|
|
1082
1205
|
class="jsm-tab" [class.jsm-tab--active]="selectedOneOf === i"
|
|
1083
|
-
|
|
1084
|
-
|
|
1206
|
+
[id]="nodeId + '-tab-' + i" [attr.aria-selected]="selectedOneOf === i"
|
|
1207
|
+
[attr.aria-controls]="nodeId + '-panel'" [attr.tabindex]="selectedOneOf === i ? 0 : -1"
|
|
1208
|
+
(click)="selectOneOf(i)">
|
|
1209
|
+
{{ option.title || optionLabel(i) }}
|
|
1085
1210
|
</button>
|
|
1086
1211
|
</div>
|
|
1087
|
-
<div class="jsm-combinator-body" *ngIf="activeVariant"
|
|
1212
|
+
<div class="jsm-combinator-body" *ngIf="activeVariant" role="tabpanel" [id]="nodeId + '-panel'"
|
|
1213
|
+
[attr.aria-labelledby]="nodeId + '-tab-' + selectedOneOf">
|
|
1088
1214
|
<jsm-schema-node [schema]="activeVariant" [control]="control" [parent]="parent" [controlKey]="controlKey"
|
|
1089
1215
|
[path]="path" [errorsMap]="errorsMap" [label]="label" [required]="required"
|
|
1090
1216
|
[allowAdditionalProperties]="allowAdditionalProperties" [showErrors]="showErrors"
|
|
@@ -1101,11 +1227,11 @@ class JsonSchemaNodeComponent {
|
|
|
1101
1227
|
</div>
|
|
1102
1228
|
<span class="jsm-combinator-badge jsm-badge--anyof">anyOf</span>
|
|
1103
1229
|
</div>
|
|
1104
|
-
<div class="jsm-anyof-options">
|
|
1230
|
+
<div class="jsm-anyof-options" role="group" [attr.aria-label]="schema.title || label || null">
|
|
1105
1231
|
<label *ngFor="let option of schema.anyOf; let i = index"
|
|
1106
1232
|
class="jsm-anyof-option" [class.jsm-anyof-option--active]="selectedAnyOf.has(i)">
|
|
1107
1233
|
<input type="checkbox" class="sr-only" [checked]="selectedAnyOf.has(i)" (change)="toggleAnyOf(i)" />
|
|
1108
|
-
{{ option.title || (
|
|
1234
|
+
{{ option.title || optionLabel(i) }}
|
|
1109
1235
|
</label>
|
|
1110
1236
|
</div>
|
|
1111
1237
|
<div class="jsm-combinator-body" *ngIf="activeVariant">
|
|
@@ -1128,7 +1254,7 @@ class JsonSchemaNodeComponent {
|
|
|
1128
1254
|
<div class="jsm-combinator-body">
|
|
1129
1255
|
<div *ngFor="let subSchema of mergedAllOf; let i = index" class="jsm-allof-section">
|
|
1130
1256
|
<jsm-schema-node [schema]="subSchema" [control]="control" [parent]="parent" [controlKey]="controlKey"
|
|
1131
|
-
[path]="path" [errorsMap]="errorsMap" [label]="subSchema.title || (
|
|
1257
|
+
[path]="path" [errorsMap]="errorsMap" [label]="subSchema.title || sectionLabel(i)" [required]="required"
|
|
1132
1258
|
[allowAdditionalProperties]="allowAdditionalProperties" [showErrors]="showErrors"
|
|
1133
1259
|
(controlReplaced)="controlReplaced.emit($event)"></jsm-schema-node>
|
|
1134
1260
|
</div>
|
|
@@ -1148,8 +1274,9 @@ class JsonSchemaNodeComponent {
|
|
|
1148
1274
|
<ng-container *ngFor="let key of simpleKeys">
|
|
1149
1275
|
<div style="display:flex;flex-direction:column;gap:.25rem;">
|
|
1150
1276
|
<div *ngIf="isDynamicKey(key)" class="jsm-dynamic-key-header">
|
|
1151
|
-
<span class="jsm-dynamic-key-label">{{ key }}</span>
|
|
1152
|
-
<button type="button" class="jsm-btn-danger"
|
|
1277
|
+
<span class="jsm-dynamic-key-label" [id]="keyId(key)">{{ key }}</span>
|
|
1278
|
+
<button type="button" class="jsm-btn-danger" [id]="keyId(key) + '-remove'"
|
|
1279
|
+
[attr.aria-labelledby]="keyId(key) + '-remove ' + keyId(key)" (click)="removeDynamicKey(key)">{{ l.remove }}</button>
|
|
1153
1280
|
</div>
|
|
1154
1281
|
<jsm-schema-node [schema]="schemaForKey(key)" [control]="childControl(key)" [parent]="controlAsGroup"
|
|
1155
1282
|
[controlKey]="key" [path]="pathForChild(key)" [errorsMap]="errorsMap" [label]="key"
|
|
@@ -1163,8 +1290,9 @@ class JsonSchemaNodeComponent {
|
|
|
1163
1290
|
<ng-container *ngFor="let key of complexKeys">
|
|
1164
1291
|
<div style="display:flex;flex-direction:column;gap:.25rem;">
|
|
1165
1292
|
<div *ngIf="isDynamicKey(key)" class="jsm-dynamic-key-header">
|
|
1166
|
-
<span class="jsm-dynamic-key-label">{{ key }}</span>
|
|
1167
|
-
<button type="button" class="jsm-btn-danger"
|
|
1293
|
+
<span class="jsm-dynamic-key-label" [id]="keyId(key)">{{ key }}</span>
|
|
1294
|
+
<button type="button" class="jsm-btn-danger" [id]="keyId(key) + '-remove'"
|
|
1295
|
+
[attr.aria-labelledby]="keyId(key) + '-remove ' + keyId(key)" (click)="removeDynamicKey(key)">{{ l.remove }}</button>
|
|
1168
1296
|
</div>
|
|
1169
1297
|
<jsm-schema-node [schema]="schemaForKey(key)" [control]="childControl(key)" [parent]="controlAsGroup"
|
|
1170
1298
|
[controlKey]="key" [path]="pathForChild(key)" [errorsMap]="errorsMap" [label]="key"
|
|
@@ -1174,45 +1302,48 @@ class JsonSchemaNodeComponent {
|
|
|
1174
1302
|
</ng-container>
|
|
1175
1303
|
</div>
|
|
1176
1304
|
|
|
1177
|
-
<div *ngIf="canAddProperty" class="jsm-add-prop">
|
|
1178
|
-
<p class="jsm-add-prop-label">
|
|
1305
|
+
<div *ngIf="canAddProperty" class="jsm-add-prop" role="group" [attr.aria-labelledby]="nodeId + '-addprop'">
|
|
1306
|
+
<p class="jsm-add-prop-label" [id]="nodeId + '-addprop'">{{ l.addProperty }}</p>
|
|
1179
1307
|
<div class="jsm-add-prop-row">
|
|
1180
|
-
<input class="jsm-input jsm-input--sm" style="flex:1;" [(ngModel)]="newPropertyKey"
|
|
1181
|
-
|
|
1308
|
+
<input class="jsm-input jsm-input--sm" style="flex:1;" [(ngModel)]="newPropertyKey" [ngModelOptions]="{standalone: true}"
|
|
1309
|
+
[attr.aria-label]="l.propertyName" [attr.placeholder]="l.propertyName"
|
|
1310
|
+
[attr.aria-invalid]="propertyError ? 'true' : null" [attr.aria-describedby]="propertyError ? nodeId + '-prop-error' : null" />
|
|
1311
|
+
<button type="button" class="jsm-btn-primary" (click)="addDynamicProperty()">{{ l.add }}</button>
|
|
1182
1312
|
</div>
|
|
1183
|
-
<p *ngIf="propertyError" class="jsm-error-msg">
|
|
1184
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1313
|
+
<p *ngIf="propertyError" class="jsm-error-msg" role="alert" [id]="nodeId + '-prop-error'">
|
|
1314
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1185
1315
|
{{ propertyError }}
|
|
1186
1316
|
</p>
|
|
1187
1317
|
</div>
|
|
1188
1318
|
|
|
1189
|
-
<div *ngIf="errorsForPath.length" class="jsm-error-list" style="margin-top:.75rem;">
|
|
1319
|
+
<div *ngIf="errorsForPath.length" class="jsm-error-list" role="alert" style="margin-top:.75rem;">
|
|
1190
1320
|
<p *ngFor="let error of errorsForPath" class="jsm-error-msg">
|
|
1191
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1192
|
-
{{ error }}
|
|
1321
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1322
|
+
{{ localize(error) }}
|
|
1193
1323
|
</p>
|
|
1194
1324
|
</div>
|
|
1195
1325
|
</fieldset>
|
|
1196
1326
|
|
|
1197
1327
|
<!-- ═══ array ═══ -->
|
|
1198
|
-
<div *ngSwitchCase="'array'" class="jsm-array-block">
|
|
1328
|
+
<div *ngSwitchCase="'array'" class="jsm-array-block" role="group" [attr.aria-labelledby]="nodeId + '-title'">
|
|
1199
1329
|
<div class="jsm-array-header">
|
|
1200
1330
|
<div>
|
|
1201
|
-
<p class="jsm-array-title">
|
|
1202
|
-
{{ schema.title || label }}<span *ngIf="required"
|
|
1331
|
+
<p class="jsm-array-title" [id]="nodeId + '-title'">
|
|
1332
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1203
1333
|
</p>
|
|
1204
1334
|
<p *ngIf="schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1205
1335
|
</div>
|
|
1206
|
-
<button type="button" class="jsm-btn-primary"
|
|
1207
|
-
|
|
1208
|
-
|
|
1336
|
+
<button type="button" class="jsm-btn-primary" [id]="nodeId + '-add'"
|
|
1337
|
+
[attr.aria-labelledby]="nodeId + '-add ' + nodeId + '-title'" (click)="addArrayItem()" [disabled]="!canAddArrayItem">
|
|
1338
|
+
<svg style="width:.875rem;height:.875rem;flex-shrink:0;" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1339
|
+
{{ l.addItem }}
|
|
1209
1340
|
</button>
|
|
1210
1341
|
</div>
|
|
1211
1342
|
|
|
1212
1343
|
<div *ngIf="effectiveSchema.contains" class="jsm-contains-hint">
|
|
1213
|
-
|
|
1214
|
-
<span *ngIf="effectiveSchema.minContains"> · min {
|
|
1215
|
-
<span *ngIf="effectiveSchema.maxContains"> · max {
|
|
1344
|
+
{{ l.mustContain }}
|
|
1345
|
+
<span *ngIf="effectiveSchema.minContains"> · {{ fmt(l.min, { n: effectiveSchema.minContains }) }}</span>
|
|
1346
|
+
<span *ngIf="effectiveSchema.maxContains"> · {{ fmt(l.max, { n: effectiveSchema.maxContains }) }}</span>
|
|
1216
1347
|
</div>
|
|
1217
1348
|
|
|
1218
1349
|
<div *ngIf="metaBadges.length" class="jsm-badge-row">
|
|
@@ -1220,10 +1351,12 @@ class JsonSchemaNodeComponent {
|
|
|
1220
1351
|
</div>
|
|
1221
1352
|
|
|
1222
1353
|
<div class="jsm-array-items" *ngIf="arrayControls.length > 0; else emptyArray">
|
|
1223
|
-
<div *ngFor="let item of arrayControls; let i = index" class="jsm-array-item">
|
|
1354
|
+
<div *ngFor="let item of arrayControls; let i = index" class="jsm-array-item" role="group" [attr.aria-labelledby]="nodeId + '-item-' + i">
|
|
1224
1355
|
<div class="jsm-array-item-header">
|
|
1225
|
-
<span class="jsm-array-index">{{ i + 1 }}</span>
|
|
1226
|
-
<
|
|
1356
|
+
<span class="jsm-array-index" aria-hidden="true">{{ i + 1 }}</span>
|
|
1357
|
+
<span class="sr-only" [id]="nodeId + '-item-' + i">{{ fmt(l.arrayItem, { n: i + 1 }) }}</span>
|
|
1358
|
+
<button type="button" class="jsm-btn-danger" [id]="nodeId + '-remove-' + i"
|
|
1359
|
+
[attr.aria-labelledby]="nodeId + '-remove-' + i + ' ' + nodeId + '-item-' + i" (click)="removeArrayItem(i)">{{ l.remove }}</button>
|
|
1227
1360
|
</div>
|
|
1228
1361
|
<jsm-schema-node [schema]="schemaForIndex(i)" [control]="item" [parent]="controlAsArray"
|
|
1229
1362
|
[controlKey]="i" [path]="pathForChild(i)" [errorsMap]="errorsMap" [label]="label + ' item'"
|
|
@@ -1233,13 +1366,13 @@ class JsonSchemaNodeComponent {
|
|
|
1233
1366
|
</div>
|
|
1234
1367
|
|
|
1235
1368
|
<ng-template #emptyArray>
|
|
1236
|
-
<div class="jsm-empty-array">
|
|
1369
|
+
<div class="jsm-empty-array">{{ l.noItems }}</div>
|
|
1237
1370
|
</ng-template>
|
|
1238
1371
|
|
|
1239
|
-
<div *ngIf="errorsForPath.length" class="jsm-error-list">
|
|
1372
|
+
<div *ngIf="errorsForPath.length" class="jsm-error-list" role="alert">
|
|
1240
1373
|
<p *ngFor="let error of errorsForPath" class="jsm-error-msg">
|
|
1241
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1242
|
-
{{ error }}
|
|
1374
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1375
|
+
{{ localize(error) }}
|
|
1243
1376
|
</p>
|
|
1244
1377
|
</div>
|
|
1245
1378
|
</div>
|
|
@@ -1247,10 +1380,10 @@ class JsonSchemaNodeComponent {
|
|
|
1247
1380
|
<!-- ═══ primitive ═══ -->
|
|
1248
1381
|
<div *ngSwitchDefault class="jsm-field">
|
|
1249
1382
|
<ng-container *ngIf="inputKind !== 'checkbox'">
|
|
1250
|
-
<label class="jsm-field-label">
|
|
1251
|
-
{{ schema.title || label }}<span *ngIf="required" class="jsm-required">*</span>
|
|
1383
|
+
<label class="jsm-field-label" [attr.for]="nodeId">
|
|
1384
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1252
1385
|
</label>
|
|
1253
|
-
<p *ngIf="schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1386
|
+
<p *ngIf="schema.description" class="jsm-field-hint" [id]="nodeId + '-hint'">{{ schema.description }}</p>
|
|
1254
1387
|
</ng-container>
|
|
1255
1388
|
|
|
1256
1389
|
<div *ngIf="metaBadges.length" class="jsm-badge-row">
|
|
@@ -1258,57 +1391,65 @@ class JsonSchemaNodeComponent {
|
|
|
1258
1391
|
</div>
|
|
1259
1392
|
|
|
1260
1393
|
<ng-container>
|
|
1261
|
-
<input *ngIf="inputKind === 'number'" jsmNumeric type="text" inputmode="decimal" class="jsm-input"
|
|
1394
|
+
<input *ngIf="inputKind === 'number'" jsmNumeric type="text" inputmode="decimal" class="jsm-input" [id]="nodeId"
|
|
1262
1395
|
[class.jsm-input--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1263
1396
|
[jsmDecimalSeparator]="decimalSeparator" [attr.data-step]="numericStep"
|
|
1264
|
-
[attr.
|
|
1397
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1398
|
+
[attr.aria-describedby]="describedBy"
|
|
1265
1399
|
[formControl]="controlAsFormControl"
|
|
1266
1400
|
(blur)="onBlur()" />
|
|
1267
1401
|
|
|
1268
|
-
<input *ngIf="inputKind === 'text'" class="jsm-input"
|
|
1402
|
+
<input *ngIf="inputKind === 'text'" class="jsm-input" [id]="nodeId"
|
|
1269
1403
|
[class.jsm-input--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1270
|
-
[attr.type]="inputType"
|
|
1404
|
+
[attr.type]="inputType"
|
|
1405
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1406
|
+
[attr.aria-describedby]="describedBy"
|
|
1271
1407
|
[formControl]="controlAsFormControl"
|
|
1272
1408
|
(blur)="onBlur()" />
|
|
1273
1409
|
|
|
1274
|
-
<textarea *ngIf="inputKind === 'textarea'" rows="4" class="jsm-textarea"
|
|
1410
|
+
<textarea *ngIf="inputKind === 'textarea'" rows="4" class="jsm-textarea" [id]="nodeId"
|
|
1275
1411
|
[class.jsm-textarea--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1276
|
-
[attr.
|
|
1412
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1413
|
+
[attr.aria-describedby]="describedBy"
|
|
1277
1414
|
[formControl]="controlAsFormControl"
|
|
1278
1415
|
(blur)="onBlur()"></textarea>
|
|
1279
1416
|
|
|
1280
1417
|
<div *ngIf="inputKind === 'select'" class="jsm-select-wrap">
|
|
1281
|
-
<select class="jsm-select"
|
|
1418
|
+
<select class="jsm-select" [id]="nodeId"
|
|
1282
1419
|
[class.jsm-select--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1420
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1421
|
+
[attr.aria-describedby]="describedBy"
|
|
1283
1422
|
[formControl]="controlAsFormControl"
|
|
1284
1423
|
(blur)="onBlur()">
|
|
1285
1424
|
<option *ngFor="let option of effectiveSchema.enum" [ngValue]="option">{{ option }}</option>
|
|
1286
1425
|
</select>
|
|
1287
|
-
<svg class="jsm-select-chevron" viewBox="0 0 16 16" fill="none">
|
|
1426
|
+
<svg class="jsm-select-chevron" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1288
1427
|
<path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1289
1428
|
</svg>
|
|
1290
1429
|
</div>
|
|
1291
1430
|
|
|
1292
1431
|
<label *ngIf="inputKind === 'checkbox'" class="jsm-toggle-label">
|
|
1293
1432
|
<span class="jsm-toggle-track" [class.jsm-on]="controlAsFormControl.value">
|
|
1294
|
-
<input type="checkbox" class="sr-only" [formControl]="controlAsFormControl"
|
|
1433
|
+
<input type="checkbox" class="sr-only" [id]="nodeId" [formControl]="controlAsFormControl"
|
|
1434
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1435
|
+
[attr.aria-describedby]="describedBy" (blur)="onBlur()" />
|
|
1295
1436
|
<span class="jsm-toggle-thumb"></span>
|
|
1296
1437
|
</span>
|
|
1297
1438
|
<span class="jsm-toggle-text">
|
|
1298
|
-
{{ schema.title || label }}<span *ngIf="required" class="jsm-required">*</span>
|
|
1439
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1299
1440
|
</span>
|
|
1300
1441
|
</label>
|
|
1301
1442
|
</ng-container>
|
|
1302
1443
|
|
|
1303
|
-
<p *ngIf="inputKind === 'checkbox' && schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1304
|
-
<p *ngIf="effectiveSchema.examples?.length" class="jsm-example">
|
|
1305
|
-
<p *ngIf="effectiveSchema.contentMediaType" class="jsm-example">
|
|
1444
|
+
<p *ngIf="inputKind === 'checkbox' && schema.description" class="jsm-field-hint" [id]="nodeId + '-hint'">{{ schema.description }}</p>
|
|
1445
|
+
<p *ngIf="effectiveSchema.examples?.length" class="jsm-example" [id]="nodeId + '-example'">{{ l.example }} {{ effectiveSchema.examples?.[0] }}</p>
|
|
1446
|
+
<p *ngIf="effectiveSchema.contentMediaType" class="jsm-example" [id]="nodeId + '-media'">
|
|
1306
1447
|
{{ effectiveSchema.contentMediaType }}<span *ngIf="effectiveSchema.contentEncoding"> ({{ effectiveSchema.contentEncoding }})</span>
|
|
1307
1448
|
</p>
|
|
1308
1449
|
|
|
1309
|
-
<div *ngIf="
|
|
1450
|
+
<div *ngIf="visibleError" class="jsm-error-list" role="alert" [id]="nodeId + '-error'">
|
|
1310
1451
|
<p *ngFor="let error of allErrors" class="jsm-error-msg">
|
|
1311
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none">
|
|
1452
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1312
1453
|
<circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/>
|
|
1313
1454
|
<path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
1314
1455
|
</svg>
|
|
@@ -1318,7 +1459,7 @@ class JsonSchemaNodeComponent {
|
|
|
1318
1459
|
</div>
|
|
1319
1460
|
|
|
1320
1461
|
</ng-container>
|
|
1321
|
-
`, isInline: true, styles: [".jsm-field{display:flex;flex-direction:column;gap:.375rem}.jsm-field-label{display:block;font-size:.8125rem;font-weight:600;color:#374151}.jsm-field-hint{font-size:.75rem;color:#6b7280;margin:0;line-height:1.4}.jsm-required{color:#ef4444;margin-left:.125rem}.jsm-example{font-size:.6875rem;color:#9ca3af}.jsm-input,.jsm-textarea,.jsm-select{width:100%;border-radius:.5rem;border:1.5px solid #d1d5db;background:Canvas;padding:.5rem .75rem;font-size:.875rem;color:CanvasText;outline:none;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s;font-family:inherit;box-sizing:border-box}.jsm-input:hover,.jsm-textarea:hover,.jsm-select:hover{border-color:#9ca3af}.jsm-input:focus,.jsm-textarea:focus,.jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f126}.jsm-input--error,.jsm-textarea--error,.jsm-select--error{border-color:#f87171!important;background:#fff5f5}.jsm-input--error:focus,.jsm-textarea--error:focus,.jsm-select--error:focus{box-shadow:0 0 0 3px #f8717133!important}.jsm-textarea{resize:vertical;min-height:6rem}.jsm-select-wrap{position:relative}.jsm-select{appearance:none;padding-right:2.25rem;cursor:pointer}.jsm-select-chevron{position:absolute;right:.625rem;top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:#9ca3af;pointer-events:none}.jsm-toggle-label{display:inline-flex;align-items:center;gap:.625rem;cursor:pointer;-webkit-user-select:none;user-select:none}.jsm-toggle-track{position:relative;display:inline-flex;align-items:center;width:2.25rem;height:1.25rem;border-radius:9999px;flex-shrink:0;background:#d1d5db;transition:background .2s}.jsm-toggle-track.jsm-on{background:#4f46e5}.jsm-toggle-thumb{display:inline-block;width:1rem;height:1rem;border-radius:9999px;background:#fff;box-shadow:0 1px 3px #0003;transform:translate(.125rem);transition:transform .2s}.jsm-toggle-track.jsm-on .jsm-toggle-thumb{transform:translate(1.125rem)}.jsm-toggle-text{font-size:.875rem;font-weight:500;color:#374151}.jsm-btn-primary{display:inline-flex;align-items:center;gap:.25rem;padding:.375rem .75rem;border-radius:.5rem;font-size:.8125rem;font-weight:600;background:#4f46e5;color:#fff;border:none;cursor:pointer;box-shadow:0 1px 2px #4f46e54d;transition:background .15s,transform .1s,box-shadow .15s;white-space:nowrap;font-family:inherit}.jsm-btn-primary:hover{background:#4338ca;transform:translateY(-1px);box-shadow:0 3px 8px #4f46e54d}.jsm-btn-primary:active{transform:translateY(0)}.jsm-btn-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.jsm-btn-danger{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;border-radius:.375rem;font-size:.75rem;font-weight:600;background:transparent;color:#dc2626;border:1.5px solid #fca5a5;cursor:pointer;transition:background .15s,border-color .15s;font-family:inherit}.jsm-btn-danger:hover{background:#fee2e2;border-color:#f87171}.jsm-error-list{display:flex;flex-direction:column;gap:.25rem;margin-top:.25rem}.jsm-error-msg{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#dc2626;font-weight:500}.jsm-error-icon{width:.875rem;height:.875rem;flex-shrink:0}.jsm-badge-row{display:flex;flex-wrap:wrap;gap:.375rem}.jsm-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase}.jsm-badge--deprecated{background:#fef3c7;color:#92400e}.jsm-badge--readonly{background:#f1f5f9;color:#475569}.jsm-badge--writeonly{background:#dbeafe;color:#1e40af}.jsm-badge--not{background:#fee2e2;color:#991b1b}.jsm-badge--nullable{background:#f3f4f6;color:#6b7280}.jsm-fieldset{border:1.5px solid #e5e7eb;border-radius:.875rem;padding:1.25rem;background:transparent;box-shadow:0 1px 3px #0000000f;transition:box-shadow .2s;box-sizing:border-box}.jsm-fieldset:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114,0 1px 3px #0000000f}.jsm-legend{display:inline-flex;align-items:center;gap:.375rem;padding:0 .5rem;font-size:.875rem;font-weight:700;color:#1f2937}.jsm-obj-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.jsm-obj-grid{grid-template-columns:repeat(2,1fr)}}.jsm-obj-complex{display:flex;flex-direction:column;gap:1rem;margin-top:1rem}.jsm-dynamic-key-header{display:flex;align-items:center;justify-content:space-between;padding:.25rem .5rem;background:#f9fafb;border-radius:.375rem;border:1px dashed #d1d5db;margin-bottom:.25rem}.jsm-dynamic-key-label{font-size:.75rem;font-weight:600;color:#6b7280;font-family:monospace}.jsm-add-prop{margin-top:1rem;padding:.875rem;background:#f9fafb;border-radius:.625rem;border:1.5px dashed #d1d5db;display:flex;flex-direction:column;gap:.5rem}.jsm-add-prop-label{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.04em}.jsm-add-prop-row{display:flex;gap:.5rem;align-items:center}.jsm-input--sm{padding:.375rem .625rem;font-size:.8125rem}.jsm-array-block{display:flex;flex-direction:column;gap:.75rem}.jsm-array-header{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem}.jsm-array-title{font-size:.875rem;font-weight:700;color:#1f2937;display:flex;align-items:center;gap:.375rem}.jsm-array-items{display:flex;flex-direction:column;gap:.75rem}.jsm-array-item{border:1.5px solid #e5e7eb;border-radius:.75rem;padding:.875rem;background:transparent;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s}.jsm-array-item:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114}.jsm-array-item-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.jsm-array-index{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:9999px;background:#eef2ff;color:#4f46e5;font-size:.6875rem;font-weight:700}.jsm-empty-array{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:2rem 1rem;border:1.5px dashed #e5e7eb;border-radius:.75rem;color:#9ca3af;font-size:.8125rem;text-align:center}.jsm-contains-hint{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#6366f1;background:#eef2ff;border-radius:.375rem;padding:.375rem .625rem}.jsm-combinator{border:1.5px solid #e5e7eb;border-radius:.875rem;overflow:hidden;background:transparent;box-shadow:0 1px 3px #0000000f}.jsm-combinator-header{display:flex;align-items:flex-start;justify-content:space-between;padding:.875rem 1rem;background:#00000008;border-bottom:1.5px solid #e5e7eb}.jsm-combinator-title{font-size:.875rem;font-weight:700;color:#1f2937}.jsm-combinator-body{padding:1rem}.jsm-combinator-hint{font-size:.75rem;color:#6b7280;margin:.25rem 0 0}.jsm-oneof-tabs{display:flex;overflow-x:auto;border-bottom:1.5px solid #e5e7eb}.jsm-tab{padding:.5rem 1rem;font-size:.8125rem;font-weight:500;color:#6b7280;border:none;background:transparent;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1.5px;transition:color .15s,border-color .15s;white-space:nowrap;font-family:inherit}.jsm-tab:hover{color:#4f46e5}.jsm-tab--active{color:#4f46e5;border-bottom-color:#4f46e5;font-weight:600}.jsm-anyof-options{display:flex;flex-wrap:wrap;gap:.5rem;padding:.75rem 1rem;border-bottom:1.5px solid #e5e7eb}.jsm-anyof-option{display:inline-flex;align-items:center;gap:.375rem;padding:.375rem .75rem;border-radius:9999px;border:1.5px solid #e5e7eb;font-size:.8125rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s;background:transparent}.jsm-anyof-option:hover{border-color:#a5b4fc;color:#4f46e5}.jsm-anyof-option--active{border-color:#6366f1;background:#eef2ff;color:#4f46e5}.jsm-allof-section{border-left:3px solid #e0e7ff;padding-left:1rem}.jsm-combinator-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0;margin-left:.75rem}.jsm-badge--oneof{background:#dbeafe;color:#1e40af}.jsm-badge--anyof{background:#ede9fe;color:#5b21b6}.jsm-badge--allof{background:#ccfbf1;color:#065f46}.dark .jsm-field-label{color:#d1d5db}.dark .jsm-field-hint{color:#9ca3af}.dark .jsm-toggle-track{background:#475569}.dark .jsm-toggle-track.jsm-on{background:#4f46e5}.dark .jsm-toggle-text{color:#d1d5db}.dark .jsm-input,.dark .jsm-textarea,.dark .jsm-select{border-color:#475569;color:#f1f5f9}.dark .jsm-input:focus,.dark .jsm-textarea:focus,.dark .jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f133}.dark .jsm-input--error,.dark .jsm-textarea--error,.dark .jsm-select--error{border-color:#f87171!important;background:#f871711a}.dark .jsm-fieldset{border-color:#334155}.dark .jsm-fieldset:focus-within{border-color:#6366f1}.dark .jsm-legend{color:#f1f5f9}.dark .jsm-combinator{border-color:#334155}.dark .jsm-combinator-header{background:#ffffff0a;border-color:#334155}.dark .jsm-combinator-title{color:#f1f5f9}.dark .jsm-oneof-tabs{border-color:#334155}.dark .jsm-tab{color:#94a3b8}.dark .jsm-tab--active{color:#818cf8;border-bottom-color:#818cf8}.dark .jsm-anyof-options{border-color:#334155}.dark .jsm-anyof-option{border-color:#334155;color:#94a3b8;background:#0f172a}.dark .jsm-anyof-option--active{border-color:#6366f1;background:#6366f126;color:#818cf8}.dark .jsm-allof-section{border-left-color:#3730a3}.dark .jsm-array-item{border-color:#334155}.dark .jsm-array-item:focus-within{border-color:#6366f1}.dark .jsm-array-index{background:#6366f133;color:#818cf8}.dark .jsm-empty-array{border-color:#334155;color:#64748b}.dark .jsm-contains-hint{background:#6366f126;color:#818cf8}.dark .jsm-add-prop{background:#1e293b66;border-color:#475569}.dark .jsm-add-prop-label{color:#64748b}.dark .jsm-dynamic-key-header{background:#1e293b80;border-color:#475569}.dark .jsm-dynamic-key-label{color:#94a3b8}.dark .jsm-error-msg{color:#f87171}.dark .jsm-array-title{color:#f1f5f9}.dark .jsm-badge--deprecated{background:#d9770633;color:#fbbf24}.dark .jsm-badge--readonly{background:#1e293b;color:#94a3b8}.dark .jsm-badge--writeonly{background:#2563eb33;color:#60a5fa}.dark .jsm-badge--not{background:#dc262633;color:#f87171}.dark .jsm-badge--nullable{background:#1e293b;color:#94a3b8}.dark .jsm-select-chevron{color:#64748b}\n"], dependencies: [{ kind: "component", type: JsonSchemaNodeComponent, selector: "jsm-schema-node", inputs: ["schema", "control", "label", "required", "path", "errorsMap", "parent", "controlKey", "allowAdditionalProperties", "showErrors"], outputs: ["controlReplaced"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NumericInputDirective, selector: "input[jsmNumeric]", inputs: ["jsmDecimalSeparator"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1462
|
+
`, isInline: true, styles: [".jsm-field{display:flex;flex-direction:column;gap:.375rem}.jsm-field-label{display:block;font-size:.8125rem;font-weight:600;color:#374151}.jsm-field-hint{font-size:.75rem;color:#6b7280;margin:0;line-height:1.4}.jsm-required{color:#dc2626;margin-left:.125rem}.jsm-example{font-size:.6875rem;color:#6b7280;margin:0}.jsm-input,.jsm-textarea,.jsm-select{width:100%;border-radius:.5rem;border:1.5px solid #6b7280;background:Canvas;padding:.5rem .75rem;font-size:.875rem;color:CanvasText;outline:none;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s;font-family:inherit;box-sizing:border-box}.jsm-input:hover,.jsm-textarea:hover,.jsm-select:hover{border-color:#4b5563}.jsm-input:focus,.jsm-textarea:focus,.jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f126}.jsm-input--error,.jsm-textarea--error,.jsm-select--error{border-color:#dc2626!important;background:#fff5f5}.jsm-input--error:focus,.jsm-textarea--error:focus,.jsm-select--error:focus{box-shadow:0 0 0 3px #f8717133!important}.jsm-textarea{resize:vertical;min-height:6rem}.jsm-select-wrap{position:relative}.jsm-select{appearance:none;padding-right:2.25rem;cursor:pointer}.jsm-select-chevron{position:absolute;right:.625rem;top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:#6b7280;pointer-events:none}.jsm-toggle-label{display:inline-flex;align-items:center;gap:.625rem;cursor:pointer;-webkit-user-select:none;user-select:none;min-height:1.5rem}.jsm-toggle-track{position:relative;display:inline-flex;align-items:center;width:2.25rem;height:1.25rem;border-radius:9999px;flex-shrink:0;background:#6b7280;transition:background .2s}.jsm-toggle-track.jsm-on{background:#4f46e5}.jsm-toggle-thumb{display:inline-block;width:1rem;height:1rem;border-radius:9999px;background:#fff;box-shadow:0 1px 3px #0003;transform:translate(.125rem);transition:transform .2s}.jsm-toggle-track.jsm-on .jsm-toggle-thumb{transform:translate(1.125rem)}.jsm-toggle-text{font-size:.875rem;font-weight:500;color:#374151}.jsm-btn-primary{display:inline-flex;align-items:center;gap:.25rem;padding:.375rem .75rem;border-radius:.5rem;font-size:.8125rem;font-weight:600;background:#4f46e5;color:#fff;border:none;cursor:pointer;box-shadow:0 1px 2px #4f46e54d;transition:background .15s,transform .1s,box-shadow .15s;white-space:nowrap;font-family:inherit}.jsm-btn-primary:hover{background:#4338ca;transform:translateY(-1px);box-shadow:0 3px 8px #4f46e54d}.jsm-btn-primary:active{transform:translateY(0)}.jsm-btn-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.jsm-btn-danger{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;border-radius:.375rem;font-size:.75rem;font-weight:600;background:transparent;color:#b91c1c;min-height:1.5rem;border:1.5px solid #fca5a5;cursor:pointer;transition:background .15s,border-color .15s;font-family:inherit}.jsm-btn-danger:hover{background:#fee2e2;border-color:#f87171}.jsm-error-list{display:flex;flex-direction:column;gap:.25rem;margin-top:.25rem}.jsm-error-msg{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#dc2626;font-weight:500}.jsm-error-icon{width:.875rem;height:.875rem;flex-shrink:0}.jsm-badge-row{display:flex;flex-wrap:wrap;gap:.375rem}.jsm-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase}.jsm-badge--deprecated{background:#fef3c7;color:#92400e}.jsm-badge--readonly{background:#f1f5f9;color:#475569}.jsm-badge--writeonly{background:#dbeafe;color:#1e40af}.jsm-badge--not{background:#fee2e2;color:#991b1b}.jsm-badge--nullable{background:#f3f4f6;color:#4b5563}.jsm-fieldset{border:1.5px solid #e5e7eb;border-radius:.875rem;padding:1.25rem;background:transparent;box-shadow:0 1px 3px #0000000f;transition:box-shadow .2s;box-sizing:border-box}.jsm-fieldset:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114,0 1px 3px #0000000f}.jsm-legend{display:inline-flex;align-items:center;gap:.375rem;padding:0 .5rem;font-size:.875rem;font-weight:700;color:#1f2937}.jsm-obj-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.jsm-obj-grid{grid-template-columns:repeat(2,1fr)}}.jsm-obj-complex{display:flex;flex-direction:column;gap:1rem;margin-top:1rem}.jsm-dynamic-key-header{display:flex;align-items:center;justify-content:space-between;padding:.25rem .5rem;background:#f9fafb;border-radius:.375rem;border:1px dashed #d1d5db;margin-bottom:.25rem}.jsm-dynamic-key-label{font-size:.75rem;font-weight:600;color:#6b7280;font-family:monospace}.jsm-add-prop{margin-top:1rem;padding:.875rem;background:#f9fafb;border-radius:.625rem;border:1.5px dashed #d1d5db;display:flex;flex-direction:column;gap:.5rem}.jsm-add-prop-label{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.04em}.jsm-add-prop-row{display:flex;gap:.5rem;align-items:center}.jsm-input--sm{padding:.375rem .625rem;font-size:.8125rem}.jsm-array-block{display:flex;flex-direction:column;gap:.75rem}.jsm-array-header{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem}.jsm-array-title{font-size:.875rem;font-weight:700;color:#1f2937;display:flex;align-items:center;gap:.375rem}.jsm-array-items{display:flex;flex-direction:column;gap:.75rem}.jsm-array-item{border:1.5px solid #e5e7eb;border-radius:.75rem;padding:.875rem;background:transparent;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s}.jsm-array-item:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114}.jsm-array-item-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.jsm-array-index{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:9999px;background:#eef2ff;color:#4f46e5;font-size:.6875rem;font-weight:700}.jsm-empty-array{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:2rem 1rem;border:1.5px dashed #e5e7eb;border-radius:.75rem;color:#6b7280;font-size:.8125rem;text-align:center}.jsm-contains-hint{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#4f46e5;background:#eef2ff;border-radius:.375rem;padding:.375rem .625rem}.jsm-combinator{border:1.5px solid #e5e7eb;border-radius:.875rem;overflow:hidden;background:transparent;box-shadow:0 1px 3px #0000000f}.jsm-combinator-header{display:flex;align-items:flex-start;justify-content:space-between;padding:.875rem 1rem;background:#00000008;border-bottom:1.5px solid #e5e7eb}.jsm-combinator-title{font-size:.875rem;font-weight:700;color:#1f2937}.jsm-combinator-body{padding:1rem}.jsm-combinator-hint{font-size:.75rem;color:#6b7280;margin:.25rem 0 0}.jsm-oneof-tabs{display:flex;overflow-x:auto;border-bottom:1.5px solid #e5e7eb}.jsm-tab{padding:.5rem 1rem;font-size:.8125rem;font-weight:500;color:#6b7280;border:none;background:transparent;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1.5px;transition:color .15s,border-color .15s;white-space:nowrap;font-family:inherit}.jsm-tab:hover{color:#4f46e5}.jsm-tab--active{color:#4f46e5;border-bottom-color:#4f46e5;font-weight:600}.jsm-anyof-options{display:flex;flex-wrap:wrap;gap:.5rem;padding:.75rem 1rem;border-bottom:1.5px solid #e5e7eb}.jsm-anyof-option{display:inline-flex;align-items:center;gap:.375rem;padding:.375rem .75rem;border-radius:9999px;border:1.5px solid #6b7280;font-size:.8125rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s;background:transparent}.jsm-anyof-option:hover{border-color:#a5b4fc;color:#4f46e5}.jsm-anyof-option--active{border-color:#6366f1;background:#eef2ff;color:#4f46e5}.jsm-allof-section{border-left:3px solid #e0e7ff;padding-left:1rem}.jsm-combinator-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0;margin-left:.75rem}.jsm-badge--oneof{background:#dbeafe;color:#1e40af}.jsm-badge--anyof{background:#ede9fe;color:#5b21b6}.jsm-badge--allof{background:#ccfbf1;color:#065f46}.jsm-input:focus-visible,.jsm-textarea:focus-visible,.jsm-select:focus-visible,.jsm-btn-primary:focus-visible,.jsm-btn-danger:focus-visible,.jsm-tab:focus-visible{outline:2px solid #4f46e5;outline-offset:2px}.jsm-toggle-label:has(input:focus-visible) .jsm-toggle-track,.jsm-anyof-option:has(input:focus-visible){outline:2px solid #4f46e5;outline-offset:2px}.dark .jsm-field-label{color:#d1d5db}.dark .jsm-required{color:#f87171}.dark .jsm-example{color:#9ca3af}.dark .jsm-input:focus-visible,.dark .jsm-textarea:focus-visible,.dark .jsm-select:focus-visible,.dark .jsm-btn-primary:focus-visible,.dark .jsm-btn-danger:focus-visible,.dark .jsm-tab:focus-visible,.dark .jsm-toggle-label:has(input:focus-visible) .jsm-toggle-track,.dark .jsm-anyof-option:has(input:focus-visible){outline-color:#818cf8}.dark .jsm-btn-danger{color:#f87171;border-color:#f87171}.dark .jsm-btn-danger:hover{background:#f8717126}.dark .jsm-field-hint{color:#9ca3af}.dark .jsm-toggle-track{background:#64748b}.dark .jsm-toggle-track.jsm-on{background:#6366f1}.dark .jsm-toggle-text{color:#d1d5db}.dark .jsm-input,.dark .jsm-textarea,.dark .jsm-select{border-color:#64748b;color:#f1f5f9}.dark .jsm-input:focus,.dark .jsm-textarea:focus,.dark .jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f133}.dark .jsm-input--error,.dark .jsm-textarea--error,.dark .jsm-select--error{border-color:#f87171!important;background:#f871711a}.dark .jsm-fieldset{border-color:#334155}.dark .jsm-fieldset:focus-within{border-color:#6366f1}.dark .jsm-legend{color:#f1f5f9}.dark .jsm-combinator{border-color:#334155}.dark .jsm-combinator-header{background:#ffffff0a;border-color:#334155}.dark .jsm-combinator-title{color:#f1f5f9}.dark .jsm-oneof-tabs{border-color:#334155}.dark .jsm-tab{color:#94a3b8}.dark .jsm-tab--active{color:#818cf8;border-bottom-color:#818cf8}.dark .jsm-anyof-options{border-color:#334155}.dark .jsm-anyof-option{border-color:#64748b;color:#94a3b8;background:#0f172a}.dark .jsm-anyof-option--active{border-color:#6366f1;background:#6366f126;color:#818cf8}.dark .jsm-allof-section{border-left-color:#3730a3}.dark .jsm-array-item{border-color:#334155}.dark .jsm-array-item:focus-within{border-color:#6366f1}.dark .jsm-array-index{background:#6366f133;color:#818cf8}.dark .jsm-empty-array{border-color:#334155;color:#94a3b8}.dark .jsm-contains-hint{background:#6366f126;color:#818cf8}.dark .jsm-add-prop{background:#1e293b66;border-color:#475569}.dark .jsm-add-prop-label{color:#94a3b8}.dark .jsm-dynamic-key-header{background:#1e293b80;border-color:#475569}.dark .jsm-dynamic-key-label{color:#94a3b8}.dark .jsm-error-msg{color:#f87171}.dark .jsm-array-title{color:#f1f5f9}.dark .jsm-badge--deprecated{background:#d9770633;color:#fbbf24}.dark .jsm-badge--readonly{background:#1e293b;color:#94a3b8}.dark .jsm-badge--writeonly{background:#2563eb33;color:#60a5fa}.dark .jsm-badge--not{background:#dc262633;color:#f87171}.dark .jsm-badge--nullable{background:#1e293b;color:#94a3b8}.dark .jsm-select-chevron{color:#94a3b8}\n"], dependencies: [{ kind: "component", type: JsonSchemaNodeComponent, selector: "jsm-schema-node", inputs: ["schema", "control", "label", "required", "path", "errorsMap", "parent", "controlKey", "allowAdditionalProperties", "showErrors"], outputs: ["controlReplaced"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NumericInputDirective, selector: "input[jsmNumeric]", inputs: ["jsmDecimalSeparator"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
1322
1463
|
}
|
|
1323
1464
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JsonSchemaNodeComponent, decorators: [{
|
|
1324
1465
|
type: Component,
|
|
@@ -1334,14 +1475,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1334
1475
|
</div>
|
|
1335
1476
|
<span class="jsm-combinator-badge jsm-badge--oneof">oneOf</span>
|
|
1336
1477
|
</div>
|
|
1337
|
-
<div class="jsm-oneof-tabs">
|
|
1338
|
-
<button *ngFor="let option of schema.oneOf; let i = index" type="button"
|
|
1478
|
+
<div class="jsm-oneof-tabs" role="tablist" [attr.aria-label]="schema.title || label || null" (keydown)="onOneOfKeydown($event)">
|
|
1479
|
+
<button *ngFor="let option of schema.oneOf; let i = index" type="button" role="tab"
|
|
1339
1480
|
class="jsm-tab" [class.jsm-tab--active]="selectedOneOf === i"
|
|
1340
|
-
|
|
1341
|
-
|
|
1481
|
+
[id]="nodeId + '-tab-' + i" [attr.aria-selected]="selectedOneOf === i"
|
|
1482
|
+
[attr.aria-controls]="nodeId + '-panel'" [attr.tabindex]="selectedOneOf === i ? 0 : -1"
|
|
1483
|
+
(click)="selectOneOf(i)">
|
|
1484
|
+
{{ option.title || optionLabel(i) }}
|
|
1342
1485
|
</button>
|
|
1343
1486
|
</div>
|
|
1344
|
-
<div class="jsm-combinator-body" *ngIf="activeVariant"
|
|
1487
|
+
<div class="jsm-combinator-body" *ngIf="activeVariant" role="tabpanel" [id]="nodeId + '-panel'"
|
|
1488
|
+
[attr.aria-labelledby]="nodeId + '-tab-' + selectedOneOf">
|
|
1345
1489
|
<jsm-schema-node [schema]="activeVariant" [control]="control" [parent]="parent" [controlKey]="controlKey"
|
|
1346
1490
|
[path]="path" [errorsMap]="errorsMap" [label]="label" [required]="required"
|
|
1347
1491
|
[allowAdditionalProperties]="allowAdditionalProperties" [showErrors]="showErrors"
|
|
@@ -1358,11 +1502,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1358
1502
|
</div>
|
|
1359
1503
|
<span class="jsm-combinator-badge jsm-badge--anyof">anyOf</span>
|
|
1360
1504
|
</div>
|
|
1361
|
-
<div class="jsm-anyof-options">
|
|
1505
|
+
<div class="jsm-anyof-options" role="group" [attr.aria-label]="schema.title || label || null">
|
|
1362
1506
|
<label *ngFor="let option of schema.anyOf; let i = index"
|
|
1363
1507
|
class="jsm-anyof-option" [class.jsm-anyof-option--active]="selectedAnyOf.has(i)">
|
|
1364
1508
|
<input type="checkbox" class="sr-only" [checked]="selectedAnyOf.has(i)" (change)="toggleAnyOf(i)" />
|
|
1365
|
-
{{ option.title || (
|
|
1509
|
+
{{ option.title || optionLabel(i) }}
|
|
1366
1510
|
</label>
|
|
1367
1511
|
</div>
|
|
1368
1512
|
<div class="jsm-combinator-body" *ngIf="activeVariant">
|
|
@@ -1385,7 +1529,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1385
1529
|
<div class="jsm-combinator-body">
|
|
1386
1530
|
<div *ngFor="let subSchema of mergedAllOf; let i = index" class="jsm-allof-section">
|
|
1387
1531
|
<jsm-schema-node [schema]="subSchema" [control]="control" [parent]="parent" [controlKey]="controlKey"
|
|
1388
|
-
[path]="path" [errorsMap]="errorsMap" [label]="subSchema.title || (
|
|
1532
|
+
[path]="path" [errorsMap]="errorsMap" [label]="subSchema.title || sectionLabel(i)" [required]="required"
|
|
1389
1533
|
[allowAdditionalProperties]="allowAdditionalProperties" [showErrors]="showErrors"
|
|
1390
1534
|
(controlReplaced)="controlReplaced.emit($event)"></jsm-schema-node>
|
|
1391
1535
|
</div>
|
|
@@ -1405,8 +1549,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1405
1549
|
<ng-container *ngFor="let key of simpleKeys">
|
|
1406
1550
|
<div style="display:flex;flex-direction:column;gap:.25rem;">
|
|
1407
1551
|
<div *ngIf="isDynamicKey(key)" class="jsm-dynamic-key-header">
|
|
1408
|
-
<span class="jsm-dynamic-key-label">{{ key }}</span>
|
|
1409
|
-
<button type="button" class="jsm-btn-danger"
|
|
1552
|
+
<span class="jsm-dynamic-key-label" [id]="keyId(key)">{{ key }}</span>
|
|
1553
|
+
<button type="button" class="jsm-btn-danger" [id]="keyId(key) + '-remove'"
|
|
1554
|
+
[attr.aria-labelledby]="keyId(key) + '-remove ' + keyId(key)" (click)="removeDynamicKey(key)">{{ l.remove }}</button>
|
|
1410
1555
|
</div>
|
|
1411
1556
|
<jsm-schema-node [schema]="schemaForKey(key)" [control]="childControl(key)" [parent]="controlAsGroup"
|
|
1412
1557
|
[controlKey]="key" [path]="pathForChild(key)" [errorsMap]="errorsMap" [label]="key"
|
|
@@ -1420,8 +1565,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1420
1565
|
<ng-container *ngFor="let key of complexKeys">
|
|
1421
1566
|
<div style="display:flex;flex-direction:column;gap:.25rem;">
|
|
1422
1567
|
<div *ngIf="isDynamicKey(key)" class="jsm-dynamic-key-header">
|
|
1423
|
-
<span class="jsm-dynamic-key-label">{{ key }}</span>
|
|
1424
|
-
<button type="button" class="jsm-btn-danger"
|
|
1568
|
+
<span class="jsm-dynamic-key-label" [id]="keyId(key)">{{ key }}</span>
|
|
1569
|
+
<button type="button" class="jsm-btn-danger" [id]="keyId(key) + '-remove'"
|
|
1570
|
+
[attr.aria-labelledby]="keyId(key) + '-remove ' + keyId(key)" (click)="removeDynamicKey(key)">{{ l.remove }}</button>
|
|
1425
1571
|
</div>
|
|
1426
1572
|
<jsm-schema-node [schema]="schemaForKey(key)" [control]="childControl(key)" [parent]="controlAsGroup"
|
|
1427
1573
|
[controlKey]="key" [path]="pathForChild(key)" [errorsMap]="errorsMap" [label]="key"
|
|
@@ -1431,45 +1577,48 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1431
1577
|
</ng-container>
|
|
1432
1578
|
</div>
|
|
1433
1579
|
|
|
1434
|
-
<div *ngIf="canAddProperty" class="jsm-add-prop">
|
|
1435
|
-
<p class="jsm-add-prop-label">
|
|
1580
|
+
<div *ngIf="canAddProperty" class="jsm-add-prop" role="group" [attr.aria-labelledby]="nodeId + '-addprop'">
|
|
1581
|
+
<p class="jsm-add-prop-label" [id]="nodeId + '-addprop'">{{ l.addProperty }}</p>
|
|
1436
1582
|
<div class="jsm-add-prop-row">
|
|
1437
|
-
<input class="jsm-input jsm-input--sm" style="flex:1;" [(ngModel)]="newPropertyKey"
|
|
1438
|
-
|
|
1583
|
+
<input class="jsm-input jsm-input--sm" style="flex:1;" [(ngModel)]="newPropertyKey" [ngModelOptions]="{standalone: true}"
|
|
1584
|
+
[attr.aria-label]="l.propertyName" [attr.placeholder]="l.propertyName"
|
|
1585
|
+
[attr.aria-invalid]="propertyError ? 'true' : null" [attr.aria-describedby]="propertyError ? nodeId + '-prop-error' : null" />
|
|
1586
|
+
<button type="button" class="jsm-btn-primary" (click)="addDynamicProperty()">{{ l.add }}</button>
|
|
1439
1587
|
</div>
|
|
1440
|
-
<p *ngIf="propertyError" class="jsm-error-msg">
|
|
1441
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1588
|
+
<p *ngIf="propertyError" class="jsm-error-msg" role="alert" [id]="nodeId + '-prop-error'">
|
|
1589
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1442
1590
|
{{ propertyError }}
|
|
1443
1591
|
</p>
|
|
1444
1592
|
</div>
|
|
1445
1593
|
|
|
1446
|
-
<div *ngIf="errorsForPath.length" class="jsm-error-list" style="margin-top:.75rem;">
|
|
1594
|
+
<div *ngIf="errorsForPath.length" class="jsm-error-list" role="alert" style="margin-top:.75rem;">
|
|
1447
1595
|
<p *ngFor="let error of errorsForPath" class="jsm-error-msg">
|
|
1448
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1449
|
-
{{ error }}
|
|
1596
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1597
|
+
{{ localize(error) }}
|
|
1450
1598
|
</p>
|
|
1451
1599
|
</div>
|
|
1452
1600
|
</fieldset>
|
|
1453
1601
|
|
|
1454
1602
|
<!-- ═══ array ═══ -->
|
|
1455
|
-
<div *ngSwitchCase="'array'" class="jsm-array-block">
|
|
1603
|
+
<div *ngSwitchCase="'array'" class="jsm-array-block" role="group" [attr.aria-labelledby]="nodeId + '-title'">
|
|
1456
1604
|
<div class="jsm-array-header">
|
|
1457
1605
|
<div>
|
|
1458
|
-
<p class="jsm-array-title">
|
|
1459
|
-
{{ schema.title || label }}<span *ngIf="required"
|
|
1606
|
+
<p class="jsm-array-title" [id]="nodeId + '-title'">
|
|
1607
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1460
1608
|
</p>
|
|
1461
1609
|
<p *ngIf="schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1462
1610
|
</div>
|
|
1463
|
-
<button type="button" class="jsm-btn-primary"
|
|
1464
|
-
|
|
1465
|
-
|
|
1611
|
+
<button type="button" class="jsm-btn-primary" [id]="nodeId + '-add'"
|
|
1612
|
+
[attr.aria-labelledby]="nodeId + '-add ' + nodeId + '-title'" (click)="addArrayItem()" [disabled]="!canAddArrayItem">
|
|
1613
|
+
<svg style="width:.875rem;height:.875rem;flex-shrink:0;" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M8 3v10M3 8h10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1614
|
+
{{ l.addItem }}
|
|
1466
1615
|
</button>
|
|
1467
1616
|
</div>
|
|
1468
1617
|
|
|
1469
1618
|
<div *ngIf="effectiveSchema.contains" class="jsm-contains-hint">
|
|
1470
|
-
|
|
1471
|
-
<span *ngIf="effectiveSchema.minContains"> · min {
|
|
1472
|
-
<span *ngIf="effectiveSchema.maxContains"> · max {
|
|
1619
|
+
{{ l.mustContain }}
|
|
1620
|
+
<span *ngIf="effectiveSchema.minContains"> · {{ fmt(l.min, { n: effectiveSchema.minContains }) }}</span>
|
|
1621
|
+
<span *ngIf="effectiveSchema.maxContains"> · {{ fmt(l.max, { n: effectiveSchema.maxContains }) }}</span>
|
|
1473
1622
|
</div>
|
|
1474
1623
|
|
|
1475
1624
|
<div *ngIf="metaBadges.length" class="jsm-badge-row">
|
|
@@ -1477,10 +1626,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1477
1626
|
</div>
|
|
1478
1627
|
|
|
1479
1628
|
<div class="jsm-array-items" *ngIf="arrayControls.length > 0; else emptyArray">
|
|
1480
|
-
<div *ngFor="let item of arrayControls; let i = index" class="jsm-array-item">
|
|
1629
|
+
<div *ngFor="let item of arrayControls; let i = index" class="jsm-array-item" role="group" [attr.aria-labelledby]="nodeId + '-item-' + i">
|
|
1481
1630
|
<div class="jsm-array-item-header">
|
|
1482
|
-
<span class="jsm-array-index">{{ i + 1 }}</span>
|
|
1483
|
-
<
|
|
1631
|
+
<span class="jsm-array-index" aria-hidden="true">{{ i + 1 }}</span>
|
|
1632
|
+
<span class="sr-only" [id]="nodeId + '-item-' + i">{{ fmt(l.arrayItem, { n: i + 1 }) }}</span>
|
|
1633
|
+
<button type="button" class="jsm-btn-danger" [id]="nodeId + '-remove-' + i"
|
|
1634
|
+
[attr.aria-labelledby]="nodeId + '-remove-' + i + ' ' + nodeId + '-item-' + i" (click)="removeArrayItem(i)">{{ l.remove }}</button>
|
|
1484
1635
|
</div>
|
|
1485
1636
|
<jsm-schema-node [schema]="schemaForIndex(i)" [control]="item" [parent]="controlAsArray"
|
|
1486
1637
|
[controlKey]="i" [path]="pathForChild(i)" [errorsMap]="errorsMap" [label]="label + ' item'"
|
|
@@ -1490,13 +1641,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1490
1641
|
</div>
|
|
1491
1642
|
|
|
1492
1643
|
<ng-template #emptyArray>
|
|
1493
|
-
<div class="jsm-empty-array">
|
|
1644
|
+
<div class="jsm-empty-array">{{ l.noItems }}</div>
|
|
1494
1645
|
</ng-template>
|
|
1495
1646
|
|
|
1496
|
-
<div *ngIf="errorsForPath.length" class="jsm-error-list">
|
|
1647
|
+
<div *ngIf="errorsForPath.length" class="jsm-error-list" role="alert">
|
|
1497
1648
|
<p *ngFor="let error of errorsForPath" class="jsm-error-msg">
|
|
1498
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1499
|
-
{{ error }}
|
|
1649
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
1650
|
+
{{ localize(error) }}
|
|
1500
1651
|
</p>
|
|
1501
1652
|
</div>
|
|
1502
1653
|
</div>
|
|
@@ -1504,10 +1655,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1504
1655
|
<!-- ═══ primitive ═══ -->
|
|
1505
1656
|
<div *ngSwitchDefault class="jsm-field">
|
|
1506
1657
|
<ng-container *ngIf="inputKind !== 'checkbox'">
|
|
1507
|
-
<label class="jsm-field-label">
|
|
1508
|
-
{{ schema.title || label }}<span *ngIf="required" class="jsm-required">*</span>
|
|
1658
|
+
<label class="jsm-field-label" [attr.for]="nodeId">
|
|
1659
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1509
1660
|
</label>
|
|
1510
|
-
<p *ngIf="schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1661
|
+
<p *ngIf="schema.description" class="jsm-field-hint" [id]="nodeId + '-hint'">{{ schema.description }}</p>
|
|
1511
1662
|
</ng-container>
|
|
1512
1663
|
|
|
1513
1664
|
<div *ngIf="metaBadges.length" class="jsm-badge-row">
|
|
@@ -1515,57 +1666,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1515
1666
|
</div>
|
|
1516
1667
|
|
|
1517
1668
|
<ng-container>
|
|
1518
|
-
<input *ngIf="inputKind === 'number'" jsmNumeric type="text" inputmode="decimal" class="jsm-input"
|
|
1669
|
+
<input *ngIf="inputKind === 'number'" jsmNumeric type="text" inputmode="decimal" class="jsm-input" [id]="nodeId"
|
|
1519
1670
|
[class.jsm-input--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1520
1671
|
[jsmDecimalSeparator]="decimalSeparator" [attr.data-step]="numericStep"
|
|
1521
|
-
[attr.
|
|
1672
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1673
|
+
[attr.aria-describedby]="describedBy"
|
|
1522
1674
|
[formControl]="controlAsFormControl"
|
|
1523
1675
|
(blur)="onBlur()" />
|
|
1524
1676
|
|
|
1525
|
-
<input *ngIf="inputKind === 'text'" class="jsm-input"
|
|
1677
|
+
<input *ngIf="inputKind === 'text'" class="jsm-input" [id]="nodeId"
|
|
1526
1678
|
[class.jsm-input--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1527
|
-
[attr.type]="inputType"
|
|
1679
|
+
[attr.type]="inputType"
|
|
1680
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1681
|
+
[attr.aria-describedby]="describedBy"
|
|
1528
1682
|
[formControl]="controlAsFormControl"
|
|
1529
1683
|
(blur)="onBlur()" />
|
|
1530
1684
|
|
|
1531
|
-
<textarea *ngIf="inputKind === 'textarea'" rows="4" class="jsm-textarea"
|
|
1685
|
+
<textarea *ngIf="inputKind === 'textarea'" rows="4" class="jsm-textarea" [id]="nodeId"
|
|
1532
1686
|
[class.jsm-textarea--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1533
|
-
[attr.
|
|
1687
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1688
|
+
[attr.aria-describedby]="describedBy"
|
|
1534
1689
|
[formControl]="controlAsFormControl"
|
|
1535
1690
|
(blur)="onBlur()"></textarea>
|
|
1536
1691
|
|
|
1537
1692
|
<div *ngIf="inputKind === 'select'" class="jsm-select-wrap">
|
|
1538
|
-
<select class="jsm-select"
|
|
1693
|
+
<select class="jsm-select" [id]="nodeId"
|
|
1539
1694
|
[class.jsm-select--error]="controlAsFormControl.invalid && (controlAsFormControl.dirty || isTouched || showErrors)"
|
|
1695
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1696
|
+
[attr.aria-describedby]="describedBy"
|
|
1540
1697
|
[formControl]="controlAsFormControl"
|
|
1541
1698
|
(blur)="onBlur()">
|
|
1542
1699
|
<option *ngFor="let option of effectiveSchema.enum" [ngValue]="option">{{ option }}</option>
|
|
1543
1700
|
</select>
|
|
1544
|
-
<svg class="jsm-select-chevron" viewBox="0 0 16 16" fill="none">
|
|
1701
|
+
<svg class="jsm-select-chevron" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1545
1702
|
<path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1546
1703
|
</svg>
|
|
1547
1704
|
</div>
|
|
1548
1705
|
|
|
1549
1706
|
<label *ngIf="inputKind === 'checkbox'" class="jsm-toggle-label">
|
|
1550
1707
|
<span class="jsm-toggle-track" [class.jsm-on]="controlAsFormControl.value">
|
|
1551
|
-
<input type="checkbox" class="sr-only" [formControl]="controlAsFormControl"
|
|
1708
|
+
<input type="checkbox" class="sr-only" [id]="nodeId" [formControl]="controlAsFormControl"
|
|
1709
|
+
[attr.aria-required]="required ? 'true' : null" [attr.aria-invalid]="visibleError ? 'true' : null"
|
|
1710
|
+
[attr.aria-describedby]="describedBy" (blur)="onBlur()" />
|
|
1552
1711
|
<span class="jsm-toggle-thumb"></span>
|
|
1553
1712
|
</span>
|
|
1554
1713
|
<span class="jsm-toggle-text">
|
|
1555
|
-
{{ schema.title || label }}<span *ngIf="required" class="jsm-required">*</span>
|
|
1714
|
+
{{ schema.title || label }}<span *ngIf="required" class="jsm-required" aria-hidden="true">*</span>
|
|
1556
1715
|
</span>
|
|
1557
1716
|
</label>
|
|
1558
1717
|
</ng-container>
|
|
1559
1718
|
|
|
1560
|
-
<p *ngIf="inputKind === 'checkbox' && schema.description" class="jsm-field-hint">{{ schema.description }}</p>
|
|
1561
|
-
<p *ngIf="effectiveSchema.examples?.length" class="jsm-example">
|
|
1562
|
-
<p *ngIf="effectiveSchema.contentMediaType" class="jsm-example">
|
|
1719
|
+
<p *ngIf="inputKind === 'checkbox' && schema.description" class="jsm-field-hint" [id]="nodeId + '-hint'">{{ schema.description }}</p>
|
|
1720
|
+
<p *ngIf="effectiveSchema.examples?.length" class="jsm-example" [id]="nodeId + '-example'">{{ l.example }} {{ effectiveSchema.examples?.[0] }}</p>
|
|
1721
|
+
<p *ngIf="effectiveSchema.contentMediaType" class="jsm-example" [id]="nodeId + '-media'">
|
|
1563
1722
|
{{ effectiveSchema.contentMediaType }}<span *ngIf="effectiveSchema.contentEncoding"> ({{ effectiveSchema.contentEncoding }})</span>
|
|
1564
1723
|
</p>
|
|
1565
1724
|
|
|
1566
|
-
<div *ngIf="
|
|
1725
|
+
<div *ngIf="visibleError" class="jsm-error-list" role="alert" [id]="nodeId + '-error'">
|
|
1567
1726
|
<p *ngFor="let error of allErrors" class="jsm-error-msg">
|
|
1568
|
-
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none">
|
|
1727
|
+
<svg class="jsm-error-icon" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1569
1728
|
<circle cx="8" cy="8" r="6.5" stroke="currentColor" stroke-width="1.5"/>
|
|
1570
1729
|
<path d="M8 5v3.5M8 11v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
1571
1730
|
</svg>
|
|
@@ -1575,7 +1734,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1575
1734
|
</div>
|
|
1576
1735
|
|
|
1577
1736
|
</ng-container>
|
|
1578
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".jsm-field{display:flex;flex-direction:column;gap:.375rem}.jsm-field-label{display:block;font-size:.8125rem;font-weight:600;color:#374151}.jsm-field-hint{font-size:.75rem;color:#6b7280;margin:0;line-height:1.4}.jsm-required{color:#ef4444;margin-left:.125rem}.jsm-example{font-size:.6875rem;color:#9ca3af}.jsm-input,.jsm-textarea,.jsm-select{width:100%;border-radius:.5rem;border:1.5px solid #d1d5db;background:Canvas;padding:.5rem .75rem;font-size:.875rem;color:CanvasText;outline:none;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s;font-family:inherit;box-sizing:border-box}.jsm-input:hover,.jsm-textarea:hover,.jsm-select:hover{border-color:#9ca3af}.jsm-input:focus,.jsm-textarea:focus,.jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f126}.jsm-input--error,.jsm-textarea--error,.jsm-select--error{border-color:#f87171!important;background:#fff5f5}.jsm-input--error:focus,.jsm-textarea--error:focus,.jsm-select--error:focus{box-shadow:0 0 0 3px #f8717133!important}.jsm-textarea{resize:vertical;min-height:6rem}.jsm-select-wrap{position:relative}.jsm-select{appearance:none;padding-right:2.25rem;cursor:pointer}.jsm-select-chevron{position:absolute;right:.625rem;top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:#9ca3af;pointer-events:none}.jsm-toggle-label{display:inline-flex;align-items:center;gap:.625rem;cursor:pointer;-webkit-user-select:none;user-select:none}.jsm-toggle-track{position:relative;display:inline-flex;align-items:center;width:2.25rem;height:1.25rem;border-radius:9999px;flex-shrink:0;background:#d1d5db;transition:background .2s}.jsm-toggle-track.jsm-on{background:#4f46e5}.jsm-toggle-thumb{display:inline-block;width:1rem;height:1rem;border-radius:9999px;background:#fff;box-shadow:0 1px 3px #0003;transform:translate(.125rem);transition:transform .2s}.jsm-toggle-track.jsm-on .jsm-toggle-thumb{transform:translate(1.125rem)}.jsm-toggle-text{font-size:.875rem;font-weight:500;color:#374151}.jsm-btn-primary{display:inline-flex;align-items:center;gap:.25rem;padding:.375rem .75rem;border-radius:.5rem;font-size:.8125rem;font-weight:600;background:#4f46e5;color:#fff;border:none;cursor:pointer;box-shadow:0 1px 2px #4f46e54d;transition:background .15s,transform .1s,box-shadow .15s;white-space:nowrap;font-family:inherit}.jsm-btn-primary:hover{background:#4338ca;transform:translateY(-1px);box-shadow:0 3px 8px #4f46e54d}.jsm-btn-primary:active{transform:translateY(0)}.jsm-btn-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.jsm-btn-danger{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;border-radius:.375rem;font-size:.75rem;font-weight:600;background:transparent;color:#dc2626;border:1.5px solid #fca5a5;cursor:pointer;transition:background .15s,border-color .15s;font-family:inherit}.jsm-btn-danger:hover{background:#fee2e2;border-color:#f87171}.jsm-error-list{display:flex;flex-direction:column;gap:.25rem;margin-top:.25rem}.jsm-error-msg{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#dc2626;font-weight:500}.jsm-error-icon{width:.875rem;height:.875rem;flex-shrink:0}.jsm-badge-row{display:flex;flex-wrap:wrap;gap:.375rem}.jsm-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase}.jsm-badge--deprecated{background:#fef3c7;color:#92400e}.jsm-badge--readonly{background:#f1f5f9;color:#475569}.jsm-badge--writeonly{background:#dbeafe;color:#1e40af}.jsm-badge--not{background:#fee2e2;color:#991b1b}.jsm-badge--nullable{background:#f3f4f6;color:#6b7280}.jsm-fieldset{border:1.5px solid #e5e7eb;border-radius:.875rem;padding:1.25rem;background:transparent;box-shadow:0 1px 3px #0000000f;transition:box-shadow .2s;box-sizing:border-box}.jsm-fieldset:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114,0 1px 3px #0000000f}.jsm-legend{display:inline-flex;align-items:center;gap:.375rem;padding:0 .5rem;font-size:.875rem;font-weight:700;color:#1f2937}.jsm-obj-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.jsm-obj-grid{grid-template-columns:repeat(2,1fr)}}.jsm-obj-complex{display:flex;flex-direction:column;gap:1rem;margin-top:1rem}.jsm-dynamic-key-header{display:flex;align-items:center;justify-content:space-between;padding:.25rem .5rem;background:#f9fafb;border-radius:.375rem;border:1px dashed #d1d5db;margin-bottom:.25rem}.jsm-dynamic-key-label{font-size:.75rem;font-weight:600;color:#6b7280;font-family:monospace}.jsm-add-prop{margin-top:1rem;padding:.875rem;background:#f9fafb;border-radius:.625rem;border:1.5px dashed #d1d5db;display:flex;flex-direction:column;gap:.5rem}.jsm-add-prop-label{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.04em}.jsm-add-prop-row{display:flex;gap:.5rem;align-items:center}.jsm-input--sm{padding:.375rem .625rem;font-size:.8125rem}.jsm-array-block{display:flex;flex-direction:column;gap:.75rem}.jsm-array-header{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem}.jsm-array-title{font-size:.875rem;font-weight:700;color:#1f2937;display:flex;align-items:center;gap:.375rem}.jsm-array-items{display:flex;flex-direction:column;gap:.75rem}.jsm-array-item{border:1.5px solid #e5e7eb;border-radius:.75rem;padding:.875rem;background:transparent;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s}.jsm-array-item:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114}.jsm-array-item-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.jsm-array-index{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:9999px;background:#eef2ff;color:#4f46e5;font-size:.6875rem;font-weight:700}.jsm-empty-array{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:2rem 1rem;border:1.5px dashed #e5e7eb;border-radius:.75rem;color:#9ca3af;font-size:.8125rem;text-align:center}.jsm-contains-hint{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#6366f1;background:#eef2ff;border-radius:.375rem;padding:.375rem .625rem}.jsm-combinator{border:1.5px solid #e5e7eb;border-radius:.875rem;overflow:hidden;background:transparent;box-shadow:0 1px 3px #0000000f}.jsm-combinator-header{display:flex;align-items:flex-start;justify-content:space-between;padding:.875rem 1rem;background:#00000008;border-bottom:1.5px solid #e5e7eb}.jsm-combinator-title{font-size:.875rem;font-weight:700;color:#1f2937}.jsm-combinator-body{padding:1rem}.jsm-combinator-hint{font-size:.75rem;color:#6b7280;margin:.25rem 0 0}.jsm-oneof-tabs{display:flex;overflow-x:auto;border-bottom:1.5px solid #e5e7eb}.jsm-tab{padding:.5rem 1rem;font-size:.8125rem;font-weight:500;color:#6b7280;border:none;background:transparent;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1.5px;transition:color .15s,border-color .15s;white-space:nowrap;font-family:inherit}.jsm-tab:hover{color:#4f46e5}.jsm-tab--active{color:#4f46e5;border-bottom-color:#4f46e5;font-weight:600}.jsm-anyof-options{display:flex;flex-wrap:wrap;gap:.5rem;padding:.75rem 1rem;border-bottom:1.5px solid #e5e7eb}.jsm-anyof-option{display:inline-flex;align-items:center;gap:.375rem;padding:.375rem .75rem;border-radius:9999px;border:1.5px solid #e5e7eb;font-size:.8125rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s;background:transparent}.jsm-anyof-option:hover{border-color:#a5b4fc;color:#4f46e5}.jsm-anyof-option--active{border-color:#6366f1;background:#eef2ff;color:#4f46e5}.jsm-allof-section{border-left:3px solid #e0e7ff;padding-left:1rem}.jsm-combinator-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0;margin-left:.75rem}.jsm-badge--oneof{background:#dbeafe;color:#1e40af}.jsm-badge--anyof{background:#ede9fe;color:#5b21b6}.jsm-badge--allof{background:#ccfbf1;color:#065f46}.dark .jsm-field-label{color:#d1d5db}.dark .jsm-field-hint{color:#9ca3af}.dark .jsm-toggle-track{background:#475569}.dark .jsm-toggle-track.jsm-on{background:#4f46e5}.dark .jsm-toggle-text{color:#d1d5db}.dark .jsm-input,.dark .jsm-textarea,.dark .jsm-select{border-color:#475569;color:#f1f5f9}.dark .jsm-input:focus,.dark .jsm-textarea:focus,.dark .jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f133}.dark .jsm-input--error,.dark .jsm-textarea--error,.dark .jsm-select--error{border-color:#f87171!important;background:#f871711a}.dark .jsm-fieldset{border-color:#334155}.dark .jsm-fieldset:focus-within{border-color:#6366f1}.dark .jsm-legend{color:#f1f5f9}.dark .jsm-combinator{border-color:#334155}.dark .jsm-combinator-header{background:#ffffff0a;border-color:#334155}.dark .jsm-combinator-title{color:#f1f5f9}.dark .jsm-oneof-tabs{border-color:#334155}.dark .jsm-tab{color:#94a3b8}.dark .jsm-tab--active{color:#818cf8;border-bottom-color:#818cf8}.dark .jsm-anyof-options{border-color:#334155}.dark .jsm-anyof-option{border-color:#334155;color:#94a3b8;background:#0f172a}.dark .jsm-anyof-option--active{border-color:#6366f1;background:#6366f126;color:#818cf8}.dark .jsm-allof-section{border-left-color:#3730a3}.dark .jsm-array-item{border-color:#334155}.dark .jsm-array-item:focus-within{border-color:#6366f1}.dark .jsm-array-index{background:#6366f133;color:#818cf8}.dark .jsm-empty-array{border-color:#334155;color:#64748b}.dark .jsm-contains-hint{background:#6366f126;color:#818cf8}.dark .jsm-add-prop{background:#1e293b66;border-color:#475569}.dark .jsm-add-prop-label{color:#64748b}.dark .jsm-dynamic-key-header{background:#1e293b80;border-color:#475569}.dark .jsm-dynamic-key-label{color:#94a3b8}.dark .jsm-error-msg{color:#f87171}.dark .jsm-array-title{color:#f1f5f9}.dark .jsm-badge--deprecated{background:#d9770633;color:#fbbf24}.dark .jsm-badge--readonly{background:#1e293b;color:#94a3b8}.dark .jsm-badge--writeonly{background:#2563eb33;color:#60a5fa}.dark .jsm-badge--not{background:#dc262633;color:#f87171}.dark .jsm-badge--nullable{background:#1e293b;color:#94a3b8}.dark .jsm-select-chevron{color:#64748b}\n"] }]
|
|
1737
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".jsm-field{display:flex;flex-direction:column;gap:.375rem}.jsm-field-label{display:block;font-size:.8125rem;font-weight:600;color:#374151}.jsm-field-hint{font-size:.75rem;color:#6b7280;margin:0;line-height:1.4}.jsm-required{color:#dc2626;margin-left:.125rem}.jsm-example{font-size:.6875rem;color:#6b7280;margin:0}.jsm-input,.jsm-textarea,.jsm-select{width:100%;border-radius:.5rem;border:1.5px solid #6b7280;background:Canvas;padding:.5rem .75rem;font-size:.875rem;color:CanvasText;outline:none;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s;font-family:inherit;box-sizing:border-box}.jsm-input:hover,.jsm-textarea:hover,.jsm-select:hover{border-color:#4b5563}.jsm-input:focus,.jsm-textarea:focus,.jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f126}.jsm-input--error,.jsm-textarea--error,.jsm-select--error{border-color:#dc2626!important;background:#fff5f5}.jsm-input--error:focus,.jsm-textarea--error:focus,.jsm-select--error:focus{box-shadow:0 0 0 3px #f8717133!important}.jsm-textarea{resize:vertical;min-height:6rem}.jsm-select-wrap{position:relative}.jsm-select{appearance:none;padding-right:2.25rem;cursor:pointer}.jsm-select-chevron{position:absolute;right:.625rem;top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:#6b7280;pointer-events:none}.jsm-toggle-label{display:inline-flex;align-items:center;gap:.625rem;cursor:pointer;-webkit-user-select:none;user-select:none;min-height:1.5rem}.jsm-toggle-track{position:relative;display:inline-flex;align-items:center;width:2.25rem;height:1.25rem;border-radius:9999px;flex-shrink:0;background:#6b7280;transition:background .2s}.jsm-toggle-track.jsm-on{background:#4f46e5}.jsm-toggle-thumb{display:inline-block;width:1rem;height:1rem;border-radius:9999px;background:#fff;box-shadow:0 1px 3px #0003;transform:translate(.125rem);transition:transform .2s}.jsm-toggle-track.jsm-on .jsm-toggle-thumb{transform:translate(1.125rem)}.jsm-toggle-text{font-size:.875rem;font-weight:500;color:#374151}.jsm-btn-primary{display:inline-flex;align-items:center;gap:.25rem;padding:.375rem .75rem;border-radius:.5rem;font-size:.8125rem;font-weight:600;background:#4f46e5;color:#fff;border:none;cursor:pointer;box-shadow:0 1px 2px #4f46e54d;transition:background .15s,transform .1s,box-shadow .15s;white-space:nowrap;font-family:inherit}.jsm-btn-primary:hover{background:#4338ca;transform:translateY(-1px);box-shadow:0 3px 8px #4f46e54d}.jsm-btn-primary:active{transform:translateY(0)}.jsm-btn-primary:disabled{opacity:.45;cursor:not-allowed;transform:none}.jsm-btn-danger{display:inline-flex;align-items:center;gap:.25rem;padding:.25rem .5rem;border-radius:.375rem;font-size:.75rem;font-weight:600;background:transparent;color:#b91c1c;min-height:1.5rem;border:1.5px solid #fca5a5;cursor:pointer;transition:background .15s,border-color .15s;font-family:inherit}.jsm-btn-danger:hover{background:#fee2e2;border-color:#f87171}.jsm-error-list{display:flex;flex-direction:column;gap:.25rem;margin-top:.25rem}.jsm-error-msg{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#dc2626;font-weight:500}.jsm-error-icon{width:.875rem;height:.875rem;flex-shrink:0}.jsm-badge-row{display:flex;flex-wrap:wrap;gap:.375rem}.jsm-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:600;letter-spacing:.02em;text-transform:uppercase}.jsm-badge--deprecated{background:#fef3c7;color:#92400e}.jsm-badge--readonly{background:#f1f5f9;color:#475569}.jsm-badge--writeonly{background:#dbeafe;color:#1e40af}.jsm-badge--not{background:#fee2e2;color:#991b1b}.jsm-badge--nullable{background:#f3f4f6;color:#4b5563}.jsm-fieldset{border:1.5px solid #e5e7eb;border-radius:.875rem;padding:1.25rem;background:transparent;box-shadow:0 1px 3px #0000000f;transition:box-shadow .2s;box-sizing:border-box}.jsm-fieldset:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114,0 1px 3px #0000000f}.jsm-legend{display:inline-flex;align-items:center;gap:.375rem;padding:0 .5rem;font-size:.875rem;font-weight:700;color:#1f2937}.jsm-obj-grid{display:grid;grid-template-columns:1fr;gap:1rem}@media (min-width:640px){.jsm-obj-grid{grid-template-columns:repeat(2,1fr)}}.jsm-obj-complex{display:flex;flex-direction:column;gap:1rem;margin-top:1rem}.jsm-dynamic-key-header{display:flex;align-items:center;justify-content:space-between;padding:.25rem .5rem;background:#f9fafb;border-radius:.375rem;border:1px dashed #d1d5db;margin-bottom:.25rem}.jsm-dynamic-key-label{font-size:.75rem;font-weight:600;color:#6b7280;font-family:monospace}.jsm-add-prop{margin-top:1rem;padding:.875rem;background:#f9fafb;border-radius:.625rem;border:1.5px dashed #d1d5db;display:flex;flex-direction:column;gap:.5rem}.jsm-add-prop-label{font-size:.75rem;font-weight:600;color:#6b7280;text-transform:uppercase;letter-spacing:.04em}.jsm-add-prop-row{display:flex;gap:.5rem;align-items:center}.jsm-input--sm{padding:.375rem .625rem;font-size:.8125rem}.jsm-array-block{display:flex;flex-direction:column;gap:.75rem}.jsm-array-header{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem}.jsm-array-title{font-size:.875rem;font-weight:700;color:#1f2937;display:flex;align-items:center;gap:.375rem}.jsm-array-items{display:flex;flex-direction:column;gap:.75rem}.jsm-array-item{border:1.5px solid #e5e7eb;border-radius:.75rem;padding:.875rem;background:transparent;box-shadow:0 1px 2px #0000000a;transition:border-color .15s,box-shadow .15s}.jsm-array-item:focus-within{border-color:#c7d2fe;box-shadow:0 0 0 3px #6366f114}.jsm-array-item-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.jsm-array-index{display:inline-flex;align-items:center;justify-content:center;width:1.5rem;height:1.5rem;border-radius:9999px;background:#eef2ff;color:#4f46e5;font-size:.6875rem;font-weight:700}.jsm-empty-array{display:flex;flex-direction:column;align-items:center;gap:.5rem;padding:2rem 1rem;border:1.5px dashed #e5e7eb;border-radius:.75rem;color:#6b7280;font-size:.8125rem;text-align:center}.jsm-contains-hint{display:flex;align-items:center;gap:.375rem;font-size:.75rem;color:#4f46e5;background:#eef2ff;border-radius:.375rem;padding:.375rem .625rem}.jsm-combinator{border:1.5px solid #e5e7eb;border-radius:.875rem;overflow:hidden;background:transparent;box-shadow:0 1px 3px #0000000f}.jsm-combinator-header{display:flex;align-items:flex-start;justify-content:space-between;padding:.875rem 1rem;background:#00000008;border-bottom:1.5px solid #e5e7eb}.jsm-combinator-title{font-size:.875rem;font-weight:700;color:#1f2937}.jsm-combinator-body{padding:1rem}.jsm-combinator-hint{font-size:.75rem;color:#6b7280;margin:.25rem 0 0}.jsm-oneof-tabs{display:flex;overflow-x:auto;border-bottom:1.5px solid #e5e7eb}.jsm-tab{padding:.5rem 1rem;font-size:.8125rem;font-weight:500;color:#6b7280;border:none;background:transparent;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1.5px;transition:color .15s,border-color .15s;white-space:nowrap;font-family:inherit}.jsm-tab:hover{color:#4f46e5}.jsm-tab--active{color:#4f46e5;border-bottom-color:#4f46e5;font-weight:600}.jsm-anyof-options{display:flex;flex-wrap:wrap;gap:.5rem;padding:.75rem 1rem;border-bottom:1.5px solid #e5e7eb}.jsm-anyof-option{display:inline-flex;align-items:center;gap:.375rem;padding:.375rem .75rem;border-radius:9999px;border:1.5px solid #6b7280;font-size:.8125rem;font-weight:500;color:#6b7280;cursor:pointer;transition:all .15s;background:transparent}.jsm-anyof-option:hover{border-color:#a5b4fc;color:#4f46e5}.jsm-anyof-option--active{border-color:#6366f1;background:#eef2ff;color:#4f46e5}.jsm-allof-section{border-left:3px solid #e0e7ff;padding-left:1rem}.jsm-combinator-badge{display:inline-flex;align-items:center;border-radius:9999px;padding:.125rem .5rem;font-size:.6875rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;flex-shrink:0;margin-left:.75rem}.jsm-badge--oneof{background:#dbeafe;color:#1e40af}.jsm-badge--anyof{background:#ede9fe;color:#5b21b6}.jsm-badge--allof{background:#ccfbf1;color:#065f46}.jsm-input:focus-visible,.jsm-textarea:focus-visible,.jsm-select:focus-visible,.jsm-btn-primary:focus-visible,.jsm-btn-danger:focus-visible,.jsm-tab:focus-visible{outline:2px solid #4f46e5;outline-offset:2px}.jsm-toggle-label:has(input:focus-visible) .jsm-toggle-track,.jsm-anyof-option:has(input:focus-visible){outline:2px solid #4f46e5;outline-offset:2px}.dark .jsm-field-label{color:#d1d5db}.dark .jsm-required{color:#f87171}.dark .jsm-example{color:#9ca3af}.dark .jsm-input:focus-visible,.dark .jsm-textarea:focus-visible,.dark .jsm-select:focus-visible,.dark .jsm-btn-primary:focus-visible,.dark .jsm-btn-danger:focus-visible,.dark .jsm-tab:focus-visible,.dark .jsm-toggle-label:has(input:focus-visible) .jsm-toggle-track,.dark .jsm-anyof-option:has(input:focus-visible){outline-color:#818cf8}.dark .jsm-btn-danger{color:#f87171;border-color:#f87171}.dark .jsm-btn-danger:hover{background:#f8717126}.dark .jsm-field-hint{color:#9ca3af}.dark .jsm-toggle-track{background:#64748b}.dark .jsm-toggle-track.jsm-on{background:#6366f1}.dark .jsm-toggle-text{color:#d1d5db}.dark .jsm-input,.dark .jsm-textarea,.dark .jsm-select{border-color:#64748b;color:#f1f5f9}.dark .jsm-input:focus,.dark .jsm-textarea:focus,.dark .jsm-select:focus{border-color:#6366f1;box-shadow:0 0 0 3px #6366f133}.dark .jsm-input--error,.dark .jsm-textarea--error,.dark .jsm-select--error{border-color:#f87171!important;background:#f871711a}.dark .jsm-fieldset{border-color:#334155}.dark .jsm-fieldset:focus-within{border-color:#6366f1}.dark .jsm-legend{color:#f1f5f9}.dark .jsm-combinator{border-color:#334155}.dark .jsm-combinator-header{background:#ffffff0a;border-color:#334155}.dark .jsm-combinator-title{color:#f1f5f9}.dark .jsm-oneof-tabs{border-color:#334155}.dark .jsm-tab{color:#94a3b8}.dark .jsm-tab--active{color:#818cf8;border-bottom-color:#818cf8}.dark .jsm-anyof-options{border-color:#334155}.dark .jsm-anyof-option{border-color:#64748b;color:#94a3b8;background:#0f172a}.dark .jsm-anyof-option--active{border-color:#6366f1;background:#6366f126;color:#818cf8}.dark .jsm-allof-section{border-left-color:#3730a3}.dark .jsm-array-item{border-color:#334155}.dark .jsm-array-item:focus-within{border-color:#6366f1}.dark .jsm-array-index{background:#6366f133;color:#818cf8}.dark .jsm-empty-array{border-color:#334155;color:#94a3b8}.dark .jsm-contains-hint{background:#6366f126;color:#818cf8}.dark .jsm-add-prop{background:#1e293b66;border-color:#475569}.dark .jsm-add-prop-label{color:#94a3b8}.dark .jsm-dynamic-key-header{background:#1e293b80;border-color:#475569}.dark .jsm-dynamic-key-label{color:#94a3b8}.dark .jsm-error-msg{color:#f87171}.dark .jsm-array-title{color:#f1f5f9}.dark .jsm-badge--deprecated{background:#d9770633;color:#fbbf24}.dark .jsm-badge--readonly{background:#1e293b;color:#94a3b8}.dark .jsm-badge--writeonly{background:#2563eb33;color:#60a5fa}.dark .jsm-badge--not{background:#dc262633;color:#f87171}.dark .jsm-badge--nullable{background:#1e293b;color:#94a3b8}.dark .jsm-select-chevron{color:#94a3b8}\n"] }]
|
|
1579
1738
|
}], ctorParameters: () => [{ type: JsonSchemaFormService }, { type: JsonSchemaValidationService }, { type: i0.ChangeDetectorRef }, { type: JsonSchemaFormOptions, decorators: [{
|
|
1580
1739
|
type: Optional
|
|
1581
1740
|
}] }], propDecorators: { schema: [{
|
|
@@ -1788,6 +1947,8 @@ class JsonSchemaFormComponent {
|
|
|
1788
1947
|
* either way); the emitted value is always a JSON number.
|
|
1789
1948
|
*/
|
|
1790
1949
|
decimalSeparator = '.';
|
|
1950
|
+
/** Texts shown by the form (translate them here); omitted keys keep the English default. */
|
|
1951
|
+
labels = {};
|
|
1791
1952
|
formReady = new EventEmitter();
|
|
1792
1953
|
valueChange = new EventEmitter();
|
|
1793
1954
|
schemaReady = new EventEmitter();
|
|
@@ -1815,6 +1976,9 @@ class JsonSchemaFormComponent {
|
|
|
1815
1976
|
if (changes['decimalSeparator']) {
|
|
1816
1977
|
this.options.decimalSeparator = this.decimalSeparator;
|
|
1817
1978
|
}
|
|
1979
|
+
if (changes['labels']) {
|
|
1980
|
+
this.options.labels = { ...DEFAULT_LABELS, ...this.labels };
|
|
1981
|
+
}
|
|
1818
1982
|
if (changes['schema']) {
|
|
1819
1983
|
// Schema changed — full rebuild required
|
|
1820
1984
|
void this.buildForm();
|
|
@@ -1913,20 +2077,20 @@ class JsonSchemaFormComponent {
|
|
|
1913
2077
|
});
|
|
1914
2078
|
}
|
|
1915
2079
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: JsonSchemaFormComponent, deps: [{ token: JsonSchemaFormService }, { token: JsonSchemaResolverService }, { token: JsonSchemaValidationService }, { token: i0.ChangeDetectorRef }, { token: JsonSchemaFormOptions }, { token: JsonSchemaStylesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1916
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: JsonSchemaFormComponent, isStandalone: true, selector: "jsm-json-schema-form", inputs: { schema: "schema", value: "value", data: "data", allowAdditionalProperties: "allowAdditionalProperties", decimalSeparator: "decimalSeparator" }, outputs: { formReady: "formReady", valueChange: "valueChange", schemaReady: "schemaReady", schemaErrors: "schemaErrors" }, providers: [JsonSchemaFormOptions], usesOnChanges: true, ngImport: i0, template: `
|
|
2080
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: JsonSchemaFormComponent, isStandalone: true, selector: "jsm-json-schema-form", inputs: { schema: "schema", value: "value", data: "data", allowAdditionalProperties: "allowAdditionalProperties", decimalSeparator: "decimalSeparator", labels: "labels" }, outputs: { formReady: "formReady", valueChange: "valueChange", schemaReady: "schemaReady", schemaErrors: "schemaErrors" }, providers: [JsonSchemaFormOptions], usesOnChanges: true, ngImport: i0, template: `
|
|
1917
2081
|
<div class="jsm-root">
|
|
1918
2082
|
<form class="w-full space-y-5">
|
|
1919
2083
|
<div *ngIf="resolvedSchema?.title || resolvedSchema?.description" class="space-y-0.5">
|
|
1920
|
-
<h2 class="text-lg font-bold tracking-tight text-slate-900 dark:text-white">{{ resolvedSchema?.title ||
|
|
2084
|
+
<h2 class="text-lg font-bold tracking-tight text-slate-900 dark:text-white">{{ resolvedSchema?.title || options.labels.formTitle }}</h2>
|
|
1921
2085
|
<p *ngIf="resolvedSchema?.description" class="text-sm text-slate-500 dark:text-slate-400">{{ resolvedSchema?.description }}</p>
|
|
1922
2086
|
</div>
|
|
1923
2087
|
|
|
1924
|
-
<div *ngIf="loading" class="flex items-center gap-2 py-6 text-sm text-slate-500 dark:text-slate-400"
|
|
1925
|
-
<svg class="h-4 w-4 animate-spin text-indigo-500 dark:text-indigo-400" viewBox="0 0 24 24" fill="none">
|
|
2088
|
+
<div *ngIf="loading" class="flex items-center gap-2 py-6 text-sm text-slate-500 dark:text-slate-400" role="status">
|
|
2089
|
+
<svg class="h-4 w-4 animate-spin text-indigo-500 dark:text-indigo-400" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
1926
2090
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
|
1927
2091
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
|
1928
2092
|
</svg>
|
|
1929
|
-
|
|
2093
|
+
{{ options.labels.resolving }}
|
|
1930
2094
|
</div>
|
|
1931
2095
|
|
|
1932
2096
|
<!-- schema structural errors panel -->
|
|
@@ -1934,16 +2098,16 @@ class JsonSchemaFormComponent {
|
|
|
1934
2098
|
class="rounded-xl border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-900/20 p-4 space-y-3"
|
|
1935
2099
|
role="alert">
|
|
1936
2100
|
<div class="flex items-center gap-2">
|
|
1937
|
-
<svg class="w-4 h-4 shrink-0 text-amber-600 dark:text-amber-400" viewBox="0 0 16 16" fill="none">
|
|
2101
|
+
<svg class="w-4 h-4 shrink-0 text-amber-600 dark:text-amber-400" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1938
2102
|
<path d="M8 2L1.5 13.5h13L8 2z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>
|
|
1939
2103
|
<path d="M8 6v3.5M8 11.5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
1940
2104
|
</svg>
|
|
1941
2105
|
<span class="text-sm font-semibold text-amber-800 dark:text-amber-300">
|
|
1942
|
-
|
|
2106
|
+
{{ options.labels.schemaErrorsTitle }} ({{ schemaErrorList.length }})
|
|
1943
2107
|
</span>
|
|
1944
2108
|
</div>
|
|
1945
2109
|
<p class="text-xs text-amber-700 dark:text-amber-400">
|
|
1946
|
-
|
|
2110
|
+
{{ options.labels.schemaErrorsHint }}
|
|
1947
2111
|
</p>
|
|
1948
2112
|
<div class="space-y-2">
|
|
1949
2113
|
<div *ngFor="let err of schemaErrorList"
|
|
@@ -1977,16 +2141,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1977
2141
|
<div class="jsm-root">
|
|
1978
2142
|
<form class="w-full space-y-5">
|
|
1979
2143
|
<div *ngIf="resolvedSchema?.title || resolvedSchema?.description" class="space-y-0.5">
|
|
1980
|
-
<h2 class="text-lg font-bold tracking-tight text-slate-900 dark:text-white">{{ resolvedSchema?.title ||
|
|
2144
|
+
<h2 class="text-lg font-bold tracking-tight text-slate-900 dark:text-white">{{ resolvedSchema?.title || options.labels.formTitle }}</h2>
|
|
1981
2145
|
<p *ngIf="resolvedSchema?.description" class="text-sm text-slate-500 dark:text-slate-400">{{ resolvedSchema?.description }}</p>
|
|
1982
2146
|
</div>
|
|
1983
2147
|
|
|
1984
|
-
<div *ngIf="loading" class="flex items-center gap-2 py-6 text-sm text-slate-500 dark:text-slate-400"
|
|
1985
|
-
<svg class="h-4 w-4 animate-spin text-indigo-500 dark:text-indigo-400" viewBox="0 0 24 24" fill="none">
|
|
2148
|
+
<div *ngIf="loading" class="flex items-center gap-2 py-6 text-sm text-slate-500 dark:text-slate-400" role="status">
|
|
2149
|
+
<svg class="h-4 w-4 animate-spin text-indigo-500 dark:text-indigo-400" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
1986
2150
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
|
1987
2151
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
|
1988
2152
|
</svg>
|
|
1989
|
-
|
|
2153
|
+
{{ options.labels.resolving }}
|
|
1990
2154
|
</div>
|
|
1991
2155
|
|
|
1992
2156
|
<!-- schema structural errors panel -->
|
|
@@ -1994,16 +2158,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1994
2158
|
class="rounded-xl border border-amber-300 dark:border-amber-700 bg-amber-50 dark:bg-amber-900/20 p-4 space-y-3"
|
|
1995
2159
|
role="alert">
|
|
1996
2160
|
<div class="flex items-center gap-2">
|
|
1997
|
-
<svg class="w-4 h-4 shrink-0 text-amber-600 dark:text-amber-400" viewBox="0 0 16 16" fill="none">
|
|
2161
|
+
<svg class="w-4 h-4 shrink-0 text-amber-600 dark:text-amber-400" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
1998
2162
|
<path d="M8 2L1.5 13.5h13L8 2z" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>
|
|
1999
2163
|
<path d="M8 6v3.5M8 11.5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
|
2000
2164
|
</svg>
|
|
2001
2165
|
<span class="text-sm font-semibold text-amber-800 dark:text-amber-300">
|
|
2002
|
-
|
|
2166
|
+
{{ options.labels.schemaErrorsTitle }} ({{ schemaErrorList.length }})
|
|
2003
2167
|
</span>
|
|
2004
2168
|
</div>
|
|
2005
2169
|
<p class="text-xs text-amber-700 dark:text-amber-400">
|
|
2006
|
-
|
|
2170
|
+
{{ options.labels.schemaErrorsHint }}
|
|
2007
2171
|
</p>
|
|
2008
2172
|
<div class="space-y-2">
|
|
2009
2173
|
<div *ngFor="let err of schemaErrorList"
|
|
@@ -2041,6 +2205,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2041
2205
|
type: Input
|
|
2042
2206
|
}], decimalSeparator: [{
|
|
2043
2207
|
type: Input
|
|
2208
|
+
}], labels: [{
|
|
2209
|
+
type: Input
|
|
2044
2210
|
}], formReady: [{
|
|
2045
2211
|
type: Output
|
|
2046
2212
|
}], valueChange: [{
|
|
@@ -2068,5 +2234,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2068
2234
|
* Generated bundle index. Do not edit.
|
|
2069
2235
|
*/
|
|
2070
2236
|
|
|
2071
|
-
export { JsonSchemaFormComponent, JsonSchemaFormModule, JsonSchemaFormOptions, JsonSchemaFormService, JsonSchemaNodeComponent, JsonSchemaResolverService, JsonSchemaStylesService, JsonSchemaValidationService, NumericInputDirective, formatNumeric, localizeNumbers, normalizeValue, parseNumericText, sanitizeNumericText };
|
|
2237
|
+
export { DEFAULT_LABELS, JsonSchemaFormComponent, JsonSchemaFormModule, JsonSchemaFormOptions, JsonSchemaFormService, JsonSchemaNodeComponent, JsonSchemaResolverService, JsonSchemaStylesService, JsonSchemaValidationService, NumericInputDirective, formatLabel, formatNumeric, localizeNumbers, normalizeValue, parseNumericText, sanitizeNumericText };
|
|
2072
2238
|
//# sourceMappingURL=elle96-ng-json-schema-manager.mjs.map
|