vanjs-jsf 0.0.11 → 0.0.12
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/README.md +10 -0
- package/dist/VanJsfField.d.ts +3 -0
- package/dist/VanJsfField.js +87 -7
- package/dist/VanJsfForm.js +13 -7
- package/dist/index.js.map +4 -4
- package/dist/main.js +34 -8
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -15,6 +15,16 @@ This library aims to provide a robust and flexible solution for dynamically gene
|
|
|
15
15
|
- [ ] **Validation Support**: Easily integrate JSON Schema-based validation for seamless user input handling.
|
|
16
16
|
- [ ] **Extensible Architecture**: Add custom widgets, field types, and behaviours as needed.
|
|
17
17
|
|
|
18
|
+
### Available components
|
|
19
|
+
The currently supported form element types are:
|
|
20
|
+
- text = "text",
|
|
21
|
+
- number = "number",
|
|
22
|
+
- textarea = "textarea",
|
|
23
|
+
- select = "select",
|
|
24
|
+
- radio = "radio",
|
|
25
|
+
- date = "date",
|
|
26
|
+
- fieldset = "fieldset"
|
|
27
|
+
|
|
18
28
|
### Use Cases
|
|
19
29
|
|
|
20
30
|
- Quickly generate forms for dashboards, admin panels, and dynamic web applications.
|
package/dist/VanJsfField.d.ts
CHANGED
|
@@ -18,7 +18,10 @@ export declare class VanJsfField extends VanJSComponent {
|
|
|
18
18
|
get inputType(): string;
|
|
19
19
|
get label(): string;
|
|
20
20
|
get class(): string;
|
|
21
|
+
get errorClass(): string;
|
|
22
|
+
get codemirrorExtension(): Array<any>;
|
|
21
23
|
get containerClass(): string;
|
|
24
|
+
get containerId(): string;
|
|
22
25
|
get titleClass(): string;
|
|
23
26
|
get descriptionClass(): string;
|
|
24
27
|
get description(): string;
|
package/dist/VanJsfField.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import van from "vanjs-core";
|
|
2
2
|
import { VanJSComponent } from "./VanJSComponent";
|
|
3
3
|
import pikaday from "pikaday";
|
|
4
|
+
import { basicSetup, EditorView } from "codemirror";
|
|
5
|
+
import { javascript, esLint } from "@codemirror/lang-javascript";
|
|
6
|
+
import { json, jsonParseLinter } from "@codemirror/lang-json";
|
|
7
|
+
import { lintGutter, linter, forEachDiagnostic } from "@codemirror/lint";
|
|
8
|
+
import * as eslint from "eslint-linter-browserify";
|
|
9
|
+
import globals from "globals";
|
|
4
10
|
const { div, p, input, label, textarea, legend, link, fieldset, span, select, option } = van.tags;
|
|
5
11
|
var FieldType;
|
|
6
12
|
(function (FieldType) {
|
|
7
13
|
FieldType["text"] = "text";
|
|
14
|
+
FieldType["code"] = "code";
|
|
8
15
|
FieldType["number"] = "number";
|
|
9
16
|
FieldType["textarea"] = "textarea";
|
|
10
17
|
FieldType["select"] = "select";
|
|
@@ -12,6 +19,21 @@ var FieldType;
|
|
|
12
19
|
FieldType["date"] = "date";
|
|
13
20
|
FieldType["fieldset"] = "fieldset";
|
|
14
21
|
})(FieldType || (FieldType = {}));
|
|
22
|
+
const eslintConfig = {
|
|
23
|
+
// eslint configuration
|
|
24
|
+
languageOptions: {
|
|
25
|
+
globals: {
|
|
26
|
+
...globals.node,
|
|
27
|
+
},
|
|
28
|
+
parserOptions: {
|
|
29
|
+
ecmaVersion: 2022,
|
|
30
|
+
sourceType: "module",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
rules: {
|
|
34
|
+
semi: ["error", "never"],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
15
37
|
export class VanJsfField extends VanJSComponent {
|
|
16
38
|
name;
|
|
17
39
|
field;
|
|
@@ -38,9 +60,58 @@ export class VanJsfField extends VanJSComponent {
|
|
|
38
60
|
get class() {
|
|
39
61
|
return this.field.class;
|
|
40
62
|
}
|
|
63
|
+
get errorClass() {
|
|
64
|
+
return this.field.errorClass;
|
|
65
|
+
}
|
|
66
|
+
get codemirrorExtension() {
|
|
67
|
+
const theme = EditorView.theme({
|
|
68
|
+
'.cm-content, .cm-gutter': {
|
|
69
|
+
"min-height": "150px",
|
|
70
|
+
},
|
|
71
|
+
'.cm-content': {
|
|
72
|
+
"min-height": "150px",
|
|
73
|
+
},
|
|
74
|
+
'.cm-gutters': {
|
|
75
|
+
margin: '1px',
|
|
76
|
+
},
|
|
77
|
+
'.cm-scroller': {
|
|
78
|
+
overflow: 'auto',
|
|
79
|
+
},
|
|
80
|
+
'.cm-wrap': {
|
|
81
|
+
border: '1px solid silver',
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
const extensions = [theme, EditorView.updateListener.of((e) => {
|
|
85
|
+
this.field.error = null;
|
|
86
|
+
forEachDiagnostic(e.state, (diag) => {
|
|
87
|
+
if (diag.severity === "error") {
|
|
88
|
+
this.field.error = diag.message;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
this.handleChange(this, e.state.doc.toString());
|
|
92
|
+
}), basicSetup, lintGutter()];
|
|
93
|
+
switch (this.field.codemirrorType) {
|
|
94
|
+
case "json":
|
|
95
|
+
extensions.push(json(), linter(jsonParseLinter()));
|
|
96
|
+
break;
|
|
97
|
+
case "javascript":
|
|
98
|
+
extensions.push(javascript(), linter(esLint(new eslint.Linter(), eslintConfig)));
|
|
99
|
+
break;
|
|
100
|
+
case "typescript":
|
|
101
|
+
extensions.push(javascript({ typescript: true }), linter(esLint(new eslint.Linter(), eslintConfig)));
|
|
102
|
+
break;
|
|
103
|
+
default:
|
|
104
|
+
extensions.push(javascript(), linter(esLint(new eslint.Linter(), eslintConfig)));
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return extensions;
|
|
108
|
+
}
|
|
41
109
|
get containerClass() {
|
|
42
110
|
return this.field.containerClass;
|
|
43
111
|
}
|
|
112
|
+
get containerId() {
|
|
113
|
+
return this.field.containerId;
|
|
114
|
+
}
|
|
44
115
|
get titleClass() {
|
|
45
116
|
return this.field.titleClass;
|
|
46
117
|
}
|
|
@@ -80,7 +151,7 @@ export class VanJsfField extends VanJSComponent {
|
|
|
80
151
|
class: this.class ? this.class : '',
|
|
81
152
|
value: this.iniVal,
|
|
82
153
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
83
|
-
}), p(() => this.error));
|
|
154
|
+
}), p({ class: this.errorClass }, () => this.error));
|
|
84
155
|
break;
|
|
85
156
|
case FieldType.textarea:
|
|
86
157
|
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
@@ -91,9 +162,17 @@ export class VanJsfField extends VanJSComponent {
|
|
|
91
162
|
rows: this.field.rows,
|
|
92
163
|
cols: this.field.columns,
|
|
93
164
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
94
|
-
}));
|
|
165
|
+
}), p({ class: this.errorClass }, () => this.error));
|
|
166
|
+
break;
|
|
167
|
+
case FieldType.code:
|
|
168
|
+
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
169
|
+
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description));
|
|
170
|
+
new EditorView({
|
|
171
|
+
doc: new String(this.iniVal).toString(),
|
|
172
|
+
parent: el,
|
|
173
|
+
extensions: this.codemirrorExtension
|
|
174
|
+
});
|
|
95
175
|
break;
|
|
96
|
-
//TODO: Add select component
|
|
97
176
|
case FieldType.select:
|
|
98
177
|
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
99
178
|
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), select({
|
|
@@ -101,7 +180,7 @@ export class VanJsfField extends VanJSComponent {
|
|
|
101
180
|
name: this.name,
|
|
102
181
|
class: this.class ? this.class : null,
|
|
103
182
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
104
|
-
}, this.options?.map((opt) => option({ class: this.class ? this.class : null, value: opt.value }, opt.label, opt.description))));
|
|
183
|
+
}, this.options?.map((opt) => option({ class: this.class ? this.class : null, value: opt.value }, opt.label, opt.description))), p({ class: this.errorClass }, () => this.error));
|
|
105
184
|
break;
|
|
106
185
|
case FieldType.date:
|
|
107
186
|
const calendarInput = input({
|
|
@@ -113,10 +192,11 @@ export class VanJsfField extends VanJSComponent {
|
|
|
113
192
|
});
|
|
114
193
|
el =
|
|
115
194
|
div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
116
|
-
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), calendarInput, link({ rel: "stylesheet", type: "text/css", href: "https://cdn.jsdelivr.net/npm/pikaday/css/pikaday.css" }));
|
|
195
|
+
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), calendarInput, p({ class: this.errorClass }, () => this.error), link({ rel: "stylesheet", type: "text/css", href: "https://cdn.jsdelivr.net/npm/pikaday/css/pikaday.css" }));
|
|
117
196
|
new pikaday({
|
|
118
197
|
field: calendarInput,
|
|
119
198
|
format: 'YYYY/MM/DD',
|
|
199
|
+
container: el,
|
|
120
200
|
firstDay: 1,
|
|
121
201
|
toString(date) {
|
|
122
202
|
// you should do formatting based on the passed format,
|
|
@@ -144,7 +224,7 @@ export class VanJsfField extends VanJSComponent {
|
|
|
144
224
|
class: this.class ? this.class : null,
|
|
145
225
|
value: this.iniVal,
|
|
146
226
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
147
|
-
}));
|
|
227
|
+
}), p({ class: this.errorClass }, () => this.error));
|
|
148
228
|
break;
|
|
149
229
|
case FieldType.fieldset:
|
|
150
230
|
console.log(this.field);
|
|
@@ -159,7 +239,7 @@ export class VanJsfField extends VanJSComponent {
|
|
|
159
239
|
value: opt.value,
|
|
160
240
|
checked: this.iniVal === opt.value,
|
|
161
241
|
onchange: (e) => this.handleChange(this, e.target.value),
|
|
162
|
-
}), opt.label, opt.description))));
|
|
242
|
+
}), opt.label, opt.description), p({ class: this.errorClass }, () => this.error))));
|
|
163
243
|
break;
|
|
164
244
|
default:
|
|
165
245
|
el = div({ style: "border: 1px dashed gray; padding: 8px;" }, `Field "${this.name}" unsupported: The type "${this.inputType}" has no UI component built yet.`);
|
package/dist/VanJsfForm.js
CHANGED
|
@@ -18,7 +18,9 @@ class VanJsfForm {
|
|
|
18
18
|
this.config = config;
|
|
19
19
|
this.isValid = isValid || undefined;
|
|
20
20
|
// Working with parameters
|
|
21
|
+
const initialValues = { ...config?.initialValues };
|
|
21
22
|
this.headlessForm = createHeadlessForm(jsonSchema, config);
|
|
23
|
+
this.config.initialValues = initialValues;
|
|
22
24
|
// Read documentation about `getFieldsAndValuedFromJsf` method below
|
|
23
25
|
const { vanJsfFields, formValues } = this.getFieldsAndValuesFromJsf(this.headlessForm, this.config.initialValues);
|
|
24
26
|
this.formFields = vanJsfFields;
|
|
@@ -52,24 +54,30 @@ class VanJsfForm {
|
|
|
52
54
|
*/
|
|
53
55
|
getFieldsAndValuesFromJsf(headlessForm, initialValues) {
|
|
54
56
|
const fields = headlessForm.fields;
|
|
55
|
-
console.log(fields);
|
|
56
57
|
const formValues = {};
|
|
58
|
+
const values = { ...initialValues };
|
|
59
|
+
console.log(values);
|
|
57
60
|
const vanJsfFields = this.processFields(fields, initialValues, formValues);
|
|
58
61
|
return { vanJsfFields, formValues };
|
|
59
62
|
}
|
|
60
63
|
handleFieldChange(field, value) {
|
|
61
|
-
console.log(
|
|
64
|
+
console.log(value);
|
|
65
|
+
console.log(field.name);
|
|
62
66
|
this.formValues[field.name] = value;
|
|
63
67
|
const { formErrors } = this.headlessForm.handleValidation(this.formValues);
|
|
68
|
+
let extraError = false;
|
|
64
69
|
console.log("formErrors", formErrors);
|
|
65
70
|
this.formFields.forEach((f) => {
|
|
66
71
|
f.isVisible = f.field.isVisible;
|
|
67
72
|
f.error = formErrors?.[f.name] ?? "";
|
|
73
|
+
console.log(f.field.error);
|
|
74
|
+
if (f.field.error) {
|
|
75
|
+
extraError = true;
|
|
76
|
+
}
|
|
68
77
|
});
|
|
69
78
|
if (this.isValid) {
|
|
70
|
-
if (formErrors) {
|
|
71
|
-
|
|
72
|
-
this.isValid.val = false;
|
|
79
|
+
if (formErrors || extraError) {
|
|
80
|
+
this.isValid.val = false;
|
|
73
81
|
}
|
|
74
82
|
else {
|
|
75
83
|
this.isValid.val = true;
|
|
@@ -84,8 +92,6 @@ class VanJsfForm {
|
|
|
84
92
|
const initVal = initialValues[fieldPath] || field.default || "";
|
|
85
93
|
// Store the initial value in the form values map
|
|
86
94
|
formValues[fieldPath] = initVal;
|
|
87
|
-
console.log(formValues);
|
|
88
|
-
console.log(initialValues);
|
|
89
95
|
// Check if the field has nested fields and process them recursively
|
|
90
96
|
if (field.fields && field.fields.length > 0) {
|
|
91
97
|
field.fields = this.processFields(field.fields, initialValues, formValues, fieldPath);
|