amis-rpc-design/libs/amis/packages/amis-ui/src/components/InputBoxWithSuggestion.tsx
2023-10-07 19:42:30 +08:00

120 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react';
import {findDOMNode} from 'react-dom';
import {localeable, LocaleProps} from 'amis-core';
import {themeable, ThemeProps} from 'amis-core';
// @ts-ignore
import {matchSorter} from 'match-sorter';
import PopOverContainer from './PopOverContainer';
import SearchBox from './SearchBox';
import ListSelection from './GroupedSelection';
import InputBox from './InputBox';
import {Icon} from './icons';
export interface InputBoxWithSuggestionProps extends ThemeProps, LocaleProps {
options: Array<any>;
value: any;
onChange: (value: any) => void;
disabled?: boolean;
searchable?: boolean;
popOverContainer?: any;
hasError?: boolean;
placeholder?: string;
clearable?: boolean;
}
const option2value = (item: any) => item.value;
export class InputBoxWithSuggestion extends React.Component<InputBoxWithSuggestionProps> {
constructor(props: InputBoxWithSuggestionProps) {
super(props);
this.state = {
searchText: ''
};
this.onSearch = this.onSearch.bind(this);
this.filterOptions = this.filterOptions.bind(this);
}
onSearch(text: string) {
let txt = text.toLowerCase();
this.setState({searchText: txt});
}
filterOptions(options: any[]) {
return this.props.value
? matchSorter(options, this.props.value, {
keys: ['label', 'value']
})
: options;
}
// 选了值还原options
onPopClose(e: React.MouseEvent, onClose: () => void) {
this.setState({searchText: ''});
onClose();
}
render() {
const {
placeholder,
onChange,
value,
classnames: cx,
disabled,
translate: __,
searchable,
popOverContainer,
clearable,
hasError,
mobileUI
} = this.props;
const options = this.filterOptions(
Array.isArray(this.props.options) ? this.props.options : []
);
return (
<PopOverContainer
popOverContainer={popOverContainer || (() => findDOMNode(this))}
popOverRender={({onClose}) => (
<>
{searchable ? (
<SearchBox mini={false} onSearch={this.onSearch} />
) : null}
<ListSelection
multiple={false}
onClick={e => this.onPopClose(e, onClose)}
options={options}
value={[value]}
option2value={option2value}
onChange={(value: any) => {
onChange?.(value);
}}
/>
</>
)}
>
{({onClick, ref, isOpened}) => (
<InputBox
className={cx('InputBox--sug', isOpened ? 'is-active' : '')}
ref={ref}
placeholder={placeholder}
disabled={disabled}
value={options.find(o => o.value === value)?.label ?? value}
onChange={onChange}
clearable={clearable}
onClick={onClick}
hasError={hasError}
mobileUI={mobileUI}
>
<span className={cx('InputBox-caret')}>
<Icon icon="right-arrow-bold" className="icon" />
</span>
</InputBox>
)}
</PopOverContainer>
);
}
}
export default themeable(localeable(InputBoxWithSuggestion));