You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
5.9 KiB
137 lines
5.9 KiB
/**
|
|
* To match accessibility requirement, we always provide an input in the component.
|
|
* Other element will not set `tabIndex` to avoid `onBlur` sequence problem.
|
|
* For focused select, we set `aria-live="polite"` to update the accessibility content.
|
|
*
|
|
* ref:
|
|
* - keyboard: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role#Keyboard_interactions
|
|
*/
|
|
import * as React from 'react';
|
|
import { RenderNode, Mode, RenderDOMFunc } from './interface';
|
|
import { GetLabeledValue, FilterOptions, FilterFunc, DefaultValueType, RawValueType, LabelValueType, Key, FlattenOptionsType, SingleType, OnClear, SelectSource, CustomTagProps } from './interface/generator';
|
|
import { OptionListProps, RefOptionListProps } from './OptionList';
|
|
export interface RefSelectProps {
|
|
focus: () => void;
|
|
blur: () => void;
|
|
}
|
|
export interface SelectProps<OptionsType extends object[], ValueType> extends React.AriaAttributes {
|
|
prefixCls?: string;
|
|
id?: string;
|
|
className?: string;
|
|
style?: React.CSSProperties;
|
|
options?: OptionsType;
|
|
children?: React.ReactNode;
|
|
mode?: Mode;
|
|
value?: ValueType;
|
|
defaultValue?: ValueType;
|
|
labelInValue?: boolean;
|
|
inputValue?: string;
|
|
searchValue?: string;
|
|
optionFilterProp?: string;
|
|
/**
|
|
* In Select, `false` means do nothing.
|
|
* In TreeSelect, `false` will highlight match item.
|
|
* It's by design.
|
|
*/
|
|
filterOption?: boolean | FilterFunc<OptionsType[number]>;
|
|
showSearch?: boolean;
|
|
autoClearSearchValue?: boolean;
|
|
onSearch?: (value: string) => void;
|
|
allowClear?: boolean;
|
|
clearIcon?: React.ReactNode;
|
|
showArrow?: boolean;
|
|
inputIcon?: RenderNode;
|
|
removeIcon?: React.ReactNode;
|
|
menuItemSelectedIcon?: RenderNode;
|
|
open?: boolean;
|
|
defaultOpen?: boolean;
|
|
listHeight?: number;
|
|
listItemHeight?: number;
|
|
dropdownStyle?: React.CSSProperties;
|
|
dropdownClassName?: string;
|
|
dropdownMatchSelectWidth?: boolean | number;
|
|
virtual?: boolean;
|
|
dropdownRender?: (menu: React.ReactElement) => React.ReactElement;
|
|
dropdownAlign?: any;
|
|
animation?: string;
|
|
transitionName?: string;
|
|
getPopupContainer?: RenderDOMFunc;
|
|
direction?: string;
|
|
disabled?: boolean;
|
|
loading?: boolean;
|
|
autoFocus?: boolean;
|
|
defaultActiveFirstOption?: boolean;
|
|
notFoundContent?: React.ReactNode;
|
|
placeholder?: React.ReactNode;
|
|
backfill?: boolean;
|
|
getInputElement?: () => JSX.Element;
|
|
optionLabelProp?: string;
|
|
maxTagTextLength?: number;
|
|
maxTagCount?: number;
|
|
maxTagPlaceholder?: React.ReactNode | ((omittedValues: LabelValueType[]) => React.ReactNode);
|
|
tokenSeparators?: string[];
|
|
tagRender?: (props: CustomTagProps) => React.ReactElement;
|
|
showAction?: ('focus' | 'click')[];
|
|
tabIndex?: number;
|
|
onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;
|
|
onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
|
|
onPopupScroll?: React.UIEventHandler<HTMLDivElement>;
|
|
onDropdownVisibleChange?: (open: boolean) => void;
|
|
onSelect?: (value: SingleType<ValueType>, option: OptionsType[number]) => void;
|
|
onDeselect?: (value: SingleType<ValueType>, option: OptionsType[number]) => void;
|
|
onInputKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
|
onClick?: React.MouseEventHandler;
|
|
onChange?: (value: ValueType, option: OptionsType[number] | OptionsType) => void;
|
|
onBlur?: React.FocusEventHandler<HTMLElement>;
|
|
onFocus?: React.FocusEventHandler<HTMLElement>;
|
|
onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
|
|
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
|
|
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
|
|
choiceTransitionName?: string;
|
|
/**
|
|
* Only used in current version for internal event process.
|
|
* Do not use in production environment.
|
|
*/
|
|
internalProps?: {
|
|
mark?: string;
|
|
onClear?: OnClear;
|
|
skipTriggerChange?: boolean;
|
|
skipTriggerSelect?: boolean;
|
|
onRawSelect?: (value: RawValueType, option: OptionsType[number], source: SelectSource) => void;
|
|
onRawDeselect?: (value: RawValueType, option: OptionsType[number], source: SelectSource) => void;
|
|
};
|
|
}
|
|
export interface GenerateConfig<OptionsType extends object[]> {
|
|
prefixCls: string;
|
|
components: {
|
|
optionList: React.ForwardRefExoticComponent<React.PropsWithoutRef<Omit<OptionListProps<OptionsType>, 'options'> & {
|
|
options: OptionsType;
|
|
}> & React.RefAttributes<RefOptionListProps>>;
|
|
};
|
|
/** Convert jsx tree into `OptionsType` */
|
|
convertChildrenToData: (children: React.ReactNode) => OptionsType;
|
|
/** Flatten nest options into raw option list */
|
|
flattenOptions: (options: OptionsType, props: any) => FlattenOptionsType<OptionsType>;
|
|
/** Convert single raw value into { label, value } format. Will be called by each value */
|
|
getLabeledValue: GetLabeledValue<FlattenOptionsType<OptionsType>>;
|
|
filterOptions: FilterOptions<OptionsType>;
|
|
findValueOption: ((values: RawValueType[], options: FlattenOptionsType<OptionsType>) => OptionsType) | ((values: RawValueType[], options: FlattenOptionsType<OptionsType>, info?: {
|
|
prevValueOptions?: OptionsType[];
|
|
}) => OptionsType);
|
|
/** Check if a value is disabled */
|
|
isValueDisabled: (value: RawValueType, options: FlattenOptionsType<OptionsType>) => boolean;
|
|
warningProps?: (props: any) => void;
|
|
fillOptionsWithMissingValue?: (options: OptionsType, value: DefaultValueType, optionLabelProp: string, labelInValue: boolean) => OptionsType;
|
|
omitDOMProps?: (props: object) => object;
|
|
}
|
|
/**
|
|
* This function is in internal usage.
|
|
* Do not use it in your prod env since we may refactor this.
|
|
*/
|
|
export default function generateSelector<OptionsType extends {
|
|
value?: RawValueType;
|
|
label?: React.ReactNode;
|
|
key?: Key;
|
|
disabled?: boolean;
|
|
}[]>(config: GenerateConfig<OptionsType>): React.ForwardRefExoticComponent<SelectProps<OptionsType, DefaultValueType> & React.RefAttributes<RefSelectProps>>;
|