mayoiga 0.1.2 → 0.1.3
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/component.test.js +33 -3
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -1
- package/dist/index.test.js +5 -2
- package/package.json +5 -4
- package/src/component.test.tsx +69 -14
- package/src/component.tsx +8 -4
- package/src/index.test.tsx +19 -17
- package/src/index.ts +11 -3
package/dist/component.test.js
CHANGED
|
@@ -4,11 +4,14 @@ import React from 'react';
|
|
|
4
4
|
import { test, expect } from 'vitest';
|
|
5
5
|
import * as zod from 'zod';
|
|
6
6
|
import { Field, Slicer } from './component';
|
|
7
|
-
import { createFormHook
|
|
7
|
+
import { createFormHook } from './index';
|
|
8
8
|
const testSchema = zod.object({
|
|
9
9
|
name: zod.string(),
|
|
10
10
|
description: zod.string(),
|
|
11
|
-
age: zod
|
|
11
|
+
age: zod
|
|
12
|
+
.string()
|
|
13
|
+
.transform((val) => Number(val))
|
|
14
|
+
.refine((val) => (Number.isNaN(val) ? 0 : val)),
|
|
12
15
|
marked: zod.boolean(),
|
|
13
16
|
});
|
|
14
17
|
const createTestHook = () => createFormHook({ name: '', description: '', age: '', marked: false }, testSchema);
|
|
@@ -36,7 +39,7 @@ test('Slice component works fine in basic usage.', async () => {
|
|
|
36
39
|
const TestFormHook = createTestHook();
|
|
37
40
|
const Top = () => {
|
|
38
41
|
return (React.createElement("div", null,
|
|
39
|
-
React.createElement(Slicer, { controller: TestFormHook.controller, selector: s => [s.value.age] }, (tool, age) => React.createElement("input", { "data-testid": "age-input", name: "age", value: age, onChange: e => tool.handleChange('age', e.target.value) }))));
|
|
42
|
+
React.createElement(Slicer, { controller: TestFormHook.controller, selector: (s) => [s.value.age] }, (tool, age) => (React.createElement("input", { "data-testid": "age-input", name: "age", value: age, onChange: (e) => tool.handleChange('age', e.target.value) })))));
|
|
40
43
|
};
|
|
41
44
|
render(React.createElement(Top, null));
|
|
42
45
|
const INPUT_AGE = '42';
|
|
@@ -51,3 +54,30 @@ test('Slice component works fine in basic usage.', async () => {
|
|
|
51
54
|
});
|
|
52
55
|
});
|
|
53
56
|
});
|
|
57
|
+
test('A user able to create a reusable component', async () => {
|
|
58
|
+
const TestFormHook = createTestHook();
|
|
59
|
+
function NarrowTypedExpected(props) {
|
|
60
|
+
return (React.createElement(Field, { controller: props.controller, name: "age" }, (tool) => React.createElement("input", { "data-testid": "age-input", ...tool })));
|
|
61
|
+
}
|
|
62
|
+
function ErrorDisplayer(props) {
|
|
63
|
+
const { controller } = props;
|
|
64
|
+
return (React.createElement(Slicer, { controller: controller, selector: (s) => [s.value.age] }, (tool, age) => (React.createElement("button", { onClick: (e) => {
|
|
65
|
+
controller.actions.pushFormErrors((_state) => ({ age: age === '42' ? 'yes!!!' : 'noooo' }));
|
|
66
|
+
} }))));
|
|
67
|
+
}
|
|
68
|
+
render(React.createElement("div", null,
|
|
69
|
+
React.createElement(NarrowTypedExpected, { controller: TestFormHook.controller }),
|
|
70
|
+
React.createElement(ErrorDisplayer, { controller: TestFormHook.controller })));
|
|
71
|
+
const INPUT_AGE = '42';
|
|
72
|
+
// calling `userEvent` in here will cause race condition...
|
|
73
|
+
await userEvent.type(screen.getByTestId('age-input'), INPUT_AGE);
|
|
74
|
+
await userEvent.click(screen.getByRole('button'));
|
|
75
|
+
await waitFor(() => {
|
|
76
|
+
const ageInput = screen.getByTestId('age-input');
|
|
77
|
+
expect(ageInput.value).toBe(INPUT_AGE);
|
|
78
|
+
TestFormHook.api.actions.peek((s) => {
|
|
79
|
+
expect(s.value.age).toBe(INPUT_AGE);
|
|
80
|
+
expect(s.errors.age).toBe('yes!!!');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +44,8 @@ declare type FormControllerBehavior<StateBeforeValidation> = {
|
|
|
44
44
|
/**
|
|
45
45
|
* You can handle server side or other external error via this action.
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
pushFormErrors: (validator: (state: StateBeforeValidation) => Partial<FormErrors<StateBeforeValidation>>) => (prev: FullFormState<StateBeforeValidation>) => FullFormState<StateBeforeValidation>;
|
|
48
|
+
reduceFormErrors: (reducer: (prev: FormErrors<StateBeforeValidation>) => FormErrors<StateBeforeValidation>) => (prev: FullFormState<StateBeforeValidation>) => FullFormState<StateBeforeValidation>;
|
|
48
49
|
/**
|
|
49
50
|
*/
|
|
50
51
|
handleChange: HandleChangeAction<StateBeforeValidation, (prev: FullFormState<StateBeforeValidation>) => FullFormState<StateBeforeValidation>>;
|
|
@@ -54,9 +55,9 @@ declare type FormControllerBehavior<StateBeforeValidation> = {
|
|
|
54
55
|
declare type ActionsCanBePublic<State extends StateRestriction> = {
|
|
55
56
|
reset: VoidFunction;
|
|
56
57
|
initializeForm: (initial: Partial<State>) => void;
|
|
58
|
+
pushFormErrors: (validator: (state: State) => Partial<FormErrors<State>>) => void;
|
|
57
59
|
handleChange: HandleChangeAction<State>;
|
|
58
60
|
handleBulkChange: (setter: (prev: State) => Partial<State>) => void;
|
|
59
|
-
handleError: (reducer: (prev: FormErrors<State>) => FormErrors<State>) => void;
|
|
60
61
|
};
|
|
61
62
|
/**
|
|
62
63
|
* Restricted type interface of the form store
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,11 @@ function createFormStore(initialState, schema) {
|
|
|
51
51
|
}, {});
|
|
52
52
|
return { ...prev, isDirty: true, isValid: false, errors: newErrors };
|
|
53
53
|
},
|
|
54
|
-
|
|
54
|
+
pushFormErrors: (validator) => (prev) => {
|
|
55
|
+
const pushedErrors = validator(prev.value);
|
|
56
|
+
return { ...prev, errors: { ...prev.errors, ...pushedErrors } };
|
|
57
|
+
},
|
|
58
|
+
reduceFormErrors: (reducer) => (prev) => {
|
|
55
59
|
return { ...prev, errors: reducer(prev.errors) };
|
|
56
60
|
},
|
|
57
61
|
handleChange: (name, value) => (prev) => {
|
package/dist/index.test.js
CHANGED
|
@@ -7,13 +7,16 @@ import { createFormHook, useFormSlice } from './index';
|
|
|
7
7
|
const testSchema = zod.object({
|
|
8
8
|
name: zod.string(),
|
|
9
9
|
description: zod.string(),
|
|
10
|
-
age: zod
|
|
10
|
+
age: zod
|
|
11
|
+
.string()
|
|
12
|
+
.transform((val) => Number(val))
|
|
13
|
+
.refine((val) => (Number.isNaN(val) ? 0 : val)),
|
|
11
14
|
marked: zod.boolean(),
|
|
12
15
|
});
|
|
13
16
|
const createTestHook = () => createFormHook({ name: '', description: '', age: '', marked: false }, testSchema);
|
|
14
17
|
const AgeInputComponent = (props) => {
|
|
15
18
|
const { controller } = props;
|
|
16
|
-
const [[age, errorMessage], { handleChange }] = useFormSlice(controller, s => [s.value.age, s.errors.age]);
|
|
19
|
+
const [[age, errorMessage], { handleChange }] = useFormSlice(controller, (s) => [s.value.age, s.errors.age]);
|
|
17
20
|
return (React.createElement("div", null,
|
|
18
21
|
React.createElement("input", { "data-testid": "age-input", value: age, name: "age", onChange: (e) => {
|
|
19
22
|
handleChange('age', e.currentTarget.value);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mayoiga",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Type safe hook based form library for React",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"test": "vitest run",
|
|
16
16
|
"prebuild": "npm run clean",
|
|
17
17
|
"build": "tsc",
|
|
18
|
-
"check:
|
|
18
|
+
"check:type": "tsc --noEmit",
|
|
19
|
+
"check:style": "prettier --check 'src/**/*.{js,ts,jsx,tsx}'",
|
|
19
20
|
"check:lint": "eslint 'src/**/*.{ts,tsx}'",
|
|
20
|
-
"check-all": "npm run check:style && npm run check:lint && npm run build --noEmit && npm run test",
|
|
21
|
-
"fix-all": "npm run check:style --write && npm run check:lint --fix",
|
|
21
|
+
"check-all": "npm run check:type && npm run check:style && npm run check:lint && npm run build --noEmit && npm run test",
|
|
22
|
+
"fix-all": "npm run check:style -- --write && npm run check:lint -- --fix",
|
|
22
23
|
"prepublish": "npm run check-all && npm run build"
|
|
23
24
|
},
|
|
24
25
|
"repository": {
|
package/src/component.test.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import {render, screen, waitFor} from '@testing-library/react';
|
|
3
2
|
import userEvent from '@testing-library/user-event';
|
|
4
3
|
import React from 'react';
|
|
@@ -7,14 +6,19 @@ import {test, expect} from 'vitest';
|
|
|
7
6
|
|
|
8
7
|
import * as zod from 'zod';
|
|
9
8
|
|
|
10
|
-
import {
|
|
9
|
+
import {Field, Slicer} from './component';
|
|
10
|
+
|
|
11
|
+
import {createFormHook} from './index';
|
|
11
12
|
|
|
12
|
-
import {
|
|
13
|
+
import type {Controller} from './index';
|
|
13
14
|
|
|
14
15
|
const testSchema = zod.object({
|
|
15
16
|
name: zod.string(),
|
|
16
17
|
description: zod.string(),
|
|
17
|
-
age: zod
|
|
18
|
+
age: zod
|
|
19
|
+
.string()
|
|
20
|
+
.transform((val) => Number(val))
|
|
21
|
+
.refine((val) => (Number.isNaN(val) ? 0 : val)),
|
|
18
22
|
marked: zod.boolean(),
|
|
19
23
|
});
|
|
20
24
|
|
|
@@ -24,9 +28,9 @@ type FormStateBeforeValidation = {
|
|
|
24
28
|
description: string;
|
|
25
29
|
age: string;
|
|
26
30
|
marked: boolean;
|
|
27
|
-
}
|
|
31
|
+
};
|
|
28
32
|
|
|
29
|
-
const createTestHook =
|
|
33
|
+
const createTestHook = () => createFormHook({name: '', description: '', age: '', marked: false} as FormStateBeforeValidation, testSchema);
|
|
30
34
|
|
|
31
35
|
// afterEach(cleanup);
|
|
32
36
|
|
|
@@ -36,11 +40,11 @@ test('Field component works fine in basic usage.', async () => {
|
|
|
36
40
|
const Top = () => {
|
|
37
41
|
return (
|
|
38
42
|
<div>
|
|
39
|
-
<Field controller={TestFormHook.controller} name="age">
|
|
40
|
-
(tool) => <input data-testid="age-input" {...tool} />
|
|
41
|
-
|
|
43
|
+
<Field controller={TestFormHook.controller} name="age">
|
|
44
|
+
{(tool) => <input data-testid="age-input" {...tool} />}
|
|
45
|
+
</Field>
|
|
42
46
|
</div>
|
|
43
|
-
)
|
|
47
|
+
);
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
render(<Top />);
|
|
@@ -66,11 +70,13 @@ test('Slice component works fine in basic usage.', async () => {
|
|
|
66
70
|
const Top = () => {
|
|
67
71
|
return (
|
|
68
72
|
<div>
|
|
69
|
-
<Slicer controller={TestFormHook.controller} selector={s => [s.value.age] as const}>
|
|
70
|
-
(tool, age: string) =>
|
|
71
|
-
|
|
73
|
+
<Slicer controller={TestFormHook.controller} selector={(s) => [s.value.age] as const}>
|
|
74
|
+
{(tool, age: string) => (
|
|
75
|
+
<input data-testid="age-input" name="age" value={age} onChange={(e) => tool.handleChange('age' as const, e.target.value)} />
|
|
76
|
+
)}
|
|
77
|
+
</Slicer>
|
|
72
78
|
</div>
|
|
73
|
-
)
|
|
79
|
+
);
|
|
74
80
|
};
|
|
75
81
|
|
|
76
82
|
render(<Top />);
|
|
@@ -89,3 +95,52 @@ test('Slice component works fine in basic usage.', async () => {
|
|
|
89
95
|
});
|
|
90
96
|
});
|
|
91
97
|
});
|
|
98
|
+
|
|
99
|
+
test('A user able to create a reusable component', async () => {
|
|
100
|
+
const TestFormHook = createTestHook();
|
|
101
|
+
|
|
102
|
+
function NarrowTypedExpected(props: {controller: Controller<{age: string}>}) {
|
|
103
|
+
return (
|
|
104
|
+
<Field controller={props.controller} name="age">
|
|
105
|
+
{(tool) => <input data-testid="age-input" {...tool} />}
|
|
106
|
+
</Field>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function ErrorDisplayer(props: {controller: Controller<{age: string}>}) {
|
|
111
|
+
const {controller} = props;
|
|
112
|
+
return (
|
|
113
|
+
<Slicer controller={controller} selector={(s) => [s.value.age] as const}>
|
|
114
|
+
{(tool, age: string) => (
|
|
115
|
+
<button
|
|
116
|
+
onClick={(e) => {
|
|
117
|
+
controller.actions.pushFormErrors((_state) => ({age: age === '42' ? 'yes!!!' : 'noooo'}));
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
</Slicer>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
render(
|
|
126
|
+
<div>
|
|
127
|
+
<NarrowTypedExpected controller={TestFormHook.controller} />
|
|
128
|
+
<ErrorDisplayer controller={TestFormHook.controller} />
|
|
129
|
+
</div>,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const INPUT_AGE = '42';
|
|
133
|
+
|
|
134
|
+
// calling `userEvent` in here will cause race condition...
|
|
135
|
+
await userEvent.type(screen.getByTestId('age-input'), INPUT_AGE);
|
|
136
|
+
await userEvent.click(screen.getByRole('button'));
|
|
137
|
+
|
|
138
|
+
await waitFor(() => {
|
|
139
|
+
const ageInput: HTMLInputElement = screen.getByTestId('age-input');
|
|
140
|
+
expect(ageInput.value).toBe(INPUT_AGE);
|
|
141
|
+
TestFormHook.api.actions.peek((s) => {
|
|
142
|
+
expect(s.value.age).toBe(INPUT_AGE);
|
|
143
|
+
expect(s.errors.age).toBe('yes!!!');
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
package/src/component.tsx
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import type {SliceProps, FieldProps, StateRestriction, Controller
|
|
3
|
+
import type {SliceProps, FieldProps, StateRestriction, Controller} from './index';
|
|
4
4
|
|
|
5
5
|
type ControlledComponentProps<State, Props> = Props & {
|
|
6
6
|
controller: Controller<State>;
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
8
|
|
|
9
|
-
export function Slicer<State extends StateRestriction, R extends ReadonlyArray<unknown>>(
|
|
9
|
+
export function Slicer<State extends StateRestriction, R extends ReadonlyArray<unknown>>(
|
|
10
|
+
props: ControlledComponentProps<State, SliceProps<State, R>>,
|
|
11
|
+
) {
|
|
10
12
|
const {controller, ...restProps} = props;
|
|
11
13
|
const {Slicer: Delegate} = controller.components;
|
|
12
14
|
return <Delegate {...restProps} />;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
export function Field<State extends StateRestriction, Name extends keyof State>(
|
|
17
|
+
export function Field<State extends StateRestriction, Name extends keyof State>(
|
|
18
|
+
props: ControlledComponentProps<State, FieldProps<State, Name>>,
|
|
19
|
+
) {
|
|
16
20
|
const {controller, ...restProps} = props;
|
|
17
21
|
const {Field: Delegate} = controller.components;
|
|
18
22
|
return <Delegate {...restProps} />;
|
package/src/index.test.tsx
CHANGED
|
@@ -7,14 +7,16 @@ import {test, expect} from 'vitest';
|
|
|
7
7
|
import * as zod from 'zod';
|
|
8
8
|
|
|
9
9
|
import {createFormHook, useFormSlice} from './index';
|
|
10
|
-
|
|
11
|
-
import type {Controller} from './index';
|
|
12
10
|
|
|
11
|
+
import type {Controller} from './index';
|
|
13
12
|
|
|
14
13
|
const testSchema = zod.object({
|
|
15
14
|
name: zod.string(),
|
|
16
15
|
description: zod.string(),
|
|
17
|
-
age: zod
|
|
16
|
+
age: zod
|
|
17
|
+
.string()
|
|
18
|
+
.transform((val) => Number(val))
|
|
19
|
+
.refine((val) => (Number.isNaN(val) ? 0 : val)),
|
|
18
20
|
marked: zod.boolean(),
|
|
19
21
|
});
|
|
20
22
|
|
|
@@ -24,13 +26,13 @@ type FormStateBeforeValidation = {
|
|
|
24
26
|
description: string;
|
|
25
27
|
age: string;
|
|
26
28
|
marked: boolean;
|
|
27
|
-
}
|
|
29
|
+
};
|
|
28
30
|
|
|
29
|
-
const createTestHook =
|
|
31
|
+
const createTestHook = () => createFormHook({name: '', description: '', age: '', marked: false} as FormStateBeforeValidation, testSchema);
|
|
30
32
|
|
|
31
33
|
const AgeInputComponent = (props: {controller: Controller<FormStateBeforeValidation>}) => {
|
|
32
34
|
const {controller} = props;
|
|
33
|
-
const [[age, errorMessage], {handleChange}] = useFormSlice(controller, s => [s.value.age, s.errors.age] as const);
|
|
35
|
+
const [[age, errorMessage], {handleChange}] = useFormSlice(controller, (s) => [s.value.age, s.errors.age] as const);
|
|
34
36
|
return (
|
|
35
37
|
<div>
|
|
36
38
|
<input
|
|
@@ -56,7 +58,7 @@ test('useSelector can select the fields', async () => {
|
|
|
56
58
|
<div>
|
|
57
59
|
<AgeInputComponent controller={TestFormHook.controller} />
|
|
58
60
|
</div>
|
|
59
|
-
)
|
|
61
|
+
);
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
render(<Top />);
|
|
@@ -81,12 +83,12 @@ test('zod parse value before submit', async () => {
|
|
|
81
83
|
const PARSED_RESULT = Number(INPUT_AGE);
|
|
82
84
|
|
|
83
85
|
const handleSubmitTester = TestFormHook.handleSubmit((e) => (result) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
if (result.success) {
|
|
87
|
+
expect(result.data.age).toBe(PARSED_RESULT);
|
|
88
|
+
} else {
|
|
89
|
+
expect('should not called').toBe(result.error);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
90
92
|
|
|
91
93
|
const Top = () => {
|
|
92
94
|
return (
|
|
@@ -94,16 +96,16 @@ test('zod parse value before submit', async () => {
|
|
|
94
96
|
<AgeInputComponent controller={TestFormHook} />
|
|
95
97
|
<button data-testid="submit-button" onClick={handleSubmitTester} />
|
|
96
98
|
</div>
|
|
97
|
-
)
|
|
99
|
+
);
|
|
98
100
|
};
|
|
99
101
|
|
|
100
102
|
render(<Top />);
|
|
101
103
|
|
|
102
|
-
const ageInput: HTMLInputElement = screen.getByTestId('age-input')
|
|
104
|
+
const ageInput: HTMLInputElement = screen.getByTestId('age-input');
|
|
103
105
|
await userEvent.type(ageInput, INPUT_AGE);
|
|
104
106
|
|
|
105
107
|
await waitFor(() => {
|
|
106
|
-
const ageInput: HTMLInputElement = screen.getByTestId('age-input')
|
|
108
|
+
const ageInput: HTMLInputElement = screen.getByTestId('age-input');
|
|
107
109
|
expect(ageInput.value).toBe(INPUT_AGE);
|
|
108
110
|
});
|
|
109
111
|
|
|
@@ -117,4 +119,4 @@ test('zod parse value before submit', async () => {
|
|
|
117
119
|
expect(s.errors.age).toBeNull();
|
|
118
120
|
});
|
|
119
121
|
});
|
|
120
|
-
});
|
|
122
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -65,7 +65,11 @@ type FormControllerBehavior<StateBeforeValidation> = {
|
|
|
65
65
|
/**
|
|
66
66
|
* You can handle server side or other external error via this action.
|
|
67
67
|
*/
|
|
68
|
-
|
|
68
|
+
pushFormErrors: (
|
|
69
|
+
validator: (state: StateBeforeValidation) => Partial<FormErrors<StateBeforeValidation>>,
|
|
70
|
+
) => (prev: FullFormState<StateBeforeValidation>) => FullFormState<StateBeforeValidation>;
|
|
71
|
+
|
|
72
|
+
reduceFormErrors: (
|
|
69
73
|
reducer: (prev: FormErrors<StateBeforeValidation>) => FormErrors<StateBeforeValidation>,
|
|
70
74
|
) => (prev: FullFormState<StateBeforeValidation>) => FullFormState<StateBeforeValidation>;
|
|
71
75
|
|
|
@@ -150,7 +154,11 @@ function createFormStore<StateBeforeValidation extends StateRestriction, Schema
|
|
|
150
154
|
|
|
151
155
|
return {...prev, isDirty: true, isValid: false, errors: newErrors};
|
|
152
156
|
},
|
|
153
|
-
|
|
157
|
+
pushFormErrors: (validator) => (prev) => {
|
|
158
|
+
const pushedErrors = validator(prev.value);
|
|
159
|
+
return {...prev, errors: {...prev.errors, ...pushedErrors}};
|
|
160
|
+
},
|
|
161
|
+
reduceFormErrors: (reducer) => (prev) => {
|
|
154
162
|
return {...prev, errors: reducer(prev.errors)};
|
|
155
163
|
},
|
|
156
164
|
handleChange: (name, value) => (prev) => {
|
|
@@ -174,9 +182,9 @@ function createFormStore<StateBeforeValidation extends StateRestriction, Schema
|
|
|
174
182
|
type ActionsCanBePublic<State extends StateRestriction> = {
|
|
175
183
|
reset: VoidFunction;
|
|
176
184
|
initializeForm: (initial: Partial<State>) => void;
|
|
185
|
+
pushFormErrors: (validator: (state: State) => Partial<FormErrors<State>>) => void;
|
|
177
186
|
handleChange: HandleChangeAction<State>;
|
|
178
187
|
handleBulkChange: (setter: (prev: State) => Partial<State>) => void;
|
|
179
|
-
handleError: (reducer: (prev: FormErrors<State>) => FormErrors<State>) => void;
|
|
180
188
|
};
|
|
181
189
|
|
|
182
190
|
/**
|