mayoiga 0.0.22 → 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.
Files changed (64) hide show
  1. package/.eslintrc.js +111 -0
  2. package/.github/workflows/checker.yml +42 -0
  3. package/.gitignore +217 -0
  4. package/.prettierrc +5 -0
  5. package/README.md +21 -45
  6. package/component.d.ts +1 -0
  7. package/component.js +1 -0
  8. package/dist/component.d.ts +7 -0
  9. package/dist/component.js +11 -0
  10. package/dist/component.test.d.ts +1 -0
  11. package/dist/component.test.js +83 -0
  12. package/dist/index.d.ts +92 -0
  13. package/dist/index.js +150 -0
  14. package/dist/index.test.d.ts +1 -0
  15. package/dist/index.test.js +77 -0
  16. package/dist/utils.d.ts +2 -0
  17. package/dist/utils.js +6 -0
  18. package/docs/.nojekyll +0 -0
  19. package/docs/assets/css/main.css +2328 -0
  20. package/docs/assets/images/icons.png +0 -0
  21. package/docs/assets/images/icons@2x.png +0 -0
  22. package/docs/assets/images/widgets.png +0 -0
  23. package/docs/assets/images/widgets@2x.png +0 -0
  24. package/docs/assets/js/main.js +1 -0
  25. package/docs/assets/js/search.js +3 -0
  26. package/docs/globals.html +185 -0
  27. package/docs/index.html +249 -0
  28. package/docs/modules/_actions_.html +398 -0
  29. package/docs/modules/_forms_.html +362 -0
  30. package/docs/modules/_index_.html +170 -0
  31. package/docs/modules/_inputprotocol_.html +319 -0
  32. package/docs/modules/_mayoiga_.html +783 -0
  33. package/docs/modules/_reducer_.html +417 -0
  34. package/example/src/demo-app.tsx +123 -0
  35. package/example/src/index.tsx +15 -0
  36. package/package.json +42 -44
  37. package/setup/vite-global-setup.js +1 -0
  38. package/setup/vite-set-global.js +0 -0
  39. package/src/component.test.tsx +146 -0
  40. package/src/component.tsx +23 -0
  41. package/src/index.test.tsx +122 -0
  42. package/src/index.ts +311 -0
  43. package/src/utils.ts +8 -0
  44. package/tsconfig.json +38 -0
  45. package/vite.config.js +10 -0
  46. package/yarn.lock +2378 -0
  47. package/lib/actions.d.ts +0 -28
  48. package/lib/actions.js +0 -29
  49. package/lib/actions.js.map +0 -1
  50. package/lib/forms.d.ts +0 -21
  51. package/lib/forms.js +0 -82
  52. package/lib/forms.js.map +0 -1
  53. package/lib/index.d.ts +0 -3
  54. package/lib/index.js +0 -7
  55. package/lib/index.js.map +0 -1
  56. package/lib/inputProtocol.d.ts +0 -17
  57. package/lib/inputProtocol.js +0 -24
  58. package/lib/inputProtocol.js.map +0 -1
  59. package/lib/mayoiga.d.ts +0 -110
  60. package/lib/mayoiga.js +0 -131
  61. package/lib/mayoiga.js.map +0 -1
  62. package/lib/reducer.d.ts +0 -20
  63. package/lib/reducer.js +0 -53
  64. package/lib/reducer.js.map +0 -1
package/lib/actions.d.ts DELETED
@@ -1,28 +0,0 @@
1
- export declare type FSA<S> = {
2
- type: 'SWAP';
3
- payload: S;
4
- } | {
5
- type: 'SET_STATE';
6
- payload: Partial<S>;
7
- } | {
8
- type: 'CHANGE';
9
- payload: {
10
- name: keyof S;
11
- value: S[keyof S];
12
- };
13
- } | {
14
- type: 'SUBMIT';
15
- payload: {};
16
- } | {
17
- type: 'ERROR';
18
- payload: {
19
- name: keyof S;
20
- value: ReadonlyArray<string>;
21
- };
22
- };
23
- export declare type FormReducerActionTypes = FSA<any>['type'];
24
- export declare const swap: <S>(newInitialState: S) => FSA<S>;
25
- export declare const setNewState: <S>(newState: Partial<S>) => FSA<S>;
26
- export declare const changeField: <S>(name: keyof S, value: S[keyof S]) => FSA<S>;
27
- export declare const submitValue: <S>(state: S) => FSA<S>;
28
- export declare const sendErrors: <S>(name: keyof S, errors: readonly string[]) => FSA<S>;
package/lib/actions.js DELETED
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.swap = (newInitialState) => ({
4
- type: 'SWAP',
5
- payload: newInitialState,
6
- });
7
- exports.setNewState = (newState) => ({
8
- type: 'SET_STATE',
9
- payload: newState,
10
- });
11
- exports.changeField = (name, value) => ({
12
- type: 'CHANGE',
13
- payload: {
14
- name,
15
- value,
16
- },
17
- });
18
- exports.submitValue = (state) => ({
19
- type: 'SUBMIT',
20
- payload: {},
21
- });
22
- exports.sendErrors = (name, errors) => ({
23
- type: 'ERROR',
24
- payload: {
25
- name,
26
- value: errors,
27
- },
28
- });
29
- //# sourceMappingURL=actions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":";;AA6Ba,QAAA,IAAI,GAAG,CAAI,eAAkB,EAAU,EAAE,CAAC,CAAC;IACtD,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,eAAe;CACzB,CAAC,CAAC;AAEU,QAAA,WAAW,GAAG,CAAI,QAAoB,EAAU,EAAE,CAAC,CAAC;IAC/D,IAAI,EAAE,WAAW;IACjB,OAAO,EAAE,QAAQ;CAClB,CAAC,CAAC;AAEU,QAAA,WAAW,GAAG,CAAI,IAAa,EAAE,KAAiB,EAAU,EAAE,CAAC,CAAC;IAC3E,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE;QACP,IAAI;QACJ,KAAK;KACN;CACF,CAAC,CAAC;AAEU,QAAA,WAAW,GAAG,CAAI,KAAQ,EAAU,EAAE,CAAC,CAAC;IACnD,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,EAAE;CACZ,CAAC,CAAC;AAEU,QAAA,UAAU,GAAG,CAAI,IAAa,EAAE,MAA6B,EAAU,EAAE,CAAC,CAAC;IACtF,IAAI,EAAE,OAAO;IACb,OAAO,EAAE;QACP,IAAI;QACJ,KAAK,EAAE,MAAM;KACd;CACF,CAAC,CAAC"}
package/lib/forms.d.ts DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * This is just a sample implementation.
3
- * You can make to fit any component library that you are using.
4
- *
5
- */
6
- /// <reference types="react" />
7
- import { InputProtocol } from './inputProtocol';
8
- export declare function MappedInputFactory(mapInputToState?: (val: string) => any /** FIXME: fmmmmmm */): <S, Name extends keyof S>(props: InputProtocol<S, Name, undefined>) => JSX.Element;
9
- export declare const Input: <S, Name extends keyof S>(props: InputProtocol<S, Name, undefined>) => JSX.Element;
10
- export declare const NumberInput: <S, Name extends keyof S>(props: InputProtocol<S, Name, undefined>) => JSX.Element;
11
- export declare function MappedRadioFactory(candidates: ReadonlyArray<{
12
- label: string;
13
- value: any;
14
- }>,
15
- /** FIXME: fmmmmmm, I think I can write infer which returns `never` if type is invalid but... */
16
- mapInputToState?: (val: string) => any): <S, Name extends keyof S>(props: InputProtocol<S, Name, undefined>) => JSX.Element;
17
- export declare function MappedSelectFactory(options: ReadonlyArray<{
18
- label: string;
19
- value: any;
20
- disabled?: boolean;
21
- }>, mapInputToState?: (val: string) => any): <S, Name extends keyof S>(props: InputProtocol<S, Name, undefined>) => JSX.Element;
package/lib/forms.js DELETED
@@ -1,82 +0,0 @@
1
- "use strict";
2
- /**
3
- * This is just a sample implementation.
4
- * You can make to fit any component library that you are using.
5
- *
6
- */
7
- var __rest = (this && this.__rest) || function (s, e) {
8
- var t = {};
9
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
10
- t[p] = s[p];
11
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
12
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
13
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
14
- t[p[i]] = s[p[i]];
15
- }
16
- return t;
17
- };
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
22
- result["default"] = mod;
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- const React = __importStar(require("react"));
27
- const react_1 = require("react");
28
- // TODO: mapStateToValue (val: S[Name]) => string
29
- function MappedInputFactory(mapInputToState = val => val /** FIXME: fmmmmmm */) {
30
- return (props) => {
31
- const { name, value, onChange, errors, touched, delegatedProps = {} } = props, restProps = __rest(props, ["name", "value", "onChange", "errors", "touched", "delegatedProps"]);
32
- const handleChange = react_1.useCallback((e) => {
33
- const value = e.currentTarget.value;
34
- onChange(name, mapInputToState(value));
35
- }, [onChange]);
36
- return (React.createElement(React.Fragment, null,
37
- React.createElement("input", Object.assign({}, restProps, delegatedProps, { value: value
38
- ? value /** FIXME: TS 3.5.1 changes defualt infer is unknown */
39
- .toString()
40
- : '', name: name, onChange: handleChange })),
41
- touched && errors.length !== 0 && React.createElement("div", { style: { color: 'red' } }, errors[0])));
42
- };
43
- }
44
- exports.MappedInputFactory = MappedInputFactory;
45
- exports.Input = MappedInputFactory();
46
- exports.NumberInput = MappedInputFactory(val => parseInt(val, 10) || 0);
47
- function MappedRadioFactory(candidates,
48
- /** FIXME: fmmmmmm, I think I can write infer which returns `never` if type is invalid but... */
49
- mapInputToState = val => val) {
50
- return (props) => {
51
- const { name, onChange, errors, touched, delegatedProps = {} } = props, restProps = __rest(props, ["name", "onChange", "errors", "touched", "delegatedProps"]);
52
- const handleChange = react_1.useCallback((e) => {
53
- const value = e.currentTarget.value;
54
- onChange(name, mapInputToState(value));
55
- }, [onChange]);
56
- return (React.createElement(React.Fragment, null,
57
- candidates.map(({ label, value }) => (React.createElement("label", { key: value },
58
- React.createElement("input", Object.assign({}, restProps, delegatedProps, { type: "radio", name: name, value: value, checked: value === props.value, onChange: handleChange })),
59
- label))),
60
- touched && errors.length !== 0 && React.createElement("div", { style: { color: 'red' } }, errors[0])));
61
- };
62
- }
63
- exports.MappedRadioFactory = MappedRadioFactory;
64
- function MappedSelectFactory(options, mapInputToState = val => val) {
65
- return (props) => {
66
- const { value, name, onChange, errors, touched, delegatedProps = {} } = props, restProps = __rest(props, ["value", "name", "onChange", "errors", "touched", "delegatedProps"]);
67
- const handleChange = react_1.useCallback((e) => {
68
- const value = e.currentTarget.value;
69
- onChange(name, mapInputToState(value));
70
- }, [onChange]);
71
- return (React.createElement(React.Fragment, null,
72
- React.createElement("select", Object.assign({}, restProps, delegatedProps, { name: name, value: value
73
- ? value /** TS 3.5.1 changes defualt infer is unknown */
74
- .toString()
75
- : '', onChange: handleChange }),
76
- React.createElement("option", { value: "", disabled: true }, "Please select"),
77
- options.map(({ label, value, disabled }) => (React.createElement("option", { key: value, value: value, disabled: disabled }, label)))),
78
- touched && errors.length !== 0 && React.createElement("div", { style: { color: 'red' } }, errors[0])));
79
- };
80
- }
81
- exports.MappedSelectFactory = MappedSelectFactory;
82
- //# sourceMappingURL=forms.js.map
package/lib/forms.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"forms.js","sourceRoot":"","sources":["../src/forms.tsx"],"names":[],"mappings":"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"}
package/lib/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import { useForm, useFormState, createFormScope } from './mayoiga';
2
- import { InputProtocol } from './inputProtocol';
3
- export { useForm, useFormState, createFormScope, InputProtocol };
package/lib/index.js DELETED
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const mayoiga_1 = require("./mayoiga");
4
- exports.useForm = mayoiga_1.useForm;
5
- exports.useFormState = mayoiga_1.useFormState;
6
- exports.createFormScope = mayoiga_1.createFormScope;
7
- //# sourceMappingURL=index.js.map
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";;AAAA,uCAAiE;AAGzD,kBAHA,iBAAO,CAGA;AAAE,uBAHA,sBAAY,CAGA;AAAE,0BAHA,yBAAe,CAGA"}
@@ -1,17 +0,0 @@
1
- import { InputHTMLAttributes } from 'react';
2
- declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
3
- declare type MayoigaConnectedInputProtocol<S, Name extends keyof S, DelegatedProps> = {
4
- name: Name;
5
- value: S[Name];
6
- /** Errors which generated by mayoiga validation */
7
- errors: ReadonlyArray<string>;
8
- /** Validation is running even if it is first renderd. `touched` can be useful if you would like to suppress error indication until user touched the input. */
9
- touched: boolean;
10
- onChange(name: Name, value: S[Name]): void;
11
- /**
12
- * Props which passed via `componentProps` of {@link FieldProps}.
13
- */
14
- delegatedProps: DelegatedProps;
15
- };
16
- export declare type InputProtocol<S, Name extends keyof S, DelegatedProps> = MayoigaConnectedInputProtocol<S, Name, DelegatedProps> & Omit<InputHTMLAttributes<any>, 'name' | 'onChange' | 'value'>;
17
- export {};
@@ -1,24 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // TODO: How's the below?
4
- // type Primitive = 'string' | 'number' | 'boolean';
5
- // type FieldType<FT> = FT extends string
6
- // ? 'string'
7
- // : FT extends number
8
- // ? 'number'
9
- // : FT extends boolean
10
- // ? 'boolean'
11
- // : ((domVal: string) => FT);
12
- // const PRIMITIVE_CONVERT_DEF = {
13
- // string: (val: string) => val,
14
- // number: (val: string) => parseInt(val, 10) || 0,
15
- // boolean: (val: string) => val === 'true',
16
- // };
17
- // function fieldConverter<FT>(dataType: FieldType<FT>, value: string): FT {
18
- // const def = (PRIMITIVE_CONVERT_DEF as any)[dataType as any];
19
- // if (def) {
20
- // return def(value);
21
- // }
22
- // return (dataType as any)(value);
23
- // }
24
- //# sourceMappingURL=inputProtocol.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inputProtocol.js","sourceRoot":"","sources":["../src/inputProtocol.tsx"],"names":[],"mappings":";;AAsBA,yBAAyB;AACzB,oDAAoD;AACpD,yCAAyC;AACzC,eAAe;AACf,wBAAwB;AACxB,eAAe;AACf,yBAAyB;AACzB,gBAAgB;AAChB,gCAAgC;AAChC,kCAAkC;AAClC,kCAAkC;AAClC,qDAAqD;AACrD,8CAA8C;AAC9C,KAAK;AAEL,4EAA4E;AAC5E,iEAAiE;AACjE,eAAe;AACf,yBAAyB;AACzB,MAAM;AACN,qCAAqC;AACrC,IAAI"}
package/lib/mayoiga.d.ts DELETED
@@ -1,110 +0,0 @@
1
- import * as React from 'react';
2
- import { Dispatch, Context, ReactNode, FC } from 'react';
3
- import { FSA } from './actions';
4
- import { Store } from './reducer';
5
- import { InputProtocol } from './inputProtocol';
6
- declare type MayoigaContextValue<S> = {
7
- state: Store<S>;
8
- dispatch: Dispatch<FSA<S>>;
9
- };
10
- /**
11
- * Validator definition to pass to the each form fields.
12
- *
13
- * @param target The value which handled by the input field.
14
- * @param record The form state itselfs. It is useful if you had to write validation depends on other fields.
15
- * @returns It should return string if there is something wrong.
16
- */
17
- declare type Validator<S, Name extends keyof S> = (target: S[Name], record: S) => undefined | string;
18
- declare type FormProps<S> = {
19
- className?: string;
20
- onSubmit?(value: S): void;
21
- children: ReactNode;
22
- };
23
- declare type FieldProps<S, Name extends keyof S, ComponentProps> = {
24
- /** One on the name of field. Have to be `keyof State`. */
25
- name: Name;
26
- /** You might want to handle onChange event in case. */
27
- onChange?(name: Name, value: S[Name]): void;
28
- validations?: ReadonlyArray<Validator<S, Name>>;
29
- /**
30
- * Props to delegate to the input component.
31
- * @example
32
- * ```
33
- *
34
- * componentProps={{disabled: props.formState.age >= 20}}
35
- * component={AlcoholCheckbox}
36
- * ```
37
- */
38
- componentProps?: ComponentProps;
39
- /** Component which can handle the field of the form state. It should implement {@link InputProtocol}. */
40
- component: FC<InputProtocol<S, Name, ComponentProps>>;
41
- };
42
- declare type MayoigaProps<S> = {
43
- initialState: S;
44
- onSubmit(hasErrors: boolean, value: S, formInfo: {
45
- errors: Store<S>['errors'];
46
- touched: boolean;
47
- }): void;
48
- };
49
- /** @obsolete */
50
- declare type ScopedComponentProps<S> = {
51
- touched: boolean;
52
- errors: Store<S>['errors'];
53
- formState: S;
54
- };
55
- /**
56
- * A function to create scope which allows to use `useForm` function to manage form value.
57
- *
58
- * @example
59
- * ```
60
- *
61
- * type FormState = {name: '', age: 0};
62
- * const {context, scope} = createFormScope<FormState>();
63
- *
64
- * const TheForm = scope(props => {
65
- * const {Form, Field} = useForm(context);
66
- * // ...
67
- * ```
68
- *
69
- */
70
- export declare function createFormScope<S>(): {
71
- context: React.Context<MayoigaContextValue<S>>;
72
- scope: <OwnProps = {}>(ConnectedComponent: React.FunctionComponent<OwnProps & ScopedComponentProps<S>>) => (props: OwnProps & MayoigaProps<S>) => JSX.Element;
73
- };
74
- /**
75
- * The Hook to summon type safe React form component.
76
- * To know the props that Field can accept {@link FieldProps}.
77
- *
78
- * @example
79
- * ```
80
- *
81
- * const TheForm = scope(props => {
82
- * const {Form, Field} = useForm(context);
83
- * return (
84
- * <Form>
85
- * <Field name="name" component={props => <input value={props.value.toString()} />} validations={[required]} />
86
- * <Field name="fieldNameHaven'tDefined" <= you will see compile error if you were specified the name haven't declared in the context type for initialState.
87
- * </Form>
88
- * );
89
- * ```
90
- *
91
- * You should be aware, `component` props for <Field /> is going to be cached at the first render. So it should be same pure function.
92
- */
93
- export declare function useForm<S>(formScope: Context<MayoigaContextValue<S>>): {
94
- Form: React.MemoExoticComponent<(props: FormProps<S>) => JSX.Element>;
95
- Field: <Name extends Extract<keyof S, string>, ComponentProps = undefined>(props: FieldProps<S, Name, ComponentProps>) => JSX.Element;
96
- useFormState(): [Store<S>, (newState: Partial<S>) => void];
97
- };
98
- /**
99
- * You can get current form state and also change it:
100
- *
101
- * ```
102
- * const [{ errors, formData }, setFormState] = useFormState(context);
103
- * ...
104
- * onChange={(name, value) => {
105
- * if (value) setFormState({otherFieldValue: ''});
106
- * }}
107
- * ```
108
- */
109
- export declare function useFormState<S>(formScope: Context<MayoigaContextValue<S>>): [Store<S>, (newState: Partial<S>) => void];
110
- export {};
package/lib/mayoiga.js DELETED
@@ -1,131 +0,0 @@
1
- "use strict";
2
- var __importStar = (this && this.__importStar) || function (mod) {
3
- if (mod && mod.__esModule) return mod;
4
- var result = {};
5
- if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
6
- result["default"] = mod;
7
- return result;
8
- };
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- const React = __importStar(require("react"));
11
- const react_1 = require("react");
12
- const actions_1 = require("./actions");
13
- const reducer_1 = require("./reducer");
14
- const EMPTY_ERRORS = [];
15
- // TODO: need `mapChanged(value: S): S;` ?
16
- /**
17
- * A function to create scope which allows to use `useForm` function to manage form value.
18
- *
19
- * @example
20
- * ```
21
- *
22
- * type FormState = {name: '', age: 0};
23
- * const {context, scope} = createFormScope<FormState>();
24
- *
25
- * const TheForm = scope(props => {
26
- * const {Form, Field} = useForm(context);
27
- * // ...
28
- * ```
29
- *
30
- */
31
- function createFormScope() {
32
- const Ctx = react_1.createContext(null);
33
- return {
34
- context: Ctx,
35
- scope: function (ConnectedComponent) {
36
- return (props) => {
37
- const { initialState, onSubmit } = props;
38
- const [state, dispatch] = reducer_1.useFormReducer(initialState, onSubmit);
39
- // TODO: I assumed useReducer is re-render if initialState was changed but doesn't. Need investigation though, I'll address by the useEffect for the time being.
40
- react_1.useEffect(() => dispatch(actions_1.swap(initialState)), [initialState]);
41
- const touchedAll = Object.values(state.touched).every(v => v);
42
- return (React.createElement(Ctx.Provider, { value: { state, dispatch } },
43
- React.createElement(ConnectedComponent, Object.assign({}, props, { formState: state.formData, touched: touchedAll, errors: state.errors }))));
44
- };
45
- },
46
- };
47
- }
48
- exports.createFormScope = createFormScope;
49
- /**
50
- * The Hook to summon type safe React form component.
51
- * To know the props that Field can accept {@link FieldProps}.
52
- *
53
- * @example
54
- * ```
55
- *
56
- * const TheForm = scope(props => {
57
- * const {Form, Field} = useForm(context);
58
- * return (
59
- * <Form>
60
- * <Field name="name" component={props => <input value={props.value.toString()} />} validations={[required]} />
61
- * <Field name="fieldNameHaven'tDefined" <= you will see compile error if you were specified the name haven't declared in the context type for initialState.
62
- * </Form>
63
- * );
64
- * ```
65
- *
66
- * You should be aware, `component` props for <Field /> is going to be cached at the first render. So it should be same pure function.
67
- */
68
- function useForm(formScope) {
69
- return react_1.useMemo(() => ({
70
- Form: react_1.memo((props) => {
71
- const { state, dispatch } = react_1.useContext(formScope);
72
- const { className, onSubmit } = props;
73
- return (React.createElement("form", { className: className, onSubmit: e => {
74
- e.preventDefault();
75
- if (onSubmit) {
76
- onSubmit(state.formData);
77
- }
78
- dispatch(actions_1.submitValue(state.formData));
79
- } }, props.children));
80
- }),
81
- Field: (props) => {
82
- const { state, dispatch } = react_1.useContext(formScope);
83
- const { component, name, validations, componentProps, onChange } = props;
84
- const validate = (target) => {
85
- if (validations !== undefined) {
86
- const errors = validations.map(v => v(target, state.formData)).filter((result) => !!result);
87
- dispatch(actions_1.sendErrors(name, errors.length === 0 ? [] : errors));
88
- }
89
- };
90
- const handleChange = react_1.useCallback((name, value) => {
91
- dispatch(actions_1.changeField(name, value));
92
- if (onChange) {
93
- onChange(name, value);
94
- }
95
- validate(value);
96
- }, [name, state, componentProps]);
97
- const value = state.formData[name];
98
- const errors = state.errors[name];
99
- const touched = state.touched[name];
100
- react_1.useEffect(() => {
101
- // I'm not exactly sure why but we need it to accomplish dispatch action on mounted. :(
102
- window.requestAnimationFrame(() => validate(value));
103
- }, [state.formData]);
104
- // cache component for performance
105
- const Component = react_1.useMemo(() => component, [name]);
106
- return (React.createElement(Component, { name: name, value: value /** FIXME: */, onChange: handleChange, errors: errors, touched: touched, delegatedProps: componentProps }));
107
- },
108
- useFormState() {
109
- const { state, dispatch } = react_1.useContext(formScope);
110
- return [state, (newState) => dispatch(actions_1.setNewState(newState))];
111
- },
112
- }), [formScope]);
113
- }
114
- exports.useForm = useForm;
115
- /**
116
- * You can get current form state and also change it:
117
- *
118
- * ```
119
- * const [{ errors, formData }, setFormState] = useFormState(context);
120
- * ...
121
- * onChange={(name, value) => {
122
- * if (value) setFormState({otherFieldValue: ''});
123
- * }}
124
- * ```
125
- */
126
- function useFormState(formScope) {
127
- const { state, dispatch } = react_1.useContext(formScope);
128
- return [state, (newState) => dispatch(actions_1.setNewState(newState))];
129
- }
130
- exports.useFormState = useFormState;
131
- //# sourceMappingURL=mayoiga.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mayoiga.js","sourceRoot":"","sources":["../src/mayoiga.tsx"],"names":[],"mappings":";;;;;;;;;AAAA,6CAA+B;AAE/B,iCAA6G;AAG7G,uCAAuF;AACvF,uCAAgD;AAGhD,MAAM,YAAY,GAA0B,EAAE,CAAC;AAyD/C,0CAA0C;AAC1C;;;;;;;;;;;;;;GAcG;AACH,SAAgB,eAAe;IAC7B,MAAM,GAAG,GAAG,qBAAa,CAAE,IAAsC,CAAC,CAAC;IAEnE,OAAO;QACL,OAAO,EAAE,GAAG;QACZ,KAAK,EAAE,UAAwB,kBAA0D;YACvF,OAAO,CAAC,KAAiC,EAAE,EAAE;gBAC3C,MAAM,EAAC,YAAY,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAC;gBACvC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,wBAAc,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;gBAEjE,gKAAgK;gBAChK,iBAAS,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;gBAE9D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAU,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACvE,OAAO,CACL,oBAAC,GAAG,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAC,KAAK,EAAE,QAAQ,EAAC;oBACpC,oBAAC,kBAAkB,oBAAK,KAAK,IAAE,SAAS,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,CAC1F,CAChB,CAAC;YACJ,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAtBD,0CAsBC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,OAAO,CAAI,SAA0C;IACnE,OAAO,eAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,IAAI,EAAE,YAAI,CAAC,CAAC,KAAmB,EAAE,EAAE;YACjC,MAAM,EAAC,KAAK,EAAE,QAAQ,EAAC,GAAG,kBAAU,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAC;YACpC,OAAO,CACL,8BACE,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE;oBACZ,CAAC,CAAC,cAAc,EAAE,CAAC;oBACnB,IAAI,QAAQ,EAAE;wBACZ,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;qBAC1B;oBACD,QAAQ,CAAC,qBAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACxC,CAAC,IAEA,KAAK,CAAC,QAAQ,CACV,CACR,CAAC;QACJ,CAAC,CAAC;QAEF,KAAK,EAAE,CAAoE,KAA0C,EAAE,EAAE;YACvH,MAAM,EAAC,KAAK,EAAE,QAAQ,EAAC,GAAG,kBAAU,CAAC,SAAS,CAAC,CAAC;YAChD,MAAM,EAAC,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAC,GAAG,KAAK,CAAC;YAEvE,MAAM,QAAQ,GAAG,CAAC,MAAe,EAAE,EAAE;gBACnC,IAAI,WAAW,KAAK,SAAS,EAAE;oBAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAoB,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;oBAC9G,QAAQ,CAAC,oBAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;iBAC/D;YACH,CAAC,CAAC;YAEF,MAAM,YAAY,GAAG,mBAAW,CAC9B,CAAC,IAAU,EAAE,KAAc,EAAE,EAAE;gBAC7B,QAAQ,CAAC,qBAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;gBACnC,IAAI,QAAQ,EAAE;oBACZ,QAAQ,CAAC,IAAI,EAAE,KAAY,CAAC,CAAC;iBAC9B;gBACD,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC,EACD,CAAC,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,CAC9B,CAAC;YAEF,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACpC,iBAAS,CAAC,GAAG,EAAE;gBACb,uFAAuF;gBACvF,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;YACtD,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YAErB,kCAAkC;YAClC,MAAM,SAAS,GAAG,eAAO,CAAC,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;YACnD,OAAO,CACL,oBAAC,SAAS,IACR,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAY,CAAC,aAAa,EACjC,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAe,GAC/B,CACH,CAAC;QACJ,CAAC;QAED,YAAY;YACV,MAAM,EAAC,KAAK,EAAE,QAAQ,EAAC,GAAG,kBAAU,CAAC,SAAS,CAAC,CAAC;YAChD,OAAO,CAAC,KAAK,EAAE,CAAC,QAAoB,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;KACF,CAAC,EACF,CAAC,SAAS,CAAC,CACZ,CAAC;AACJ,CAAC;AAzED,0BAyEC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,YAAY,CAAI,SAA0C;IACxE,MAAM,EAAC,KAAK,EAAE,QAAQ,EAAC,GAAG,kBAAU,CAAC,SAAS,CAAC,CAAC;IAChD,OAAO,CAAC,KAAK,EAAE,CAAC,QAAoB,EAAE,EAAE,CAAC,QAAQ,CAAC,qBAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAHD,oCAGC"}
package/lib/reducer.d.ts DELETED
@@ -1,20 +0,0 @@
1
- /// <reference types="react" />
2
- import { FSA } from './actions';
3
- declare type Errors<StateKeys extends string> = {
4
- [K in StateKeys]: ReadonlyArray<string>;
5
- };
6
- declare type Touched<StateKeys extends string> = {
7
- [K in StateKeys]: boolean;
8
- };
9
- export declare type Store<S extends {
10
- [key: string]: any;
11
- }> = {
12
- errors: Errors<Extract<keyof S, string>>;
13
- formData: S;
14
- touched: Touched<Extract<keyof S, string>>;
15
- };
16
- export declare const useFormReducer: <S>(initialState: S, onSubmit: (hasErrors: boolean, value: S, formInfo: {
17
- errors: Errors<Extract<keyof S, string>>;
18
- touched: boolean;
19
- }) => void) => [Store<S>, import("react").Dispatch<FSA<S>>];
20
- export {};
package/lib/reducer.js DELETED
@@ -1,53 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const react_1 = require("react");
4
- const createFormInitialState = (initialState) => {
5
- const stateKeys = Object.keys(initialState);
6
- return {
7
- formData: initialState,
8
- errors: stateKeys.reduce((buf, k) => {
9
- // NOTE: because typedoc is using old version of TypeScript.
10
- buf[k] = [];
11
- return buf;
12
- }, {}),
13
- touched: stateKeys.reduce((buf, k) => {
14
- // NOTE: same as above. Hey! should I make the code dirty because of document automation???
15
- buf[k] = false;
16
- return buf;
17
- }, {}),
18
- };
19
- };
20
- exports.useFormReducer = (initialState, onSubmit) => react_1.useReducer((state, action) => {
21
- // TODO: logging functionality
22
- // console.log(action);
23
- switch (action.type) {
24
- case 'SWAP': {
25
- return createFormInitialState(action.payload);
26
- }
27
- case 'SET_STATE': {
28
- return Object.assign({}, state, { formData: Object.assign({}, state.formData, action.payload) });
29
- }
30
- case 'CHANGE': {
31
- const { name, value } = action.payload;
32
- return Object.assign({}, state, { formData: Object.assign({}, state.formData, { [name]: value }), touched: Object.assign({}, state.touched, { [name]: true }) });
33
- }
34
- case 'SUBMIT': {
35
- // FIXME: :thinking_face:
36
- const haveTouchedAll = Object.values(state.touched).every(v => v);
37
- const hasAnyError = Object.values(state.errors).some(errs => errs.length !== 0);
38
- // I should repent my sin. I called side effect in reducer...
39
- onSubmit(hasAnyError, state.formData, {
40
- errors: state.errors,
41
- touched: haveTouchedAll,
42
- });
43
- return state;
44
- }
45
- case 'ERROR': {
46
- const { name, value } = action.payload;
47
- return Object.assign({}, state, { errors: Object.assign({}, state.errors, { [name]: value }) });
48
- }
49
- default:
50
- return state;
51
- }
52
- }, initialState, createFormInitialState);
53
- //# sourceMappingURL=reducer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reducer.js","sourceRoot":"","sources":["../src/reducer.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AAejC,MAAM,sBAAsB,GAAG,CAAsB,YAAe,EAAE,EAAE;IACtE,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5C,OAAO;QACL,QAAQ,EAAE,YAAY;QACtB,MAAM,EAAE,SAAS,CAAC,MAAM,CACtB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACT,4DAA4D;YAC3D,GAAW,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YACrB,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAAwB,CACzB;QACD,OAAO,EAAE,SAAS,CAAC,MAAM,CACvB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;YACT,2FAA2F;YAC1F,GAAW,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;YACxB,OAAO,GAAG,CAAC;QACb,CAAC,EACD,EAAyB,CAC1B;KACF,CAAC;AACJ,CAAC,CAAC;AAEW,QAAA,cAAc,GAAG,CAC5B,YAAe,EACf,QAA0G,EAC1G,EAAE,CACF,kBAAU,CACR,CAAC,KAAe,EAAE,MAAc,EAAE,EAAE;IAClC,8BAA8B;IAC9B,uBAAuB;IACvB,QAAQ,MAAM,CAAC,IAAI,EAAE;QACnB,KAAK,MAAM,CAAC,CAAC;YACX,OAAO,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;SAC/C;QACD,KAAK,WAAW,CAAC,CAAC;YAChB,yBACK,KAAK,IACR,QAAQ,oBACH,KAAK,CAAC,QAAQ,EACd,MAAM,CAAC,OAAO,KAEnB;SACH;QACD,KAAK,QAAQ,CAAC,CAAC;YACb,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,CAAC,OAAO,CAAC;YACrC,yBACK,KAAK,IACR,QAAQ,oBACH,KAAK,CAAC,QAAQ,IACjB,CAAC,IAAI,CAAC,EAAE,KAAK,KAEf,OAAO,oBACF,KAAK,CAAC,OAAO,IAChB,CAAC,IAAI,CAAC,EAAE,IAAI,OAEd;SACH;QACD,KAAK,QAAQ,CAAC,CAAC;YACb,yBAAyB;YACzB,MAAM,cAAc,GAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC9F,MAAM,WAAW,GAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAA2B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;YAC3G,6DAA6D;YAC7D,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,QAAQ,EAAE;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,cAAc;aACxB,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;SACd;QACD,KAAK,OAAO,CAAC,CAAC;YACZ,MAAM,EAAC,IAAI,EAAE,KAAK,EAAC,GAAG,MAAM,CAAC,OAAO,CAAC;YACrC,yBACK,KAAK,IACR,MAAM,oBACD,KAAK,CAAC,MAAM,IACf,CAAC,IAAI,CAAC,EAAE,KAAK,OAEf;SACH;QACD;YACE,OAAO,KAAK,CAAC;KAChB;AACH,CAAC,EACD,YAAY,EACZ,sBAAsB,CACvB,CAAC"}