@formio/js 5.4.2 → 5.4.4-api99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/formio.embed.js +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.embed.min.js.LICENSE.txt +1 -1
- package/dist/formio.form.js +25 -25
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +1 -1
- package/dist/formio.full.js +27 -27
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +1 -1
- package/dist/formio.js +7 -7
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +1 -1
- package/dist/formio.utils.js +2 -2
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +1 -1
- package/lib/cjs/Element.js +1 -1
- package/lib/cjs/Embed.js +1 -1
- package/lib/cjs/Formio.js +1 -1
- package/lib/cjs/Wizard.d.ts +1 -0
- package/lib/cjs/Wizard.js +15 -0
- package/lib/cjs/components/datagrid/DataGrid.js +8 -0
- package/lib/cjs/components/file/File.js +12 -5
- package/lib/cjs/components/file/editForm/File.edit.file.d.ts +9 -3
- package/lib/cjs/components/file/editForm/File.edit.file.js +20 -23
- package/lib/cjs/components/html/HTML.d.ts +1 -1
- package/lib/cjs/components/html/HTML.js +7 -5
- package/lib/cjs/components/number/Number.js +5 -1
- package/lib/cjs/components/radio/Radio.js +10 -0
- package/lib/cjs/components/signature/Signature.js +16 -14
- package/lib/cjs/components/signature/editForm/Signature.edit.display.d.ts +4 -10
- package/lib/cjs/components/signature/editForm/Signature.edit.display.js +8 -8
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/providers/storage/indexeddb.js +14 -5
- package/lib/cjs/providers/storage/url.js +13 -2
- package/lib/cjs/providers/storage/xhr.js +1 -1
- package/lib/cjs/templates/index.d.ts +1 -0
- package/lib/mjs/Element.js +1 -1
- package/lib/mjs/Embed.js +1 -1
- package/lib/mjs/Formio.js +1 -1
- package/lib/mjs/Wizard.d.ts +1 -0
- package/lib/mjs/Wizard.js +15 -0
- package/lib/mjs/components/datagrid/DataGrid.js +7 -0
- package/lib/mjs/components/file/File.js +12 -5
- package/lib/mjs/components/file/editForm/File.edit.file.d.ts +9 -3
- package/lib/mjs/components/file/editForm/File.edit.file.js +20 -23
- package/lib/mjs/components/html/HTML.d.ts +1 -1
- package/lib/mjs/components/html/HTML.js +7 -5
- package/lib/mjs/components/number/Number.js +5 -1
- package/lib/mjs/components/radio/Radio.js +10 -0
- package/lib/mjs/components/signature/Signature.js +15 -13
- package/lib/mjs/components/signature/editForm/Signature.edit.display.d.ts +4 -10
- package/lib/mjs/components/signature/editForm/Signature.edit.display.js +6 -8
- package/lib/mjs/package.json +1 -1
- package/lib/mjs/providers/storage/indexeddb.js +14 -5
- package/lib/mjs/providers/storage/url.js +13 -2
- package/lib/mjs/providers/storage/xhr.js +1 -1
- package/lib/mjs/templates/index.d.ts +1 -0
- package/package.json +3 -3
|
@@ -42,6 +42,7 @@ export default class FileComponent extends Field {
|
|
|
42
42
|
fileMinSize: '0KB',
|
|
43
43
|
fileMaxSize: '1GB',
|
|
44
44
|
uploadOnly: false,
|
|
45
|
+
options: {},
|
|
45
46
|
}, ...extend);
|
|
46
47
|
}
|
|
47
48
|
static get builderInfo() {
|
|
@@ -109,7 +110,7 @@ export default class FileComponent extends Field {
|
|
|
109
110
|
return [];
|
|
110
111
|
}
|
|
111
112
|
getValueAsString(value, options) {
|
|
112
|
-
if (options?.review && !this.component.uploadOnly) {
|
|
113
|
+
if (options?.review && !this.component.uploadOnly && !options?.pdf) {
|
|
113
114
|
return _.map(value, (val, index) => {
|
|
114
115
|
return `<a href="${val.url || '#'}" target="_blank" data-path='${this.path}' data-fileindex='${index}'>${val.originalName}</a>`;
|
|
115
116
|
}).join(', ');
|
|
@@ -633,7 +634,9 @@ export default class FileComponent extends Field {
|
|
|
633
634
|
originalName: escapedFileName,
|
|
634
635
|
fileKey: this.component.fileKey || 'file',
|
|
635
636
|
storage: this.component.storage,
|
|
636
|
-
options: this.component.
|
|
637
|
+
options: this.component.storage === 'url'
|
|
638
|
+
? (this.component.urlRequestOptions || this.component.options)
|
|
639
|
+
: this.component.options,
|
|
637
640
|
file,
|
|
638
641
|
size: file.size,
|
|
639
642
|
status: 'info',
|
|
@@ -862,7 +865,9 @@ export default class FileComponent extends Field {
|
|
|
862
865
|
}
|
|
863
866
|
}
|
|
864
867
|
async deleteFile(fileInfo) {
|
|
865
|
-
const
|
|
868
|
+
const options = this.component.storage === 'url'
|
|
869
|
+
? (this.component.urlRequestOptions || this.component.options || {})
|
|
870
|
+
: (this.component.options || {});
|
|
866
871
|
if (fileInfo &&
|
|
867
872
|
['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage)) {
|
|
868
873
|
const { fileService } = this;
|
|
@@ -990,7 +995,7 @@ export default class FileComponent extends Field {
|
|
|
990
995
|
? response
|
|
991
996
|
: response.type === 'abort'
|
|
992
997
|
? this.t('requestAborted')
|
|
993
|
-
: response.toString();
|
|
998
|
+
: response.message || response.toString();
|
|
994
999
|
this.emit('fileUploadingEnd', Promise.reject(response));
|
|
995
1000
|
this.emit(_.get(response, 'type') === 'abort' ? 'fileUploadCanceled' : 'fileUploadError', {
|
|
996
1001
|
fileToSync,
|
|
@@ -1054,7 +1059,9 @@ export default class FileComponent extends Field {
|
|
|
1054
1059
|
}
|
|
1055
1060
|
}
|
|
1056
1061
|
getFile(fileInfo) {
|
|
1057
|
-
const
|
|
1062
|
+
const options = this.component.storage === 'url'
|
|
1063
|
+
? (this.component.urlRequestOptions || this.component.options || {})
|
|
1064
|
+
: (this.component.options || {});
|
|
1058
1065
|
const { fileService } = this;
|
|
1059
1066
|
if (!fileService) {
|
|
1060
1067
|
return alert(this.t('noFileService'));
|
|
@@ -131,11 +131,10 @@ declare const _default: ({
|
|
|
131
131
|
values?: undefined;
|
|
132
132
|
} | {
|
|
133
133
|
type: string;
|
|
134
|
-
input: boolean;
|
|
135
134
|
key: string;
|
|
136
135
|
label: string;
|
|
137
136
|
weight: number;
|
|
138
|
-
|
|
137
|
+
input: boolean;
|
|
139
138
|
conditional: {
|
|
140
139
|
json: {
|
|
141
140
|
in: (string[] | {
|
|
@@ -145,12 +144,19 @@ declare const _default: ({
|
|
|
145
144
|
'=='?: undefined;
|
|
146
145
|
};
|
|
147
146
|
};
|
|
147
|
+
components: {
|
|
148
|
+
type: string;
|
|
149
|
+
input: boolean;
|
|
150
|
+
key: string;
|
|
151
|
+
label: string;
|
|
152
|
+
placeholder: string;
|
|
153
|
+
}[];
|
|
154
|
+
placeholder?: undefined;
|
|
148
155
|
tooltip?: undefined;
|
|
149
156
|
valueProperty?: undefined;
|
|
150
157
|
dataSrc?: undefined;
|
|
151
158
|
data?: undefined;
|
|
152
159
|
tableView?: undefined;
|
|
153
|
-
components?: undefined;
|
|
154
160
|
rows?: undefined;
|
|
155
161
|
editor?: undefined;
|
|
156
162
|
as?: undefined;
|
|
@@ -79,30 +79,11 @@ export default [
|
|
|
79
79
|
},
|
|
80
80
|
},
|
|
81
81
|
{
|
|
82
|
-
type: '
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
label: 'Database',
|
|
82
|
+
type: 'container',
|
|
83
|
+
key: 'options',
|
|
84
|
+
label: 'IndexedDB options',
|
|
86
85
|
weight: 10,
|
|
87
|
-
placeholder: 'Enter the indexeddb database name',
|
|
88
|
-
conditional: {
|
|
89
|
-
json: {
|
|
90
|
-
in: [
|
|
91
|
-
{
|
|
92
|
-
var: 'data.storage',
|
|
93
|
-
},
|
|
94
|
-
['indexeddb'],
|
|
95
|
-
],
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
type: 'textfield',
|
|
101
86
|
input: true,
|
|
102
|
-
label: 'Table',
|
|
103
|
-
key: 'options.indexeddbTable',
|
|
104
|
-
weight: 10,
|
|
105
|
-
placeholder: 'Enter the name for indexeddb table',
|
|
106
87
|
conditional: {
|
|
107
88
|
json: {
|
|
108
89
|
in: [
|
|
@@ -113,10 +94,26 @@ export default [
|
|
|
113
94
|
],
|
|
114
95
|
},
|
|
115
96
|
},
|
|
97
|
+
components: [
|
|
98
|
+
{
|
|
99
|
+
type: 'textfield',
|
|
100
|
+
input: true,
|
|
101
|
+
key: 'indexeddb',
|
|
102
|
+
label: 'Database',
|
|
103
|
+
placeholder: 'Enter the indexeddb database name',
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'textfield',
|
|
107
|
+
input: true,
|
|
108
|
+
key: 'indexeddbTable',
|
|
109
|
+
label: 'Table',
|
|
110
|
+
placeholder: 'Enter the name for indexeddb table',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
116
113
|
},
|
|
117
114
|
{
|
|
118
115
|
type: 'textarea',
|
|
119
|
-
key: '
|
|
116
|
+
key: 'urlRequestOptions',
|
|
120
117
|
label: 'Custom request options',
|
|
121
118
|
tooltip: 'Pass your custom xhr options(optional)',
|
|
122
119
|
rows: 5,
|
|
@@ -12,7 +12,7 @@ export default class HTMLComponent extends Component {
|
|
|
12
12
|
get content(): any;
|
|
13
13
|
get singleTags(): string[];
|
|
14
14
|
checkRefreshOn(changed: any): void;
|
|
15
|
-
renderContent(): any;
|
|
15
|
+
renderContent(content?: any): any;
|
|
16
16
|
render(): string;
|
|
17
17
|
get dataReady(): any;
|
|
18
18
|
attach(element: any): Promise<void>;
|
|
@@ -66,7 +66,7 @@ export default class HTMLComponent extends Component {
|
|
|
66
66
|
this.setContent(this.element, this.renderContent());
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
renderContent() {
|
|
69
|
+
renderContent(content = this.content) {
|
|
70
70
|
const submission = _.get(this.root, 'submission', {});
|
|
71
71
|
return this.renderTemplate('html', {
|
|
72
72
|
component: this.component,
|
|
@@ -82,23 +82,25 @@ export default class HTMLComponent extends Component {
|
|
|
82
82
|
}),
|
|
83
83
|
};
|
|
84
84
|
}),
|
|
85
|
-
content
|
|
85
|
+
content,
|
|
86
86
|
singleTags: this.singleTags,
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
render() {
|
|
90
|
-
return super.render(this.renderContent());
|
|
90
|
+
return super.render(this.renderContent(''));
|
|
91
91
|
}
|
|
92
92
|
get dataReady() {
|
|
93
93
|
return this.root?.submissionReady || Promise.resolve();
|
|
94
94
|
}
|
|
95
95
|
attach(element) {
|
|
96
96
|
this.loadRefs(element, { html: 'single' });
|
|
97
|
-
|
|
97
|
+
const setHtmlContent = () => {
|
|
98
98
|
if (this.refs.html) {
|
|
99
99
|
this.setContent(this.refs.html, this.content);
|
|
100
100
|
}
|
|
101
|
-
}
|
|
101
|
+
};
|
|
102
|
+
setHtmlContent();
|
|
103
|
+
this.dataReady.then(setHtmlContent);
|
|
102
104
|
return super.attach(element);
|
|
103
105
|
}
|
|
104
106
|
}
|
|
@@ -185,7 +185,11 @@ export default class NumberComponent extends Input {
|
|
|
185
185
|
return null;
|
|
186
186
|
}
|
|
187
187
|
const val = this.refs.input[index].value;
|
|
188
|
-
|
|
188
|
+
const result = val && val !== '-_' ? this.parseNumber(val) : null;
|
|
189
|
+
if (_.isNaN(result)) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
return result;
|
|
189
193
|
}
|
|
190
194
|
setValueAt(index, value, flags = {}) {
|
|
191
195
|
return super.setValueAt(index, this.formatValue(this.parseValue(value)), flags);
|
|
@@ -343,6 +343,16 @@ export default class RadioComponent extends ListComponent {
|
|
|
343
343
|
}
|
|
344
344
|
setItems(items) {
|
|
345
345
|
const listData = [];
|
|
346
|
+
// If the items is a string, then parse as JSON.
|
|
347
|
+
if (typeof items == 'string') {
|
|
348
|
+
try {
|
|
349
|
+
items = JSON.parse(items);
|
|
350
|
+
}
|
|
351
|
+
catch (err) {
|
|
352
|
+
console.warn(err.message);
|
|
353
|
+
items = [];
|
|
354
|
+
}
|
|
355
|
+
}
|
|
346
356
|
items?.forEach((item, i) => {
|
|
347
357
|
const valueAtProperty = _.get(item, this.component.valueProperty);
|
|
348
358
|
this.loadedOptions[i] = {
|
|
@@ -45,19 +45,21 @@ export default class SignatureComponent extends Input {
|
|
|
45
45
|
super.init();
|
|
46
46
|
this.currentWidth = 0;
|
|
47
47
|
this.scale = 1;
|
|
48
|
-
if (
|
|
49
|
-
this.component.width
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.component.height
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
if (this.options?.inFormBuilder) {
|
|
49
|
+
if (!this.component.width) {
|
|
50
|
+
this.component.width = '100%';
|
|
51
|
+
}
|
|
52
|
+
if (!this.component.height) {
|
|
53
|
+
this.component.height = '200px';
|
|
54
|
+
}
|
|
55
|
+
if (this.component.keepOverlayRatio &&
|
|
56
|
+
this.options.pdf &&
|
|
57
|
+
this.component.overlay?.width &&
|
|
58
|
+
this.component.overlay?.height) {
|
|
59
|
+
this.ratio = this.component.overlay?.width / this.component.overlay?.height;
|
|
60
|
+
this.component.width = '100%';
|
|
61
|
+
this.component.height = 'auto';
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
get emptyValue() {
|
|
@@ -6,7 +6,7 @@ declare const _default: ({
|
|
|
6
6
|
tooltip: string;
|
|
7
7
|
placeholder: string;
|
|
8
8
|
weight: number;
|
|
9
|
-
|
|
9
|
+
customConditional?: undefined;
|
|
10
10
|
ignore?: undefined;
|
|
11
11
|
} | {
|
|
12
12
|
type: string;
|
|
@@ -15,13 +15,7 @@ declare const _default: ({
|
|
|
15
15
|
label: string;
|
|
16
16
|
tooltip: string;
|
|
17
17
|
placeholder: string;
|
|
18
|
-
|
|
19
|
-
json: {
|
|
20
|
-
'!': {
|
|
21
|
-
var: string;
|
|
22
|
-
}[];
|
|
23
|
-
};
|
|
24
|
-
};
|
|
18
|
+
customConditional: (context: any) => boolean;
|
|
25
19
|
weight: number;
|
|
26
20
|
ignore?: undefined;
|
|
27
21
|
} | {
|
|
@@ -32,7 +26,7 @@ declare const _default: ({
|
|
|
32
26
|
key: string;
|
|
33
27
|
input: boolean;
|
|
34
28
|
placeholder?: undefined;
|
|
35
|
-
|
|
29
|
+
customConditional?: undefined;
|
|
36
30
|
ignore?: undefined;
|
|
37
31
|
} | {
|
|
38
32
|
key: string;
|
|
@@ -43,6 +37,6 @@ declare const _default: ({
|
|
|
43
37
|
tooltip?: undefined;
|
|
44
38
|
placeholder?: undefined;
|
|
45
39
|
weight?: undefined;
|
|
46
|
-
|
|
40
|
+
customConditional?: undefined;
|
|
47
41
|
})[];
|
|
48
42
|
export default _default;
|
|
@@ -15,10 +15,9 @@ export default [
|
|
|
15
15
|
label: 'Width',
|
|
16
16
|
tooltip: 'The width of the signature area.',
|
|
17
17
|
placeholder: 'Width',
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
18
|
+
customConditional: (context) => {
|
|
19
|
+
const isPdf = context.options?.editForm?.display === 'pdf';
|
|
20
|
+
return isPdf ? !context.data?.keepOverlayRatio : true;
|
|
22
21
|
},
|
|
23
22
|
weight: 50,
|
|
24
23
|
},
|
|
@@ -29,10 +28,9 @@ export default [
|
|
|
29
28
|
label: 'Height',
|
|
30
29
|
tooltip: 'The height of the signature area.',
|
|
31
30
|
placeholder: 'Height',
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
31
|
+
customConditional: (context) => {
|
|
32
|
+
const isPdf = context.options?.editForm?.display === 'pdf';
|
|
33
|
+
return isPdf ? !context.data?.keepOverlayRatio : true;
|
|
36
34
|
},
|
|
37
35
|
weight: 51,
|
|
38
36
|
},
|
package/lib/mjs/package.json
CHANGED
|
@@ -61,21 +61,30 @@ function indexeddb() {
|
|
|
61
61
|
});
|
|
62
62
|
},
|
|
63
63
|
downloadFile(file, options) {
|
|
64
|
+
const opts = options?.options || options || {};
|
|
65
|
+
const dbName = opts.indexeddb;
|
|
66
|
+
const tableName = opts.indexeddbTable;
|
|
67
|
+
if (!dbName || !tableName) {
|
|
68
|
+
return Promise.reject(new Error('IndexedDB storage options (indexeddb, indexeddbTable) are required for download'));
|
|
69
|
+
}
|
|
64
70
|
return new Promise((resolve) => {
|
|
65
|
-
const request = indexedDB.open(
|
|
71
|
+
const request = indexedDB.open(dbName);
|
|
66
72
|
request.onsuccess = function (event) {
|
|
67
73
|
const db = event.target.result;
|
|
68
74
|
resolve(db);
|
|
69
75
|
};
|
|
70
76
|
}).then((db) => {
|
|
71
77
|
return new Promise((resolve, reject) => {
|
|
72
|
-
const trans = db.transaction(
|
|
73
|
-
const store = trans.objectStore(
|
|
78
|
+
const trans = db.transaction(tableName, 'readonly');
|
|
79
|
+
const store = trans.objectStore(tableName).get(file.id);
|
|
74
80
|
store.onsuccess = () => {
|
|
75
81
|
trans.oncomplete = () => {
|
|
76
82
|
const result = store.result;
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
if (!result || !result.data) {
|
|
84
|
+
return reject(new Error('File not found in IndexedDB'));
|
|
85
|
+
}
|
|
86
|
+
const dbFile = new File([result.data], file.name, {
|
|
87
|
+
type: result.type,
|
|
79
88
|
});
|
|
80
89
|
const reader = new FileReader();
|
|
81
90
|
reader.onload = (event) => {
|
|
@@ -64,8 +64,19 @@ function url(formio) {
|
|
|
64
64
|
reject(xhr.response || 'Unable to upload file');
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
-
xhr.onerror = () =>
|
|
68
|
-
|
|
67
|
+
xhr.onerror = () => {
|
|
68
|
+
xhr.message =
|
|
69
|
+
xhr.status >= 400
|
|
70
|
+
? `${xhr.status} ${xhr.statusText || ''}`.trim()
|
|
71
|
+
: xhr.statusText && xhr.statusText.trim()
|
|
72
|
+
? xhr.statusText.trim()
|
|
73
|
+
: 'Unable to upload file';
|
|
74
|
+
return reject(xhr);
|
|
75
|
+
};
|
|
76
|
+
xhr.onabort = () => {
|
|
77
|
+
xhr.type = 'abort';
|
|
78
|
+
return reject(xhr);
|
|
79
|
+
};
|
|
69
80
|
let requestUrl = url + (url.indexOf('?') > -1 ? '&' : '?');
|
|
70
81
|
for (const key in query) {
|
|
71
82
|
requestUrl += `${key}=${query[key]}&`;
|
|
@@ -24,7 +24,7 @@ const XHR = {
|
|
|
24
24
|
.join('/');
|
|
25
25
|
},
|
|
26
26
|
async upload(formio, type, xhrCallback, file, fileName, dir, progressCallback, groupPermissions, groupId, abortCallback, multipartOptions) {
|
|
27
|
-
// Use makeRequest so portal plugins (e.g. x-remote-token) are applied.
|
|
27
|
+
// Use makeRequest so portal plugins (e.g. x-remote-token) are applied. GOTCHA(G-FJS05)
|
|
28
28
|
let serverResponse;
|
|
29
29
|
try {
|
|
30
30
|
serverResponse = await formio.makeRequest('file', `${formio.formUrl}/storage/${type}`, 'POST', {
|
|
@@ -43,6 +43,7 @@ declare namespace _default {
|
|
|
43
43
|
iconClass: (iconset: "fa" | "bi", name: string, spinning: boolean) => string;
|
|
44
44
|
cssClasses: {
|
|
45
45
|
'border-default': string;
|
|
46
|
+
'sr-only': string;
|
|
46
47
|
'formio-tab-panel-active': string;
|
|
47
48
|
'formio-tab-link-active': string;
|
|
48
49
|
'formio-tab-link-container-active': string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formio/js",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.4-api99.0",
|
|
4
4
|
"description": "JavaScript powered Forms with JSON Form Builder",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"tippy.js": "^6.3.7",
|
|
90
90
|
"uuid": "^9.0.0",
|
|
91
91
|
"vanilla-picker": "^2.12.3",
|
|
92
|
-
"@formio/
|
|
93
|
-
"@formio/
|
|
92
|
+
"@formio/core": "^2.8.0-api99.0",
|
|
93
|
+
"@formio/bootstrap": "^4.0.3"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
96
96
|
"@types/node": "^22.15.19",
|