diff --git a/package.json b/package.json index bb78b5cf1..84a77cf71 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "email-validator": "^2.0.4", "eslint": "^7.32.0", "eslint-config-next": "^11.1.2", + "formik": "^2.2.9", "immutability-helper": "^3.1.1", "js-cookie": "^2.2.1", "lodash.debounce": "^4.0.8", @@ -51,7 +52,8 @@ "swr": "^0.5.6", "tabbable": "^5.2.0", "tailwindcss": "^2.2.2", - "uuidv4": "^6.2.10" + "uuidv4": "^6.2.10", + "yup": "^0.32.9" }, "devDependencies": { "@graphql-codegen/cli": "^1.21.5", diff --git a/src/components/common/ButtonCommon/ButtonCommon.tsx b/src/components/common/ButtonCommon/ButtonCommon.tsx index 7261d6ff6..862adf71d 100644 --- a/src/components/common/ButtonCommon/ButtonCommon.tsx +++ b/src/components/common/ButtonCommon/ButtonCommon.tsx @@ -3,38 +3,51 @@ import React, { memo } from 'react' import s from './ButtonCommon.module.scss' interface Props { - children?: React.ReactNode, - type?: 'primary' | 'light' | 'ghost' | 'lightBorderNone', - size?: 'default' | 'large' | 'small', - icon?: React.ReactNode, - isIconSuffix?: boolean, - loading?: boolean, - disabled?: boolean, - onClick?: () => void, + children?: React.ReactNode + type?: 'primary' | 'light' | 'ghost' | 'lightBorderNone' + HTMLType?: "submit" | "button" | "reset" + size?: 'default' | 'large' | 'small' + icon?: React.ReactNode + isIconSuffix?: boolean + loading?: boolean + disabled?: boolean + onClick?: () => void } -const ButtonCommon = memo(({ type = 'primary', size = 'default', loading = false, isIconSuffix = false, - icon, disabled, children, onClick }: Props) => { +const ButtonCommon = memo( + ({ + type = 'primary', + HTMLType, + size = 'default', + loading = false, + isIconSuffix = false, + icon, + disabled, + children, + onClick, + }: Props) => { return ( - + disabled={disabled || loading} + onClick={onClick} + type={HTMLType} + > +
+ {icon && {icon}} + {children} +
+ ) -}) + } +) +ButtonCommon.displayName = 'ButtonCommon' export default ButtonCommon diff --git a/src/components/common/InputCommon/InputCommon.module.scss b/src/components/common/InputCommon/InputCommon.module.scss index 5471b2169..b62048bb4 100644 --- a/src/components/common/InputCommon/InputCommon.module.scss +++ b/src/components/common/InputCommon/InputCommon.module.scss @@ -1,100 +1,5 @@ -@import "../../../styles/utilities"; +@import "../../../styles/form"; .inputWrap { - .inputInner { - @apply flex items-center relative; - .icon { - @apply absolute flex justify-center items-center; - content: ""; - left: 1.6rem; - margin-right: 1.6rem; - svg path { - fill: currentColor; - } - } - .icon + .inputCommon { - padding-left: 4.8rem; - } - - .inputCommon { - @apply block w-full transition-all duration-200 bg-white; - border-radius: .8rem; - padding: 1.6rem; - border: 1px solid var(--border-line); - &:hover, - &:focus, - &:active { - outline: none; - border: 1px solid var(--primary); - @apply shadow-md; - } - - &::placeholder { - @apply text-label; - } - } - - &.preserve { - @apply flex-row-reverse; - .icon { - left: unset; - right: 1.6rem; - margin-left: 1.6rem; - margin-right: 0; - svg path { - fill: var(--text-label); - } - } - .icon + .inputCommon { - padding-left: 1.6rem; - padding-right: 4.8rem; - } - } - &.success { - .icon { - svg path { - fill: var(--primary); - } - } - } - - &.error { - .icon { - svg path { - fill: var(--negative); - } - } - input { - border-color: var(--negative) !important; - } - } - } - .errorMessage { - @apply caption; - color: var(--negative); - margin-top: 0.4rem; - } - - &.custom { - @apply shape-common; - .inputCommon { - border: none; - background: var(--background-gray); - &:hover, - &:focus, - &:active { - @apply shadow-md; - border: none; - } - } - } - &.bgTransparent { - .inputCommon { - background: rgb(227, 242, 233, 0.3); - color: var(--white); - &::placeholder { - color: var(--white); - } - } - } + @extend .formInputWrap; } diff --git a/src/components/common/InputCommon/InputCommon.tsx b/src/components/common/InputCommon/InputCommon.tsx index 7ef9d886f..2300e9b80 100644 --- a/src/components/common/InputCommon/InputCommon.tsx +++ b/src/components/common/InputCommon/InputCommon.tsx @@ -1,95 +1,127 @@ -import classNames from 'classnames'; -import React, { forwardRef, useImperativeHandle, useMemo, useRef } from 'react'; -import { IconCheck, IconError } from 'src/components/icons'; -import { KEY } from 'src/utils/constanst.utils'; -import s from './InputCommon.module.scss'; +import classNames from 'classnames' +import React, { forwardRef, useImperativeHandle, useMemo, useRef } from 'react' +import { IconCheck, IconError } from 'src/components/icons' +import { KEY } from 'src/utils/constanst.utils' +import s from './InputCommon.module.scss' type Ref = { - focus: () => void - getValue: () => string | number -} | null; + focus: () => void + getValue: () => string | number +} | null interface Props { - children?: React.ReactNode, - value?: string | number, - placeholder?: string, - type?: 'text' | 'number' | 'email' | 'password', - styleType?: 'default' | 'custom', - backgroundTransparent?: boolean, - icon?: React.ReactNode, - isIconSuffix?: boolean, - isShowIconSuccess?: boolean, - error?: string, - onChange?: (value: string | number) => void, - onEnter?: (value: string | number) => void, + children?: React.ReactNode + value?: string | number + placeholder?: string + type?: 'text' | 'number' | 'email' | 'password' + styleType?: 'default' | 'custom' + backgroundTransparent?: boolean + icon?: React.ReactNode + isIconSuffix?: boolean + isShowIconSuccess?: boolean + error?: string + onChange?: (value: string | number) => void + onChangeEvent?: (e: React.ChangeEvent) => void + onBlur?: (e: any) => void + onEnter?: (value: string | number) => void } -const InputCommon = forwardRef(({ value, placeholder, type, styleType = 'default', icon, backgroundTransparent = false, - isIconSuffix, isShowIconSuccess, error, - onChange, onEnter }: Props, ref) => { - const inputElementRef = useRef(null); +const InputCommon = forwardRef( + ( + { + value, + placeholder, + type, + styleType = 'default', + icon, + backgroundTransparent = false, + isIconSuffix, + isShowIconSuccess, + error, + onChange, + onChangeEvent, + onEnter, + onBlur, + }: Props, + ref + ) => { + const inputElementRef = useRef(null) const iconElement = useMemo(() => { - if (error) { - return - } else if (isShowIconSuccess) { - return - } else if (icon) { - return {icon} - } - return <> + if (error) { + return ( + + {' '} + + ) + } else if (isShowIconSuccess) { + return ( + + {' '} + + ) + } else if (icon) { + return {icon} + } + return <> }, [icon, error, isShowIconSuccess]) useImperativeHandle(ref, () => ({ - focus: () => { - inputElementRef.current?.focus(); - }, - getValue: () => { - const value = inputElementRef.current?.value || '' - return value - } - })); + focus: () => { + inputElementRef.current?.focus() + }, + getValue: () => { + const value = inputElementRef.current?.value || '' + return value + }, + })) const handleChange = (e: React.ChangeEvent) => { + if (onChangeEvent) { + onChangeEvent(e) + } else { onChange && onChange(e.target.value) + } } const handleKeyDown = (e: any) => { - if (e.key === KEY.ENTER && onEnter) { - const value = inputElementRef.current?.value || '' - onEnter(value) - } + if (e.key === KEY.ENTER && onEnter) { + const value = inputElementRef.current?.value || '' + onEnter(value) + } } return ( -
-
- {iconElement} - -
- { - error &&
{error}
- } +
+
+ {iconElement} +
+ {error &&
{error}
} +
) + } +) -}) - +InputCommon.displayName = 'InputCommon' export default InputCommon diff --git a/src/components/common/InputFiledInForm/InputFiledInForm.module.scss b/src/components/common/InputFiledInForm/InputFiledInForm.module.scss new file mode 100644 index 000000000..b62048bb4 --- /dev/null +++ b/src/components/common/InputFiledInForm/InputFiledInForm.module.scss @@ -0,0 +1,5 @@ +@import "../../../styles/form"; + +.inputWrap { + @extend .formInputWrap; +} diff --git a/src/components/common/InputFiledInForm/InputFiledInForm.tsx b/src/components/common/InputFiledInForm/InputFiledInForm.tsx new file mode 100644 index 000000000..4b848e244 --- /dev/null +++ b/src/components/common/InputFiledInForm/InputFiledInForm.tsx @@ -0,0 +1,94 @@ +import classNames from 'classnames' +import { Field } from 'formik' +import React, { useMemo, useRef } from 'react' +import { IconCheck, IconError } from 'src/components/icons' +import { KEY } from 'src/utils/constanst.utils' +import s from './InputFiledInForm.module.scss' + +interface Props { + placeholder?: string + type?: 'text' | 'number' | 'email' | 'password' + styleType?: 'default' | 'custom' + backgroundTransparent?: boolean + icon?: React.ReactNode + isIconSuffix?: boolean + isShowIconSuccess?: boolean + name: string + error?: string + onChange?: (value: string | number) => void + onChangeEvent?: (e: React.ChangeEvent) => void + onBlur?: (e: any) => void + onEnter?: (value: string | number) => void +} + +const InputFiledInForm = ({ + name, + placeholder, + type, + styleType = 'default', + icon, + backgroundTransparent = false, + isIconSuffix = true, + isShowIconSuccess, + error, + onEnter, +}: Props) => { + const inputElementRef = useRef(null) + + const iconElement = useMemo(() => { + if (error) { + return ( + + {' '} + + ) + } else if (isShowIconSuccess) { + return ( + + {' '} + + ) + } else if (icon) { + return {icon} + } + return <> + }, [icon, error, isShowIconSuccess]) + + const handleKeyDown = (e: any) => { + if (e.key === KEY.ENTER && onEnter) { + const value = inputElementRef.current?.value || '' + onEnter(value) + } + } + + return ( +
+
+ {iconElement} + +
+ {error &&
{error}
} +
+ ) +} + +InputFiledInForm.displayName = 'InputFiledInForm' +export default InputFiledInForm diff --git a/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.module.scss b/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.module.scss new file mode 100644 index 000000000..598620891 --- /dev/null +++ b/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.module.scss @@ -0,0 +1,10 @@ +.iconPassword { + all: unset; + cursor: pointer; + &:focus { + outline: none; + } + &:focus-visible { + outline: 2px solid var(--text-active); + } +} diff --git a/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.tsx b/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.tsx new file mode 100644 index 000000000..3cdc48353 --- /dev/null +++ b/src/components/common/InputPasswordFiledInForm/InputPasswordFiledInForm.tsx @@ -0,0 +1,49 @@ +import React, { useState } from 'react' +import { IconPassword, IconPasswordCross } from 'src/components/icons' +import InputFiledInForm from '../InputFiledInForm/InputFiledInForm' +import s from './InputPasswordFiledInForm.module.scss' + +interface Props { + name?: string + placeholder?: string + styleType?: 'default' | 'custom' + error?: string + onChange?: (value: string | number) => void + onEnter?: (value: string | number) => void +} + +const InputPasswordFiledInForm = ({ + name = 'password', + placeholder, + styleType = 'default', + error, + onChange, + onEnter, +}: Props) => { + const [isShowPassword, setIsShowPassword] = useState(false) + const toggleShowPassword = (e: React.MouseEvent) => { + e.stopPropagation() + e.preventDefault() + setIsShowPassword(!isShowPassword) + } + + return ( + + {isShowPassword ? : } + + } + isIconSuffix={true} + onChange={onChange} + onEnter={onEnter} + /> + ) +} + +export default InputPasswordFiledInForm diff --git a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx index 81d8f5687..793218c7c 100644 --- a/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx +++ b/src/components/common/ModalAuthenticate/components/FormRegister/FormRegister.tsx @@ -1,83 +1,121 @@ import classNames from 'classnames' -import React, { useEffect, useRef, useState } from 'react' -import { ButtonCommon, Inputcommon, InputPassword } from 'src/components/common' +import { Form, Formik } from 'formik' +import React, { useEffect, useRef } from 'react' +import { + ButtonCommon, + InputFiledInForm, + InputPasswordFiledInForm +} from 'src/components/common' import { CustomInputCommon } from 'src/utils/type.utils' +import * as Yup from 'yup' import { useSignup } from '../../../../hooks' import s from '../FormAuthen.module.scss' import SocialAuthen from '../SocialAuthen/SocialAuthen' import styles from './FormRegister.module.scss' interface Props { - isHide: boolean, - onSwitch: () => void + isHide: boolean + onSwitch: () => void } +const DisplayingErrorMessagesSchema = Yup.object().shape({ + email: Yup.string().email('Your email was wrong').required('Required'), + password: Yup.string() + .matches( + /^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])((?=.*[0-9!@#$%^&*()\-_=+{};:,<.>]){1}).*$/, + 'Must contain 8 characters with at least 1 uppercase and 1 lowercase letter and either 1 number or 1 special character.' + ) + .max(30, 'Password is too long') + .required('Required'), +}) + const FormRegister = ({ onSwitch, isHide }: Props) => { - const emailRef = useRef(null) - const { loading, signup, error } = useSignup() - const [email, setEmail] = useState('') - const [password, setPassword] = useState('') + const emailRef = useRef(null) + const { loading, signup, error } = useSignup() - - useEffect(() => { - if (!isHide) { - emailRef.current?.focus() - } - }, [isHide]) - - const onSignup = () => { - // TODO: validate fields - signup({ email, password }) - // TODO: - alert("User created. Please verify your email") + useEffect(() => { + if (!isHide) { + emailRef.current?.focus() } + }, [isHide]) + const onSignup = (values: { email: string; password: string }) => { + signup({ email: values.email, password: values.password }) + // TODO: flow + alert('User created. Please verify your email') + } - useEffect(() => { - if (error) { - alert(error.message) - } - }, [error]) + useEffect(() => { + if (error) { + alert(error.message) + } + }, [error]) - return ( -
-
-
- setEmail(val.toString())} - /> - setPassword(val.toString())} - /> - -
- Must contain 8 characters with at least 1 uppercase and 1 lowercase letter and either 1 number or 1 special character. -
+ return ( +
+
+
+ + {({ errors, touched }) => ( +
+
+ + +
+ Must contain 8 characters with at least 1 uppercase and 1 + lowercase letter and either 1 number or 1 special character. +
- - Create Account - + + Create Account +
- -
- Already an account? - -
-
-
- ) + + )} + +
+ +
+ Already an account? + +
+
+
+ ) } -export default FormRegister \ No newline at end of file +export default FormRegister diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 7b82399f6..0edc064cc 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -1,3 +1,4 @@ +import { InputFiledInForm } from 'src/components/common/InputFiledInForm/InputFiledInForm'; export { default as ButtonCommon } from './ButtonCommon/ButtonCommon' export { default as Layout } from './Layout/Layout' export { default as CarouselCommon } from './CarouselCommon/CarouselCommon' @@ -47,4 +48,6 @@ export { default as StaticImage} from './StaticImage/StaticImage' export { default as EmptyCommon} from './EmptyCommon/EmptyCommon' export { default as CustomShapeSvg} from './CustomShapeSvg/CustomShapeSvg' export { default as RecommendedRecipes} from './RecommendedRecipes/RecommendedRecipes' -export { default as LayoutCheckout} from './LayoutCheckout/LayoutCheckout' \ No newline at end of file +export { default as LayoutCheckout} from './LayoutCheckout/LayoutCheckout' +export { default as InputPasswordFiledInForm} from './InputPasswordFiledInForm/InputPasswordFiledInForm' +export { default as InputFiledInForm} from './InputFiledInForm/InputFiledInForm' diff --git a/src/styles/_form.scss b/src/styles/_form.scss new file mode 100644 index 000000000..0ec3b4a96 --- /dev/null +++ b/src/styles/_form.scss @@ -0,0 +1,100 @@ +@import './utilities'; + +.formInputWrap { + .inputInner { + @apply flex items-center relative; + .icon { + @apply absolute flex justify-center items-center; + content: ""; + left: 1.6rem; + margin-right: 1.6rem; + svg path { + fill: currentColor; + } + } + .icon + input { + padding-left: 4.8rem; + } + + input { + @apply block w-full transition-all duration-200 bg-white; + border-radius: .8rem; + padding: 1.6rem; + border: 1px solid var(--border-line); + &:hover, + &:focus, + &:active { + outline: none; + border: 1px solid var(--primary); + @apply shadow-md; + } + + &::placeholder { + @apply text-label; + } + } + + &.preserve { + @apply flex-row-reverse; + .icon { + left: unset; + right: 1.6rem; + margin-left: 1.6rem; + margin-right: 0; + svg path { + fill: var(--text-label); + } + } + .icon + input { + padding-left: 1.6rem; + padding-right: 4.8rem; + } + } + &.success { + .icon { + svg path { + fill: var(--primary); + } + } + } + + &.error { + .icon { + svg path { + fill: var(--negative); + } + } + input { + border-color: var(--negative) !important; + } + } + } + .errorMessage { + @apply caption; + color: var(--negative); + margin-top: 0.4rem; + } + + &.custom { + @apply shape-common; + input { + border: none; + background: var(--background-gray); + &:hover, + &:focus, + &:active { + @apply shadow-md; + border: none; + } + } + } + &.bgTransparent { + input { + background: rgb(227, 242, 233, 0.3); + color: var(--white); + &::placeholder { + color: var(--white); + } + } + } + } \ No newline at end of file diff --git a/src/styles/main.scss b/src/styles/main.scss index 51391b33f..e742ca4be 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -6,4 +6,5 @@ @import "~tailwindcss/utilities"; @import './utilities'; +@import './form'; @import './pages' diff --git a/yarn.lock b/yarn.lock index b69068411..5964ce61a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -445,7 +445,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.0": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.14.0": version "7.15.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== @@ -1213,6 +1213,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== +"@types/lodash@^4.14.165": + version "4.14.175" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.175.tgz#b78dfa959192b01fae0ad90e166478769b215f45" + integrity sha512-XmdEOrKQ8a1Y/yxQFOMbC47G/V2VDO1GvMRnl4O75M4GW/abC5tnfzadQYkqEveqRM1dEJGFFegfPNA2vvx2iw== + "@types/lru-cache@4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-4.1.1.tgz#b2d87a5e3df8d4b18ca426c5105cd701c2306d40" @@ -2572,6 +2577,11 @@ deepmerge@4.2.2, deepmerge@^4.0.0, deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +deepmerge@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" + integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== + defer-to-connect@^1.0.1: version "1.1.3" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" @@ -3279,6 +3289,19 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +formik@^2.2.9: + version "2.2.9" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0" + integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA== + dependencies: + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.21" + lodash-es "^4.17.21" + react-fast-compare "^2.0.1" + tiny-warning "^1.0.2" + tslib "^1.10.0" + fraction.js@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" @@ -3595,6 +3618,13 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -4415,6 +4445,11 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash-es@^4.17.15, lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -4752,6 +4787,11 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + nanoid@^3.1.23: version "3.1.25" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" @@ -5795,6 +5835,11 @@ prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.8.1" +property-expr@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + public-encrypt@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" @@ -5921,6 +5966,11 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-fast-compare@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-fast-compare@^3.0.1: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -5936,7 +5986,7 @@ react-is@17.0.2: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== -react-is@^16.8.1: +react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -6878,6 +6928,11 @@ timers-browserify@2.0.12, timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + title-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" @@ -6926,6 +6981,11 @@ toidentifier@1.0.0: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + totalist@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" @@ -6970,7 +7030,7 @@ tsconfig-paths@^3.11.0, tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -7419,3 +7479,16 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yup@^0.32.9: + version "0.32.9" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872" + integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg== + dependencies: + "@babel/runtime" "^7.10.5" + "@types/lodash" "^4.14.165" + lodash "^4.17.20" + lodash-es "^4.17.15" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2"