diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b119dc3 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +semi: false +singleQuote: true +trailingComma: es5 +tabWidth: 2 +printWidth: 200 diff --git a/lib/index.ts b/lib/index.ts index 60de332..f26f159 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,21 +1,19 @@ import React, { useState, useEffect } from 'react' - - export type useFormExtractor = (from: any) => any export type useFormOptions = { - extractor?: useFormExtractor, - getter?: string, - setter?: string, + extractor?: useFormExtractor + getter?: string + setter?: string } -export type useFormValidatorFunction = ((s: any) => boolean | Promise) +export type useFormValidatorFunction = (s: any) => boolean | Promise export type useFormValidatorMethod = useFormValidatorFunction | RegExp export type useFormValidatorObject = { - validator: useFormValidatorMethod, - message?: string, + validator: useFormValidatorMethod + message?: string } export type useFormValidator = useFormValidatorMethod | useFormValidatorObject @@ -26,82 +24,74 @@ export const HTMLInputExtractor: useFormExtractor = (e: React.FormEvent) => e.currentTarget.checked function isFormValidatorObject(validator: useFormValidatorMethod | useFormValidatorObject): validator is useFormValidatorObject { - return validator.constructor.name === 'Object' + return validator.constructor.name === 'Object' } const defaultErrorMessage = (key: any) => `Error in ${key}` export const useForm = (init: T, validators: Partial = {}, options: useFormOptions = {}) => { - const [form, setForm] = useState(init) + const [form, setForm] = useState(init) - const [errors, setErrors] = useState>({}) - const [isValid, setIsValid] = useState(true); + const [errors, setErrors] = useState>({}) + const [isValid, setIsValid] = useState(true) - useEffect(() => { - setIsValid(!Object.values(errors).reduce((acc, cur) => acc || cur !== undefined, false)) - }, [errors]) + useEffect(() => { + setIsValid(!Object.values(errors).reduce((acc, cur) => acc || cur !== undefined, false)) + }, [errors]) - const _set = (key: keyof T, value: any) => { - setForm({ - ...form, - [key]: value, - }) - } + const _set = (key: keyof T, value: any) => { + setForm({ + ...form, + [key]: value, + }) + } - const _validateAll = async (value: any, object: useFormValidator): Promise => { - const validator = isFormValidatorObject(object) ? object.validator : object + const _validateAll = async (value: any, object: useFormValidator): Promise => { + const validator = isFormValidatorObject(object) ? object.validator : object - if (validator.constructor.name === 'Function') - return (validator as useFormValidatorFunction)(value) - else if (validator.constructor.name === 'AsyncFunction') - return await (validator as useFormValidatorFunction)(value) - else if (validator.constructor.name === 'RegExp') - return (validator as RegExp).test(value) - else return false - } + if (validator.constructor.name === 'Function') return (validator as useFormValidatorFunction)(value) + else if (validator.constructor.name === 'AsyncFunction') return await (validator as useFormValidatorFunction)(value) + else if (validator.constructor.name === 'RegExp') return (validator as RegExp).test(value) + else return false + } - const _validate = (key: keyof T, value: any) => { - const validator: useFormValidatorParameter | undefined = validators[key] - if (!validator) return + const _validate = (key: keyof T, value: any) => { + const validator: useFormValidatorParameter | undefined = validators[key] + if (!validator) return - if (Array.isArray(validator)) { - Promise.all(validator.map(v => _validateAll(value, v))) - .then(result => { - const index = result.indexOf(false) - setErrors({ - ...errors, - [key]: index === -1 - ? undefined - : isFormValidatorObject(validator[index]) && (validator[index] as useFormValidatorObject).message - ? (validator[index] as useFormValidatorObject).message - : defaultErrorMessage(key) - }) - }) - } else { - _validateAll(value, validator) - .then(valid => { - setErrors({ - ...errors, - [key]: valid - ? undefined - : isFormValidatorObject(validator) && validator.message - ? validator.message - : defaultErrorMessage(key) - }) - }) - } - } + if (Array.isArray(validator)) { + Promise.all(validator.map(v => _validateAll(value, v))).then(result => { + const index = result.indexOf(false) + setErrors({ + ...errors, + [key]: + index === -1 + ? undefined + : isFormValidatorObject(validator[index]) && (validator[index] as useFormValidatorObject).message + ? (validator[index] as useFormValidatorObject).message + : defaultErrorMessage(key), + }) + }) + } else { + _validateAll(value, validator).then(valid => { + setErrors({ + ...errors, + [key]: valid ? undefined : isFormValidatorObject(validator) && validator.message ? validator.message : defaultErrorMessage(key), + }) + }) + } + } - const update = (key: keyof T, extractor = options.extractor) => (value: any) => { - const extracted = extractor ? extractor(value) : HTMLInputExtractor(value) - _set(key, extracted) - _validate(key, extracted) - } + const update = (key: keyof T, extractor = options.extractor) => (value: any) => { + const extracted = extractor ? extractor(value) : HTMLInputExtractor(value) + _set(key, extracted) + _validate(key, extracted) + } - const auto = (key: keyof T, opts: useFormOptions = {}) => ({ - [opts.getter || options.getter || 'onChange']: update(key, opts.extractor), - [opts.setter || options.setter || 'value']: form[key] as any, - }) + const auto = (key: keyof T, opts: useFormOptions = {}) => ({ + [opts.getter || options.getter || 'onChange']: update(key, opts.extractor), + [opts.setter || options.setter || 'value']: form[key] as any, + }) - return { form, update, auto, errors, isValid } -} \ No newline at end of file + return { form, update, auto, errors, isValid } +} diff --git a/test/index.html b/test/index.html index 5a922ba..569c307 100644 --- a/test/index.html +++ b/test/index.html @@ -1,22 +1,19 @@ + + + + + Form Hero + + + - - - - - Form Hero - - - - - -
- - - - \ No newline at end of file + +
+ + + diff --git a/test/test.tsx b/test/test.tsx index ab7862c..3432bee 100644 --- a/test/test.tsx +++ b/test/test.tsx @@ -3,32 +3,33 @@ import ReactDOM from 'react-dom' import { useForm } from '../' - -const TextError: React.FC<{ error?: string }> = ({ error }) => !error - ? null - :
{error}
+const TextError: React.FC<{ error?: string }> = ({ error }) => (!error ? null :
{error}
) const Index: React.FC = () => { - - const { auto, form, errors, isValid } = useForm({ - username: '', - password: '', - type: 'formhero', - awesome: true, - }, { - username: [ - /^test/, - { - validator: async () => { return true }, - message: 'Digits please', - } - ], - password: { - validator: /^.{3,}$/, - message: 'To short', + const { auto, form, errors, isValid } = useForm( + { + username: '', + password: '', + type: 'formhero', + awesome: true, }, - awesome: (value) => !!value - }) + { + username: [ + /^test/, + { + validator: async () => { + return true + }, + message: 'Digits please', + }, + ], + password: { + validator: /^.{3,}$/, + message: 'To short', + }, + awesome: value => !!value, + } + ) const _submit = (e: React.FormEvent) => { e.preventDefault() @@ -41,12 +42,14 @@ const Index: React.FC = () => {
Username
-

+
+
Password
-

+
+
Which one to choose?
@@ -57,21 +60,27 @@ const Index: React.FC = () => {
-

- +
+
-

+
+
- + ) @@ -79,5 +88,5 @@ const Index: React.FC = () => { ReactDOM.render(, document.getElementById('root')) - // @ts-ignore -// if (module.hot) module.hot.accept() \ No newline at end of file +// @ts-ignore +// if (module.hot) module.hot.accept()