import type { CSSProperties, ButtonHTMLAttributes, ChangeEventHandler, Dispatch, ReactNode, ReactElement, Ref, RefObject, MouseEvent, UIEvent } from 'react'; import type { SafeExtract, NeverProps } from '../../types'; import type { RequiredProps, LabelProps, HintProps } from '../TextField/TextField.types'; import { FocusedPathState, TreePathState, TreePathAction } from './reducers'; import type { ValueToCheckedMapType } from './hooks/usePathMaps'; export type SelectPlacementBasic = 'top' | 'bottom' | 'right' | 'left'; export type SelectPlacement = 'top' | 'bottom' | 'right' | 'left' | 'auto'; export type SelectValue = string | string[]; export type SelectCheckedState = boolean | 'done' | 'dot' | 'indeterminate'; export type { RequiredProps, HintProps }; export type ItemOption = { /** * Значение у item. */ value: string; /** * Метка-подпись к item. */ label: string; /** * Сторона открытия вложенного выпадающего списка относительно текущего элемента. * @default right */ placement?: SelectPlacement | Array; /** * Список дочерних items. */ items?: ItemOption[]; /** * Item не активен. */ disabled?: boolean; /** * Слот для контента слева. */ contentLeft?: ReactNode; /** * Слот для контента справа. */ contentRight?: ReactNode; /** * Classname для item. */ className?: string; /** * Максимальная высота дочернего выпадающего списка. */ listMaxHeight?: CSSProperties['height']; }; export type ItemOptionTransformed = Omit & { items?: ItemOptionTransformed[]; parent?: ItemOptionTransformed | null; }; export type SelectAllProps = { checked?: boolean; indeterminate?: boolean; label?: string; onClick?: () => void; sticky?: boolean; }; type TextfieldLikeTargetProps = { /** * Стиль селекта: button-like или textfield-like. * @default textfield-like */ target?: 'textfield-like'; /** * Слот для контента слева. */ contentLeft?: ReactNode; /** * Слот для контента справа. */ contentRight?: ReactElement; /** * Placeholder. */ placeholder?: string; /** * Вспомогательный текст снизу слева для поля ввода. */ helperText?: string; /** * Внешний вид chip. * @default default */ chipType?: 'default' | 'text'; /** * Область, по которой происходит нажатие. * @default full */ chipClickArea?: 'full' | 'close-icon'; } & RequiredProps & HintProps & LabelProps; type ButtonLikeTargetProps = { target: 'button-like'; /** * Метка-подпись к элементу */ label?: string; contentLeft?: never; contentRight?: never; placeholder?: string; helperText?: never; keepPlaceholder?: never; chipType?: never; chipClickArea?: never; } & NeverProps>; type Target = TextfieldLikeTargetProps | ButtonLikeTargetProps; type SelectSingleProps = { multiselect?: false; value?: string; defaultValue?: string; onChange?: (value: string, item: K | null) => void; /** * Если включено - будет выведено общее количество выбранных элементов вместо перечисления. * @default false */ isTargetAmount?: false; /** * Callback для кастомной настройки значения в селекте. */ renderTarget?: (value: K, opened?: boolean) => ReactNode; selectAllOptions?: never; }; type SelectMultiselectProps = { multiselect: true; value?: string[]; defaultValue?: string[]; onChange?: (value: string[], item: K | null) => void; isTargetAmount?: true; renderTarget?: (value: K[], opened?: boolean) => ReactNode; selectAllOptions?: SelectAllProps; }; type SelectSingleNativeProps = Omit, 'onChange' | 'value'> & { /** * Имя поля. Используется для нативной формы и react-hook-form register. */ name: string; value?: never; onChange?: ChangeEventHandler; }; type SelectMultiselectNativeProps = Omit, 'onChange' | 'value'> & { name: string; value?: never; onChange?: ChangeEventHandler; }; /** * Описание режимов работы компонента: * * 1. Если value !== null && value !== undefined, компонент controlled. * name не включает native-режим, onChange вызывается как (value, item). * 2. Если value нет и name есть, компонент uncontrolled внутри, * но изменения дополнительно прокидываются в hidden