'use client';
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { useAdaptivity } from '../../hooks/useAdaptivity';
import { useExternRef } from '../../hooks/useExternRef';
import { useFocusVisibleClassName } from '../../hooks/useFocusVisibleClassName';
import { useFocusWithin } from '../../hooks/useFocusWithin';
import type { HasComponent, HasRootRef } from '../../types';
import styles from './FormField.module.css';
const sizeYClassNames = {
none: styles.sizeYNone,
compact: styles.sizeYCompact,
};
const stylesStatus = {
error: styles.statusError,
valid: styles.statusValid,
};
const iconAlignClassNames = {
center: undefined,
start: styles.iconAlignStart,
end: styles.iconAlignEnd,
};
const renderIcon = (icon: React.ReactNode, align: FieldIconsAlign, className: string) => {
return (
{icon}
);
};
export type FieldIconsAlign = 'start' | 'center' | 'end';
export interface FormFieldProps {
/**
* Статус отображения поля в форме.
*/
status?: 'default' | 'error' | 'valid';
/**
* Добавляет иконку слева.
*
* Рекомендации:
*
* - Используйте следующие размеры иконок `12` | `16` | `20` | `24` | `28`.
* - Используйте [IconButton](https://vkui.io/components/icon-button), если вам нужна иконка, реагирующая на нажатие.
*/
before?: React.ReactNode;
/**
* Вертикальное выравнивание иконки слева.
*/
beforeAlign?: FieldIconsAlign;
/**
* Добавляет иконку справа.
*
* Рекомендации:
*
* - Используйте следующие размеры иконок `12` | `16` | `20` | `24` | `28`.
* - Используйте [IconButton](https://vkui.io/components/icon-button), если вам нужна иконка, реагируюущая на нажатие.
*/
after?: React.ReactNode;
/**
* Вертикальное выравнивание иконки справа.
*/
afterAlign?: FieldIconsAlign;
/**
* Режим отображения.
*
* - `default` — показывает фон, обводку и, при наличии, текст-подсказку.
* - `plain` — показывает только текст-подсказку.
*/
mode?: 'default' | 'plain';
/**
* Максимальная высота поля.
*/
maxHeight?: number;
}
export interface FormFieldOwnProps
extends React.AllHTMLAttributes,
HasRootRef,
HasComponent,
FormFieldProps {
/**
* Блокировка взаимодействия с компонентом.
*/
disabled?: boolean;
}
/**
* @see https://vkui.io/components/form-field
*/
export const FormField = ({
Component = 'span',
status = 'default',
children,
getRootRef,
before,
after,
beforeAlign = 'center',
afterAlign = 'center',
disabled,
mode = 'default',
className,
maxHeight,
style,
...restProps
}: FormFieldOwnProps): React.ReactNode => {
const elRef = useExternRef(getRootRef);
const { sizeY = 'none' } = useAdaptivity();
const [hover, setHover] = React.useState(false);
const focusWithin = useFocusWithin(elRef);
const focusVisibleClassNames = useFocusVisibleClassName({
focusVisible: focusWithin,
mode: styles.focusVisible,
});
const handleMouseEnter = (e: MouseEvent) => {
e.stopPropagation();
setHover(true);
};
const handleMouseLeave = (e: MouseEvent) => {
e.stopPropagation();
setHover(false);
};
return (
{before && renderIcon(before, beforeAlign, styles.before)}
{children}
{after &&
renderIcon(after, afterAlign, classNames(styles.after, 'vkuiInternalFormField__after'))}
);
};