@ekzo-dev/bootstrap-addons 5.2.5 → 5.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekzo-dev/bootstrap-addons",
|
|
3
3
|
"description": "Aurelia Bootstrap additional component",
|
|
4
|
-
"version": "5.2.
|
|
4
|
+
"version": "5.2.7",
|
|
5
5
|
"homepage": "https://github.com/ekzo-dev/aurelia-components/tree/main/packages/bootstrap-addons",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@ekzo-dev/bootstrap": "^5.2.11",
|
|
13
|
-
"@ekzo-dev/vanilla-jsoneditor": "^0.23.
|
|
13
|
+
"@ekzo-dev/vanilla-jsoneditor": "^0.23.7",
|
|
14
14
|
"@ekzo-dev/toolkit": "^1.2.4",
|
|
15
15
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
|
16
16
|
"@types/json-schema": "^7.0.14",
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<input ref="input" required.bind="inputRequired" />
|
|
3
3
|
<json-editor
|
|
4
|
-
ref="
|
|
5
|
-
|
|
4
|
+
ref="editorElement"
|
|
5
|
+
component.ref="editorComponent"
|
|
6
|
+
content.to-view="content"
|
|
6
7
|
validator.bind="validator"
|
|
7
8
|
read-only.bind="disabled"
|
|
8
9
|
on-render-value.one-time="onRenderValue"
|
|
9
10
|
on-render-menu.one-time="onRenderMenu"
|
|
11
|
+
on-change.one-time="onChange"
|
|
10
12
|
mode="text"
|
|
11
13
|
...$bindables="jsonEditorOptions"
|
|
12
14
|
></json-editor>
|
|
@@ -2,27 +2,31 @@ import template from './json-input.html';
|
|
|
2
2
|
|
|
3
3
|
import './json-input.scss';
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import Ajv, { ErrorObject, Options } from 'ajv';
|
|
9
|
-
import Ajv2019 from 'ajv/dist/2019';
|
|
10
|
-
import Ajv2020 from 'ajv/dist/2020';
|
|
11
|
-
import addFormats from 'ajv-formats';
|
|
12
|
-
import { bindable, BindingMode, customElement } from 'aurelia';
|
|
13
|
-
import { JSONValue, parsePath } from 'immutable-json-patch';
|
|
14
|
-
import {
|
|
5
|
+
import type {
|
|
6
|
+
Content,
|
|
7
|
+
JSONContent,
|
|
15
8
|
JSONEditorPropsOptional,
|
|
16
9
|
JSONSchema,
|
|
17
10
|
JSONSchemaDefinitions,
|
|
18
11
|
MenuItem,
|
|
19
12
|
RenderValueComponentDescription,
|
|
20
13
|
RenderValueProps,
|
|
14
|
+
TextContent,
|
|
21
15
|
ValidationError,
|
|
22
16
|
ValidationSeverity,
|
|
23
17
|
Validator,
|
|
24
18
|
} from 'vanilla-jsoneditor';
|
|
25
19
|
|
|
20
|
+
import { coerceBoolean } from '@ekzo-dev/toolkit';
|
|
21
|
+
import { JsonEditor } from '@ekzo-dev/vanilla-jsoneditor';
|
|
22
|
+
import { faUpRightAndDownLeftFromCenter } from '@fortawesome/free-solid-svg-icons/faUpRightAndDownLeftFromCenter';
|
|
23
|
+
import Ajv, { ErrorObject, Options } from 'ajv';
|
|
24
|
+
import Ajv2019 from 'ajv/dist/2019';
|
|
25
|
+
import Ajv2020 from 'ajv/dist/2020';
|
|
26
|
+
import addFormats from 'ajv-formats';
|
|
27
|
+
import { bindable, BindingMode, customElement } from 'aurelia';
|
|
28
|
+
import { JSONValue, parsePath } from 'immutable-json-patch';
|
|
29
|
+
|
|
26
30
|
@customElement({
|
|
27
31
|
name: 'bs-json-input',
|
|
28
32
|
template,
|
|
@@ -47,36 +51,34 @@ export class BsJsonInput {
|
|
|
47
51
|
@bindable()
|
|
48
52
|
jsonEditorOptions: JSONEditorPropsOptional = {};
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
valueCache?: unknown;
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
content?: JSONContent;
|
|
53
57
|
|
|
54
58
|
readonly input!: HTMLInputElement;
|
|
55
59
|
|
|
56
|
-
readonly
|
|
60
|
+
readonly editorElement!: HTMLElement;
|
|
61
|
+
|
|
62
|
+
readonly editorComponent!: JsonEditor;
|
|
57
63
|
|
|
58
|
-
|
|
59
|
-
this
|
|
60
|
-
this.editorModule = await import('vanilla-jsoneditor');
|
|
64
|
+
binding() {
|
|
65
|
+
this.#setContent(this.value);
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
valueChanged(value: unknown) {
|
|
64
|
-
this
|
|
65
|
-
|
|
66
|
-
if (value == null || value === '') {
|
|
67
|
-
this.input.setCustomValidity('');
|
|
68
|
-
}
|
|
69
|
+
this.#setContent(value);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
onRenderValue = (props: RenderValueProps): RenderValueComponentDescription[] => {
|
|
72
73
|
let result: RenderValueComponentDescription[] | null;
|
|
73
74
|
const { jsonSchema } = this;
|
|
75
|
+
const { editorModule } = this.editorComponent;
|
|
74
76
|
|
|
75
77
|
if (jsonSchema && typeof jsonSchema === 'object') {
|
|
76
|
-
result =
|
|
78
|
+
result = editorModule.renderJSONSchemaEnum(props, jsonSchema, this.#getSchemaDefinitions(jsonSchema));
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
return result ??
|
|
81
|
+
return result ?? editorModule.renderValue(props);
|
|
80
82
|
};
|
|
81
83
|
|
|
82
84
|
onRenderMenu = (items: MenuItem[]): MenuItem[] | undefined => {
|
|
@@ -91,7 +93,7 @@ export class BsJsonInput {
|
|
|
91
93
|
if (document.fullscreenElement) {
|
|
92
94
|
void document.exitFullscreen();
|
|
93
95
|
} else {
|
|
94
|
-
void this.
|
|
96
|
+
void this.editorElement.requestFullscreen();
|
|
95
97
|
}
|
|
96
98
|
},
|
|
97
99
|
icon: faUpRightAndDownLeftFromCenter,
|
|
@@ -100,36 +102,76 @@ export class BsJsonInput {
|
|
|
100
102
|
];
|
|
101
103
|
};
|
|
102
104
|
|
|
105
|
+
onChange = (content: Content): void => {
|
|
106
|
+
const { json, text } = content as JSONContent & TextContent;
|
|
107
|
+
|
|
108
|
+
if (json !== undefined) {
|
|
109
|
+
this.valueCache = json;
|
|
110
|
+
} else {
|
|
111
|
+
const message = 'Please enter a valid JSON string';
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
this.valueCache = text === '' ? '' : (this.jsonEditorOptions?.parser ?? JSON).parse(text);
|
|
115
|
+
|
|
116
|
+
if (this.input.validationMessage === message || text === '') {
|
|
117
|
+
this.input.setCustomValidity('');
|
|
118
|
+
}
|
|
119
|
+
} catch (e) {
|
|
120
|
+
if (e instanceof SyntaxError) {
|
|
121
|
+
this.input.setCustomValidity(message);
|
|
122
|
+
} else {
|
|
123
|
+
throw e;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
this.value = this.valueCache;
|
|
129
|
+
};
|
|
130
|
+
|
|
103
131
|
get inputRequired(): boolean {
|
|
104
132
|
return this.required && (this.value == null || this.value === '');
|
|
105
133
|
}
|
|
106
134
|
|
|
135
|
+
get schemaVersion(): string {
|
|
136
|
+
if (this.jsonSchema !== true) return undefined;
|
|
137
|
+
|
|
138
|
+
const { value } = this;
|
|
139
|
+
|
|
140
|
+
return value == null || value['$schema'] == null ? '' : (value['$schema'] as string);
|
|
141
|
+
}
|
|
142
|
+
|
|
107
143
|
get validator(): Validator | undefined {
|
|
108
|
-
const { schemaVersion, disabled } = this;
|
|
144
|
+
const { schemaVersion, disabled, ajvOptions, jsonSchema } = this;
|
|
109
145
|
// use raw object because proxies don't work with private properties
|
|
110
146
|
const rawThis = this['__raw__'] as BsJsonInput;
|
|
111
147
|
// use jsonSchema from raw object to pass original (non-proxied) object to AJV
|
|
112
|
-
const { jsonSchema } = rawThis;
|
|
148
|
+
const { jsonSchema: rawJsonSchema } = rawThis;
|
|
113
149
|
|
|
114
150
|
if (jsonSchema && typeof jsonSchema === 'object' && !disabled) {
|
|
115
|
-
const ajv = rawThis.#initAjv(jsonSchema.$schema as string);
|
|
151
|
+
const ajv = rawThis.#initAjv(jsonSchema.$schema as string, ajvOptions);
|
|
116
152
|
|
|
117
153
|
addFormats(ajv);
|
|
118
|
-
const validate = ajv.compile(
|
|
154
|
+
const validate = ajv.compile(rawJsonSchema);
|
|
119
155
|
|
|
120
156
|
if (validate.errors) {
|
|
121
157
|
throw validate.errors[0];
|
|
122
158
|
}
|
|
123
159
|
|
|
124
160
|
return (json: unknown): ValidationError[] => {
|
|
161
|
+
// do not validate empty documents
|
|
162
|
+
if (json === undefined) return [];
|
|
163
|
+
|
|
125
164
|
validate(json);
|
|
126
165
|
|
|
127
166
|
return rawThis.#processErrors(validate.errors, json);
|
|
128
167
|
};
|
|
129
168
|
} else if (schemaVersion != null && !disabled) {
|
|
130
|
-
const ajv = rawThis.#initAjv(schemaVersion);
|
|
169
|
+
const ajv = rawThis.#initAjv(schemaVersion, ajvOptions);
|
|
131
170
|
|
|
132
171
|
return (json: unknown): ValidationError[] => {
|
|
172
|
+
// do not validate empty documents
|
|
173
|
+
if (json === undefined) return [];
|
|
174
|
+
|
|
133
175
|
void ajv.validateSchema(json);
|
|
134
176
|
|
|
135
177
|
return rawThis.#processErrors(ajv.errors, json);
|
|
@@ -137,11 +179,21 @@ export class BsJsonInput {
|
|
|
137
179
|
}
|
|
138
180
|
}
|
|
139
181
|
|
|
140
|
-
#
|
|
182
|
+
#setContent(value: unknown): void {
|
|
183
|
+
if (value !== this.valueCache) {
|
|
184
|
+
// reset validation state before assigning new content
|
|
185
|
+
this.input?.setCustomValidity('');
|
|
186
|
+
|
|
187
|
+
this.content = { json: value };
|
|
188
|
+
this.valueCache = value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
#initAjv($schema: string, ajvOptions: Options): Ajv {
|
|
141
193
|
const options: Options = {
|
|
142
194
|
strict: false,
|
|
143
195
|
multipleOfPrecision: 2,
|
|
144
|
-
...
|
|
196
|
+
...ajvOptions,
|
|
145
197
|
};
|
|
146
198
|
let ajv: Ajv;
|
|
147
199
|
|
|
@@ -165,10 +217,6 @@ export class BsJsonInput {
|
|
|
165
217
|
return (schema.$defs ?? schema.definitions) as JSONSchemaDefinitions;
|
|
166
218
|
}
|
|
167
219
|
|
|
168
|
-
#getSchemaVersion(value: unknown): string {
|
|
169
|
-
return value === Object(value) && value['$schema'] ? (value['$schema'] as string) : '';
|
|
170
|
-
}
|
|
171
|
-
|
|
172
220
|
#processErrors(errors: ErrorObject[] | null, json: unknown): ValidationError[] {
|
|
173
221
|
const message = this.jsonSchema === true ? 'JSON is not a valid JSONSchema' : 'JSON does not match schema';
|
|
174
222
|
|