foorm 0.0.1-alpha.1
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 +1 -0
- package/dist/index.cjs +128 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.mjs +125 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @foormjs/foorm
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ftring = require('@prostojs/ftring');
|
|
4
|
+
|
|
5
|
+
class Foorm {
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.type = 'foorm';
|
|
8
|
+
this.title = (opts === null || opts === void 0 ? void 0 : opts.title) || '';
|
|
9
|
+
this.defaultAction = (opts === null || opts === void 0 ? void 0 : opts.defaultAction) || '';
|
|
10
|
+
this.entries = (opts === null || opts === void 0 ? void 0 : opts.entries) || [];
|
|
11
|
+
}
|
|
12
|
+
getField(name) {
|
|
13
|
+
return this.entries.find(e => e.field === name);
|
|
14
|
+
}
|
|
15
|
+
setValue(field, value) {
|
|
16
|
+
const entry = this.entries.find(e => e.field === field);
|
|
17
|
+
if (entry)
|
|
18
|
+
entry.value = value;
|
|
19
|
+
}
|
|
20
|
+
getEntries() {
|
|
21
|
+
return this.entries;
|
|
22
|
+
}
|
|
23
|
+
setEntries(entries) {
|
|
24
|
+
this.entries = entries;
|
|
25
|
+
}
|
|
26
|
+
getFormValidator() {
|
|
27
|
+
if (!this.fns)
|
|
28
|
+
this.fns = new ftring.FtringsPool();
|
|
29
|
+
const fields = {};
|
|
30
|
+
for (const entry of this.entries) {
|
|
31
|
+
if (entry.validators && entry.field) {
|
|
32
|
+
fields[entry.field] = {
|
|
33
|
+
entry,
|
|
34
|
+
validators: entry.validators.map(v => this.fns.getFn(v)),
|
|
35
|
+
};
|
|
36
|
+
if (!entry.optional)
|
|
37
|
+
fields[entry.field].validators.unshift(this.fns.getFn('!!v || "Required"'));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return (inputs) => {
|
|
41
|
+
let passed = true;
|
|
42
|
+
const errors = {};
|
|
43
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
44
|
+
const result = validate({
|
|
45
|
+
v: inputs[key],
|
|
46
|
+
validators: value.validators,
|
|
47
|
+
entry: value.entry,
|
|
48
|
+
inputs,
|
|
49
|
+
});
|
|
50
|
+
if (!result.passed) {
|
|
51
|
+
passed = false;
|
|
52
|
+
if (!errors[key]) {
|
|
53
|
+
errors[key] = result.error || 'Wrong value';
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
passed,
|
|
59
|
+
errors,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
genUIEntries() {
|
|
64
|
+
if (!this.fns)
|
|
65
|
+
this.fns = new ftring.FtringsPool();
|
|
66
|
+
let autoFocusAttached = false;
|
|
67
|
+
const uiEntries = [];
|
|
68
|
+
for (const entry of this.entries) {
|
|
69
|
+
const uiEntry = Object.assign({}, entry);
|
|
70
|
+
// apply autofocus to the first focusable element of this form
|
|
71
|
+
if (!autoFocusAttached && entry.focusable) {
|
|
72
|
+
autoFocusAttached = true;
|
|
73
|
+
uiEntry.autoFocus = true;
|
|
74
|
+
}
|
|
75
|
+
// create dynamic validators
|
|
76
|
+
if (entry.validators) {
|
|
77
|
+
uiEntry.validators = entry.validators.map(v => this.fns.getFn(v));
|
|
78
|
+
if (!entry.optional)
|
|
79
|
+
uiEntry.validators.unshift(this.fns.getFn('!!v || "Required"'));
|
|
80
|
+
}
|
|
81
|
+
// create dynamic classes
|
|
82
|
+
if (entry.classes) {
|
|
83
|
+
if (typeof entry.classes === 'string') {
|
|
84
|
+
uiEntry.classes = this.fns.getFn(entry.classes);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
uiEntry.classes = {};
|
|
88
|
+
for (const [key, value] of Object.entries(entry.classes)) {
|
|
89
|
+
uiEntry.classes[key] = this.fns.getFn(value);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// create dynamic disabled
|
|
94
|
+
if (entry.disabled) {
|
|
95
|
+
uiEntry.disabled = this.fns.getFn(entry.disabled);
|
|
96
|
+
}
|
|
97
|
+
uiEntries.push(uiEntry);
|
|
98
|
+
// assign next focus on enter
|
|
99
|
+
let next = undefined;
|
|
100
|
+
for (let i = uiEntries.length - 1; i >= 0; i--) {
|
|
101
|
+
const uiEntry = uiEntries[i];
|
|
102
|
+
uiEntry.id = [uiEntry.field, uiEntry.action || '', uiEntry.type, i].join('-');
|
|
103
|
+
if (uiEntry.nextFocusable) {
|
|
104
|
+
if (next) {
|
|
105
|
+
uiEntry.next = next;
|
|
106
|
+
}
|
|
107
|
+
next = uiEntry;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return uiEntries;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
function validate(opts) {
|
|
115
|
+
for (const validator of (opts.validators || [])) {
|
|
116
|
+
const result = validator({ v: opts.v || '', inputs: opts.inputs, entry: opts.entry });
|
|
117
|
+
if (result !== true) {
|
|
118
|
+
return {
|
|
119
|
+
passed: false,
|
|
120
|
+
error: (result || 'Wrong value'),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return { passed: true };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
exports.Foorm = Foorm;
|
|
128
|
+
exports.validate = validate;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export declare class Foorm {
|
|
2
|
+
title: string;
|
|
3
|
+
defaultAction: string;
|
|
4
|
+
protected type: string;
|
|
5
|
+
private fns;
|
|
6
|
+
protected entries: TFoormEntry[];
|
|
7
|
+
constructor(opts?: {
|
|
8
|
+
title: string;
|
|
9
|
+
entries?: TFoormEntry[];
|
|
10
|
+
defaultAction?: string;
|
|
11
|
+
});
|
|
12
|
+
getField(name: string): TFoormEntry | undefined;
|
|
13
|
+
setValue(field: string, value: unknown): void;
|
|
14
|
+
getEntries(): TFoormEntry[];
|
|
15
|
+
setEntries(entries: TFoormEntry[]): void;
|
|
16
|
+
getFormValidator(): ((inputs: Record<string, unknown>) => {
|
|
17
|
+
passed: boolean;
|
|
18
|
+
errors: Record<string, string>;
|
|
19
|
+
});
|
|
20
|
+
genUIEntries(): TFoormEntryUI[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export declare type TDynamicFn<R = boolean | string> = ((ctx: TDynamicFnCtx) => R);
|
|
24
|
+
|
|
25
|
+
export declare type TDynamicFnCtx = {
|
|
26
|
+
v: unknown;
|
|
27
|
+
inputs?: Record<string, unknown>;
|
|
28
|
+
entry?: TFoormEntry | TFoormEntryUI;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export declare type TFeComponentName = 'fe-input' | 'fe-button' | 'fe-checkbox' | 'fe-pin' | 'fe-select';
|
|
32
|
+
|
|
33
|
+
export declare type TFoormEntry<FN = string> = {
|
|
34
|
+
component: string;
|
|
35
|
+
label?: string;
|
|
36
|
+
type?: string;
|
|
37
|
+
validators?: FN[];
|
|
38
|
+
disabled?: FN;
|
|
39
|
+
classes?: FN | Record<string, FN>;
|
|
40
|
+
optional?: boolean;
|
|
41
|
+
field?: string;
|
|
42
|
+
value?: unknown;
|
|
43
|
+
focusable?: boolean;
|
|
44
|
+
nextFocusable?: boolean;
|
|
45
|
+
action?: string;
|
|
46
|
+
validateOnBlur?: boolean;
|
|
47
|
+
validateBeforeAction?: boolean;
|
|
48
|
+
bind?: Record<string, unknown>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export declare type TFoormEntryUI = TFoormEntry<TDynamicFn> & {
|
|
52
|
+
id: string;
|
|
53
|
+
autoFocus?: boolean;
|
|
54
|
+
next?: TFoormEntryUI;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export declare function validate(opts: {
|
|
58
|
+
v: unknown;
|
|
59
|
+
inputs?: Record<string, unknown>;
|
|
60
|
+
entry?: TFoormEntry;
|
|
61
|
+
validators: TDynamicFn[];
|
|
62
|
+
}): {
|
|
63
|
+
passed: boolean;
|
|
64
|
+
error: string;
|
|
65
|
+
} | {
|
|
66
|
+
passed: boolean;
|
|
67
|
+
error?: undefined;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { }
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { FtringsPool } from '@prostojs/ftring';
|
|
2
|
+
|
|
3
|
+
class Foorm {
|
|
4
|
+
constructor(opts) {
|
|
5
|
+
this.type = 'foorm';
|
|
6
|
+
this.title = (opts === null || opts === void 0 ? void 0 : opts.title) || '';
|
|
7
|
+
this.defaultAction = (opts === null || opts === void 0 ? void 0 : opts.defaultAction) || '';
|
|
8
|
+
this.entries = (opts === null || opts === void 0 ? void 0 : opts.entries) || [];
|
|
9
|
+
}
|
|
10
|
+
getField(name) {
|
|
11
|
+
return this.entries.find(e => e.field === name);
|
|
12
|
+
}
|
|
13
|
+
setValue(field, value) {
|
|
14
|
+
const entry = this.entries.find(e => e.field === field);
|
|
15
|
+
if (entry)
|
|
16
|
+
entry.value = value;
|
|
17
|
+
}
|
|
18
|
+
getEntries() {
|
|
19
|
+
return this.entries;
|
|
20
|
+
}
|
|
21
|
+
setEntries(entries) {
|
|
22
|
+
this.entries = entries;
|
|
23
|
+
}
|
|
24
|
+
getFormValidator() {
|
|
25
|
+
if (!this.fns)
|
|
26
|
+
this.fns = new FtringsPool();
|
|
27
|
+
const fields = {};
|
|
28
|
+
for (const entry of this.entries) {
|
|
29
|
+
if (entry.validators && entry.field) {
|
|
30
|
+
fields[entry.field] = {
|
|
31
|
+
entry,
|
|
32
|
+
validators: entry.validators.map(v => this.fns.getFn(v)),
|
|
33
|
+
};
|
|
34
|
+
if (!entry.optional)
|
|
35
|
+
fields[entry.field].validators.unshift(this.fns.getFn('!!v || "Required"'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return (inputs) => {
|
|
39
|
+
let passed = true;
|
|
40
|
+
const errors = {};
|
|
41
|
+
for (const [key, value] of Object.entries(fields)) {
|
|
42
|
+
const result = validate({
|
|
43
|
+
v: inputs[key],
|
|
44
|
+
validators: value.validators,
|
|
45
|
+
entry: value.entry,
|
|
46
|
+
inputs,
|
|
47
|
+
});
|
|
48
|
+
if (!result.passed) {
|
|
49
|
+
passed = false;
|
|
50
|
+
if (!errors[key]) {
|
|
51
|
+
errors[key] = result.error || 'Wrong value';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
passed,
|
|
57
|
+
errors,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
genUIEntries() {
|
|
62
|
+
if (!this.fns)
|
|
63
|
+
this.fns = new FtringsPool();
|
|
64
|
+
let autoFocusAttached = false;
|
|
65
|
+
const uiEntries = [];
|
|
66
|
+
for (const entry of this.entries) {
|
|
67
|
+
const uiEntry = Object.assign({}, entry);
|
|
68
|
+
// apply autofocus to the first focusable element of this form
|
|
69
|
+
if (!autoFocusAttached && entry.focusable) {
|
|
70
|
+
autoFocusAttached = true;
|
|
71
|
+
uiEntry.autoFocus = true;
|
|
72
|
+
}
|
|
73
|
+
// create dynamic validators
|
|
74
|
+
if (entry.validators) {
|
|
75
|
+
uiEntry.validators = entry.validators.map(v => this.fns.getFn(v));
|
|
76
|
+
if (!entry.optional)
|
|
77
|
+
uiEntry.validators.unshift(this.fns.getFn('!!v || "Required"'));
|
|
78
|
+
}
|
|
79
|
+
// create dynamic classes
|
|
80
|
+
if (entry.classes) {
|
|
81
|
+
if (typeof entry.classes === 'string') {
|
|
82
|
+
uiEntry.classes = this.fns.getFn(entry.classes);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
uiEntry.classes = {};
|
|
86
|
+
for (const [key, value] of Object.entries(entry.classes)) {
|
|
87
|
+
uiEntry.classes[key] = this.fns.getFn(value);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// create dynamic disabled
|
|
92
|
+
if (entry.disabled) {
|
|
93
|
+
uiEntry.disabled = this.fns.getFn(entry.disabled);
|
|
94
|
+
}
|
|
95
|
+
uiEntries.push(uiEntry);
|
|
96
|
+
// assign next focus on enter
|
|
97
|
+
let next = undefined;
|
|
98
|
+
for (let i = uiEntries.length - 1; i >= 0; i--) {
|
|
99
|
+
const uiEntry = uiEntries[i];
|
|
100
|
+
uiEntry.id = [uiEntry.field, uiEntry.action || '', uiEntry.type, i].join('-');
|
|
101
|
+
if (uiEntry.nextFocusable) {
|
|
102
|
+
if (next) {
|
|
103
|
+
uiEntry.next = next;
|
|
104
|
+
}
|
|
105
|
+
next = uiEntry;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return uiEntries;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function validate(opts) {
|
|
113
|
+
for (const validator of (opts.validators || [])) {
|
|
114
|
+
const result = validator({ v: opts.v || '', inputs: opts.inputs, entry: opts.entry });
|
|
115
|
+
if (result !== true) {
|
|
116
|
+
return {
|
|
117
|
+
passed: false,
|
|
118
|
+
error: (result || 'Wrong value'),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { passed: true };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { Foorm, validate };
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "foorm",
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"description": "foorm",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/foormjs/foormjs.git",
|
|
22
|
+
"directory": "packages/foorm"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"foorm",
|
|
26
|
+
"foormjs",
|
|
27
|
+
"forms",
|
|
28
|
+
"validations"
|
|
29
|
+
],
|
|
30
|
+
"author": "Artem Maltsev",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/foormjs/foormjs/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/foormjs/foormjs/tree/main/packages/foorm#readme",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@prostojs/ftring": "^0.0.3"
|
|
38
|
+
}
|
|
39
|
+
}
|