ant-design/components/auto-complete/index.tsx
二货机器人 2ea28af6ed
Virtual select component (#18658)
* init

* fix firefox

* add active style

* adjust arrow style

* update select

* update icon logic

* render empty

* init multiple

* fix ff display style

* sync font size

* adjust padding style

* add padding

* padding it

* hotfix of chrome

* single sm

* multiple size

* update option group style

* update snapshot

* clean up transition

* rm combobox in ts define

* auto complete init

* fix auto option def

* update demo

* update demo

* update uncertain demo

* update demo

* warning if user set `size` on AutoComplete

* add debug demo

* updat demo

* update demo of disabled

* update snapshot

* rm useless test

* fix pagination test

* fix Table test

* fix calendar test case

* fix calendar test case

* adjust style

* add big data demo

* support clean up

* fix ts define

* fix lint

* fix demo lint

* fix style lint fix

* rm useless deps

* update snapshot

* stop mock

* add space
2019-09-12 20:15:17 +08:00

131 lines
4.0 KiB
TypeScript
Executable File

/**
* TODO: 4.0
* - remove `dataSource`
* - `size` not work with customizeInput
* - customizeInput not feedback `ENTER` key since accessibility enhancement
*/
import * as React from 'react';
import toArray from 'rc-util/lib/Children/toArray';
import { SelectProps as RcSelectProps } from 'rc-select';
import classNames from 'classnames';
import omit from 'omit.js';
import Select, { InternalSelectProps, OptionType } from '../select';
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
import warning from '../_util/warning';
const { Option } = Select;
const InternalSelect = Select as React.ComponentClass<RcSelectProps>;
export interface DataSourceItemObject {
value: string;
text: string;
}
export type DataSourceItemType = string | DataSourceItemObject;
export interface AutoCompleteProps
extends Omit<InternalSelectProps<string>, 'inputIcon' | 'loading' | 'mode' | 'optionLabelProp'> {
dataSource?: DataSourceItemType[];
}
function isSelectOptionOrSelectOptGroup(child: any): Boolean {
return child && child.type && (child.type.isSelectOption || child.type.isSelectOptGroup);
}
const AutoComplete: React.RefForwardingComponent<Select, AutoCompleteProps> = (props, ref) => {
const { prefixCls: customizePrefixCls, className, children, dataSource } = props;
const childNodes: React.ReactElement[] = toArray(children);
const selectRef = React.useRef<Select>();
React.useImperativeHandle<Select, Select>(ref, () => selectRef.current!);
// ============================= Input =============================
let customizeInput: React.ReactElement;
if (
childNodes.length === 1 &&
React.isValidElement(childNodes[0]) &&
!isSelectOptionOrSelectOptGroup(childNodes[0])
) {
customizeInput = childNodes[0];
}
const getInputElement = (): React.ReactElement => customizeInput;
// ============================ Options ============================
let optionChildren: React.ReactNode;
// [Legacy] convert `children` or `dataSource` into option children
if (childNodes.length && isSelectOptionOrSelectOptGroup(childNodes[0])) {
optionChildren = children;
} else {
optionChildren = dataSource
? dataSource.map(item => {
if (React.isValidElement(item)) {
return item;
}
switch (typeof item) {
case 'string':
return <Option key={item}>{item}</Option>;
case 'object':
return (
<Option key={(item as DataSourceItemObject).value}>
{(item as DataSourceItemObject).text}
</Option>
);
default:
throw new Error('AutoComplete[dataSource] only supports type `string[] | Object[]`.');
}
})
: [];
}
// ============================ Warning ============================
React.useEffect(() => {
warning(
!('dataSource' in props),
'AutoComplete',
'`dataSource` is deprecated, please use `options` instead.',
);
warning(
!customizeInput || !('size' in props),
'AutoComplete',
'You need to control style self instead of setting `size` when using customize input.',
);
}, []);
return (
<ConfigConsumer>
{({ getPrefixCls }: ConfigConsumerProps) => {
const prefixCls = getPrefixCls('select', customizePrefixCls);
return (
<InternalSelect
ref={selectRef as any}
{...omit(props, ['dataSource'])}
prefixCls={prefixCls}
className={classNames(className, `${prefixCls}-auto-complete`)}
mode={Select.SECRET_COMBOBOX_MODE_DO_NOT_USE as any}
getInputElement={getInputElement}
>
{optionChildren}
</InternalSelect>
);
}}
</ConfigConsumer>
);
};
const RefAutoComplete = React.forwardRef<Select, AutoCompleteProps>(AutoComplete);
type RefAutoComplete = typeof RefAutoComplete & {
Option: OptionType;
};
(RefAutoComplete as RefAutoComplete).Option = Option;
export default RefAutoComplete as RefAutoComplete;