vanjs-jsf 0.0.7 → 0.0.10
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/LICENSE +201 -201
- package/README.md +92 -92
- package/dist/VanJsfField.d.ts +5 -0
- package/dist/VanJsfField.js +69 -8
- package/dist/VanJsfForm.js +25 -14
- package/dist/index.js.map +4 -4
- package/package.json +44 -44
package/dist/VanJsfField.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import van from "vanjs-core";
|
|
2
2
|
import { VanJSComponent } from "./VanJSComponent";
|
|
3
|
-
|
|
3
|
+
import pikaday from "pikaday";
|
|
4
|
+
const { div, p, input, label, textarea, legend, link, fieldset, span } = van.tags;
|
|
4
5
|
var FieldType;
|
|
5
6
|
(function (FieldType) {
|
|
6
7
|
FieldType["text"] = "text";
|
|
7
8
|
FieldType["number"] = "number";
|
|
8
9
|
FieldType["textarea"] = "textarea";
|
|
9
10
|
FieldType["radio"] = "radio";
|
|
11
|
+
FieldType["date"] = "date";
|
|
12
|
+
FieldType["fieldset"] = "fieldset";
|
|
10
13
|
})(FieldType || (FieldType = {}));
|
|
11
14
|
export class VanJsfField extends VanJSComponent {
|
|
12
15
|
name;
|
|
@@ -31,6 +34,18 @@ export class VanJsfField extends VanJSComponent {
|
|
|
31
34
|
get label() {
|
|
32
35
|
return this.field.label;
|
|
33
36
|
}
|
|
37
|
+
get class() {
|
|
38
|
+
return this.field.class;
|
|
39
|
+
}
|
|
40
|
+
get containerClass() {
|
|
41
|
+
return this.field.containerClass;
|
|
42
|
+
}
|
|
43
|
+
get titleClass() {
|
|
44
|
+
return this.field.titleClass;
|
|
45
|
+
}
|
|
46
|
+
get descriptionClass() {
|
|
47
|
+
return this.field.descriptionClass;
|
|
48
|
+
}
|
|
34
49
|
get description() {
|
|
35
50
|
return this.field.description;
|
|
36
51
|
}
|
|
@@ -53,40 +68,83 @@ export class VanJsfField extends VanJSComponent {
|
|
|
53
68
|
let el;
|
|
54
69
|
const props = {
|
|
55
70
|
style: () => (this.isVisible ? "display: block" : "display: none"),
|
|
71
|
+
class: this.containerClass ? this.containerClass : ''
|
|
56
72
|
};
|
|
57
73
|
switch (this.inputType) {
|
|
58
74
|
case FieldType.text:
|
|
59
|
-
el = div(props, label({ for: this.name }, this.label), this.description &&
|
|
60
|
-
div({ id: `${this.name}-description
|
|
75
|
+
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
76
|
+
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), input({
|
|
61
77
|
id: this.name,
|
|
62
78
|
type: "text",
|
|
79
|
+
class: this.class ? this.class : '',
|
|
63
80
|
value: this.iniVal,
|
|
64
81
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
65
82
|
}), p(() => this.error));
|
|
66
83
|
break;
|
|
67
84
|
case FieldType.textarea:
|
|
68
|
-
el = div(props, label({ for: this.name }, this.label), this.description &&
|
|
69
|
-
div({ id: `${this.name}-description
|
|
85
|
+
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
86
|
+
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), textarea({
|
|
70
87
|
id: this.name,
|
|
71
88
|
name: this.name,
|
|
89
|
+
class: this.class ? this.class : null,
|
|
72
90
|
rows: this.field.rows,
|
|
73
91
|
cols: this.field.columns,
|
|
74
92
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
75
93
|
}));
|
|
76
94
|
break;
|
|
95
|
+
case FieldType.date:
|
|
96
|
+
const calendarInput = input({
|
|
97
|
+
id: this.name,
|
|
98
|
+
type: "text",
|
|
99
|
+
class: this.class ? this.class : null,
|
|
100
|
+
value: this.iniVal,
|
|
101
|
+
onchange: (e) => this.handleChange(this, e.target.value),
|
|
102
|
+
});
|
|
103
|
+
el =
|
|
104
|
+
div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
105
|
+
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" }));
|
|
106
|
+
new pikaday({
|
|
107
|
+
field: calendarInput,
|
|
108
|
+
format: 'YYYY/MM/DD',
|
|
109
|
+
firstDay: 1,
|
|
110
|
+
toString(date) {
|
|
111
|
+
// you should do formatting based on the passed format,
|
|
112
|
+
// but we will just return 'D/M/YYYY' for simplicity
|
|
113
|
+
const day = date.getDate();
|
|
114
|
+
const month = date.getMonth() + 1;
|
|
115
|
+
const year = date.getFullYear();
|
|
116
|
+
return `${year}-${("0" + month).slice(-2)}-${("0" + day).slice(-2)}`;
|
|
117
|
+
},
|
|
118
|
+
parse(dateString, format) {
|
|
119
|
+
// dateString is the result of `toString` method
|
|
120
|
+
const parts = dateString.split('/');
|
|
121
|
+
const day = parseInt(parts[0], 10);
|
|
122
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
123
|
+
const year = parseInt(parts[2], 10);
|
|
124
|
+
return new Date(year, month, day);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
break;
|
|
77
128
|
case FieldType.number:
|
|
78
|
-
el = div(props, label({ for: this.name }, this.label), this.description &&
|
|
79
|
-
div({ id: `${this.name}-description
|
|
129
|
+
el = div(props, label({ for: this.name, style: "margin-right: 5px;", class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
130
|
+
div({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), input({
|
|
80
131
|
id: this.name,
|
|
81
132
|
type: "number",
|
|
133
|
+
class: this.class ? this.class : null,
|
|
82
134
|
value: this.iniVal,
|
|
83
135
|
oninput: (e) => this.handleChange(this, e.target.value),
|
|
84
136
|
}));
|
|
85
137
|
break;
|
|
138
|
+
case FieldType.fieldset:
|
|
139
|
+
console.log(this.field);
|
|
140
|
+
el = div(props, fieldset(legend({ class: this.titleClass ? this.titleClass : '' }, this.label), this.description &&
|
|
141
|
+
span({ id: `${this.name}-description`, class: this.descriptionClass ? this.descriptionClass : '' }, this.description), this.isVanJsfFieldArray(this.field.fields) ? this.field.fields.map((field) => field.render()) : null));
|
|
142
|
+
break;
|
|
86
143
|
case FieldType.radio:
|
|
87
|
-
el = div(legend(this.label), this.description && div(this.description), div(this.options?.map((opt) => label(input({
|
|
144
|
+
el = div(legend({ class: this.titleClass ? this.titleClass : '' }, this.label), this.description && div(this.description), div(this.options?.map((opt) => label(input({
|
|
88
145
|
type: "radio",
|
|
89
146
|
name: this.name,
|
|
147
|
+
class: this.class ? this.class : null,
|
|
90
148
|
value: opt.value,
|
|
91
149
|
checked: this.iniVal === opt.value,
|
|
92
150
|
onchange: (e) => this.handleChange(this, e.target.value),
|
|
@@ -97,4 +155,7 @@ export class VanJsfField extends VanJSComponent {
|
|
|
97
155
|
}
|
|
98
156
|
return el;
|
|
99
157
|
}
|
|
158
|
+
isVanJsfFieldArray(fields) {
|
|
159
|
+
return Array.isArray(fields) && fields.every(field => field instanceof VanJsfField);
|
|
160
|
+
}
|
|
100
161
|
}
|
package/dist/VanJsfForm.js
CHANGED
|
@@ -50,21 +50,9 @@ class VanJsfForm {
|
|
|
50
50
|
*/
|
|
51
51
|
getFieldsAndValuesFromJsf(headlessForm, initialValues) {
|
|
52
52
|
const fields = headlessForm.fields;
|
|
53
|
+
console.log(fields);
|
|
53
54
|
const formValues = {};
|
|
54
|
-
const vanJsfFields =
|
|
55
|
-
// TODO needs to support field sets recursively
|
|
56
|
-
// Extract the field name as a string
|
|
57
|
-
const fieldName = field.name;
|
|
58
|
-
// Determine the initial value for the field
|
|
59
|
-
// **Important**!: `field.default` is not properly documented in
|
|
60
|
-
// https://json-schema-form.vercel.app/?path=/docs/api-reference-api--docs
|
|
61
|
-
// They say the property for default values is `defaultValue` but it's not
|
|
62
|
-
const initVal = initialValues[fieldName] || field.default || "";
|
|
63
|
-
// Store the initial value in the form values map
|
|
64
|
-
formValues[fieldName] = initVal;
|
|
65
|
-
// Create and return a new VanJsfField instance for this field
|
|
66
|
-
return new VanJsfField(field, initVal, this.handleFieldChange);
|
|
67
|
-
});
|
|
55
|
+
const vanJsfFields = this.processFields(fields, initialValues, formValues);
|
|
68
56
|
return { vanJsfFields, formValues };
|
|
69
57
|
}
|
|
70
58
|
handleFieldChange(field, value) {
|
|
@@ -77,6 +65,24 @@ class VanJsfForm {
|
|
|
77
65
|
f.error = formErrors?.[f.name] ?? "";
|
|
78
66
|
});
|
|
79
67
|
}
|
|
68
|
+
processFields(fields, initialValues, formValues, parentPath = "") {
|
|
69
|
+
return fields.map((field) => {
|
|
70
|
+
// Construct the full path for the field
|
|
71
|
+
const fieldPath = parentPath ? `${parentPath}.${field.name}` : field.name;
|
|
72
|
+
// Determine the initial value for the field
|
|
73
|
+
const initVal = initialValues[fieldPath] || field.default || "";
|
|
74
|
+
// Store the initial value in the form values map
|
|
75
|
+
formValues[fieldPath] = initVal;
|
|
76
|
+
console.log(formValues);
|
|
77
|
+
console.log(initialValues);
|
|
78
|
+
// Check if the field has nested fields and process them recursively
|
|
79
|
+
if (field.fields && field.fields.length > 0) {
|
|
80
|
+
field.fields = this.processFields(field.fields, initialValues, formValues, fieldPath);
|
|
81
|
+
}
|
|
82
|
+
// Create and return a new VanJsfField instance for this field
|
|
83
|
+
return new VanJsfField(field, initVal, this.handleFieldChange);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
80
86
|
}
|
|
81
87
|
export function jsform(attributes, ...children) {
|
|
82
88
|
if (!attributes.schema) {
|
|
@@ -93,6 +99,7 @@ export function jsform(attributes, ...children) {
|
|
|
93
99
|
config.formValues = {};
|
|
94
100
|
}
|
|
95
101
|
const vanJsfForm = new VanJsfForm(attributes.schema, config);
|
|
102
|
+
console.log(vanJsfForm);
|
|
96
103
|
const fields = vanJsfForm.formFields.map((field) => field.render());
|
|
97
104
|
const childrenWithFields = [...fields, ...children]; // Concatenate fields with other children
|
|
98
105
|
const originalOnSubmit = attributes.onsubmit;
|
|
@@ -101,6 +108,10 @@ export function jsform(attributes, ...children) {
|
|
|
101
108
|
config.formValues = vanJsfForm.formValues;
|
|
102
109
|
originalOnSubmit && originalOnSubmit(e);
|
|
103
110
|
};
|
|
111
|
+
const handleChange = (e) => {
|
|
112
|
+
config.formValues = vanJsfForm.formValues;
|
|
113
|
+
};
|
|
104
114
|
attributes.onsubmit = handleSubmit;
|
|
115
|
+
attributes.onchange = handleChange;
|
|
105
116
|
return form(attributes, ...childrenWithFields);
|
|
106
117
|
}
|