diff --git a/src/lib/core/components/Form/constants.ts b/src/lib/core/components/Form/constants.ts index 7a6a06ad..5abe77ec 100644 --- a/src/lib/core/components/Form/constants.ts +++ b/src/lib/core/components/Form/constants.ts @@ -1,3 +1,5 @@ export const OBJECT_ARRAY_FLAG = '____arr-obj'; export const OBJECT_ARRAY_CNT = '____arr-obj-cnt'; + +export const SPEC_TYPE_FOR_GENERATE_BUTTON = ['base', 'password', 'textarea']; diff --git a/src/lib/core/components/Form/utils/common.ts b/src/lib/core/components/Form/utils/common.ts index dfc940b2..3f7b543a 100644 --- a/src/lib/core/components/Form/utils/common.ts +++ b/src/lib/core/components/Form/utils/common.ts @@ -1,8 +1,9 @@ import _ from 'lodash'; import {SpecTypes} from '../../../constants'; -import {FormValue, ObjectValue} from '../../../types'; -import {OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG} from '../constants'; +import {isStringSpec} from '../../../helpers'; +import {FormValue, ObjectValue, Spec} from '../../../types'; +import {OBJECT_ARRAY_CNT, OBJECT_ARRAY_FLAG, SPEC_TYPE_FOR_GENERATE_BUTTON} from '../constants'; export const isCorrectConfig = (candidate: any) => Object.values(SpecTypes).every( @@ -68,3 +69,8 @@ export const transformArrOut = name[name.length - 1] === '>'; + +export const withGenerateButton = (spec: Spec) => + isStringSpec(spec) && + SPEC_TYPE_FOR_GENERATE_BUTTON.includes(spec.viewSpec.type) && + spec.viewSpec.generateRandomValueButton; diff --git a/src/lib/kit/components/ErrorWrapper/ErrorWrapper.tsx b/src/lib/kit/components/ErrorWrapper/ErrorWrapper.tsx index 3cde3cb9..832a3b15 100644 --- a/src/lib/kit/components/ErrorWrapper/ErrorWrapper.tsx +++ b/src/lib/kit/components/ErrorWrapper/ErrorWrapper.tsx @@ -12,6 +12,7 @@ export interface ErrorWrapperProps { name: string; meta: FieldRenderProps['meta']; withoutChildErrorStyles?: boolean; + className?: string; } export const ErrorWrapper: React.FC = ({ @@ -19,6 +20,7 @@ export const ErrorWrapper: React.FC = ({ meta, withoutChildErrorStyles, children, + className, }) => { const error = React.useMemo(() => { if ((meta.touched || meta.submitFailed) && meta.error) { @@ -34,7 +36,10 @@ export const ErrorWrapper: React.FC = ({ ); return ( - + {children} {error && typeof error === 'string' ? (
{error}
diff --git a/src/lib/kit/components/Inputs/Text/Text.scss b/src/lib/kit/components/Inputs/Text/Text.scss index df45fa19..bb0bd3e1 100644 --- a/src/lib/kit/components/Inputs/Text/Text.scss +++ b/src/lib/kit/components/Inputs/Text/Text.scss @@ -2,4 +2,8 @@ .#{$ns}text { display: flex; + + &__button { + --yc-button-background-color-hover: transparent; + } } diff --git a/src/lib/kit/components/Inputs/Text/Text.tsx b/src/lib/kit/components/Inputs/Text/Text.tsx index e6d23fa6..40c5b8a5 100644 --- a/src/lib/kit/components/Inputs/Text/Text.tsx +++ b/src/lib/kit/components/Inputs/Text/Text.tsx @@ -1,11 +1,11 @@ import React from 'react'; -import {TextInput} from '@gravity-ui/uikit'; +import {Copy, CopyCheck, Eye, EyeSlash} from '@gravity-ui/icons'; +import {Button, CopyToClipboard, CopyToClipboardStatus, Icon, TextInput} from '@gravity-ui/uikit'; import _ from 'lodash'; -import {FieldRenderProps, NumberInputProps, StringInputProps, isStringSpec} from '../../../../core'; +import {FieldRenderProps, NumberInputProps, StringInputProps} from '../../../../core'; import {block} from '../../../utils'; -import {GenerateRandomValueButton} from '../../GenerateRandomValueButton'; import './Text.scss'; @@ -13,6 +13,7 @@ const b = block('text'); export const Text = ({name, input, spec}: T) => { const {value, onBlur, onChange, onFocus} = input; + const [hideValue, setHideValue] = React.useState(spec.viewSpec.type === 'password'); const handleChange = React.useCallback( (value: string) => { @@ -29,45 +30,58 @@ export const Text = ({name, input return 'text'; }, [spec.viewSpec.type]); - const textInput = React.useMemo( - () => ( - - ), - [ - handleChange, - name, - onBlur, - onFocus, - spec.viewSpec.disabled, - spec.viewSpec.placeholder, - type, - value, - ], - ); + const additionalRightContent = React.useMemo(() => { + if (type === 'password') { + const onClick = () => { + setHideValue((hideValue) => !hideValue); + }; - const content = React.useMemo(() => { - if (isStringSpec(spec)) { return (
- {textInput} - + {input.value ? ( + + {(state) => ( + + )} + + ) : null} +
); } - return {textInput}; - }, [handleChange, spec, textInput]); + return undefined; + }, [hideValue, input.value, type, value]); - return {content}; + return ( + + ); }; diff --git a/src/lib/kit/components/Inputs/TextArea/TextArea.scss b/src/lib/kit/components/Inputs/TextArea/TextArea.scss deleted file mode 100644 index c137815f..00000000 --- a/src/lib/kit/components/Inputs/TextArea/TextArea.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import '../../../styles/variables'; - -.#{$ns}text-area { - display: flex; - justify-content: flex-start; -} diff --git a/src/lib/kit/components/Inputs/TextArea/TextArea.tsx b/src/lib/kit/components/Inputs/TextArea/TextArea.tsx index a5b92482..4749290a 100644 --- a/src/lib/kit/components/Inputs/TextArea/TextArea.tsx +++ b/src/lib/kit/components/Inputs/TextArea/TextArea.tsx @@ -3,31 +3,22 @@ import React from 'react'; import {TextArea as TextAreaBase} from '@gravity-ui/uikit'; import {StringInput} from '../../../../core'; -import {block} from '../../../utils'; -import {GenerateRandomValueButton} from '../../GenerateRandomValueButton'; - -import './TextArea.scss'; - -const b = block('text-area'); export const TextArea: StringInput = ({name, input, spec}) => { const {value, onBlur, onChange, onFocus} = input; return ( -
- - -
+ ); }; diff --git a/src/lib/kit/components/Layouts/Row/Row.scss b/src/lib/kit/components/Layouts/Row/Row.scss index b558600a..b47fad29 100644 --- a/src/lib/kit/components/Layouts/Row/Row.scss +++ b/src/lib/kit/components/Layouts/Row/Row.scss @@ -10,11 +10,6 @@ margin-bottom: 0; } - &_extra-width { - width: 533px; - max-width: 533px; - } - &__left { width: 180px; min-height: 28px; @@ -90,4 +85,8 @@ &__required-mark { color: var(--yc-color-text-danger); } + + &__error-wrapper { + min-width: 100%; + } } diff --git a/src/lib/kit/components/Layouts/Row/Row.tsx b/src/lib/kit/components/Layouts/Row/Row.tsx index 0b91ef74..97077931 100644 --- a/src/lib/kit/components/Layouts/Row/Row.tsx +++ b/src/lib/kit/components/Layouts/Row/Row.tsx @@ -3,16 +3,19 @@ import React from 'react'; import {HelpPopover} from '@gravity-ui/components'; import {TrashBin} from '@gravity-ui/icons'; import {Button, Icon} from '@gravity-ui/uikit'; +import _ from 'lodash'; import { FieldValue, LayoutProps, Spec, + StringSpec, isArrayItem, isArraySpec, isObjectSpec, + withGenerateButton, } from '../../../../core'; -import {ErrorWrapper} from '../../../components'; +import {ErrorWrapper, GenerateRandomValueButton} from '../../../components'; import {block} from '../../../utils'; import './Row.scss'; @@ -32,9 +35,10 @@ const RowBase = ({ children, }: LayoutProps & RowProps) => { const arrayItem = React.useMemo(() => isArrayItem(name), [name]); + const generateButton = React.useMemo(() => withGenerateButton(spec), [spec]); return ( -
+
@@ -58,9 +62,16 @@ const RowBase = ({ name={name} meta={meta} withoutChildErrorStyles={isArraySpec(spec) || isObjectSpec(spec)} + className={b('error-wrapper')} > {children} + {generateButton ? ( + void} + /> + ) : null} {arrayItem ? (
); diff --git a/src/stories/StringPassword.stories.tsx b/src/stories/StringPassword.stories.tsx index 62901564..76c7b9c8 100644 --- a/src/stories/StringPassword.stories.tsx +++ b/src/stories/StringPassword.stories.tsx @@ -13,7 +13,7 @@ export default { const baseSpec: StringSpec = { type: SpecTypes.String, - pattern: '/[a-z]{6}/', + pattern: '^[-_a-zA-Z0-9/.]+$', patternError: 'Pattern error', viewSpec: { type: 'password',