mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
feat: 移动端单选select支持搜索
This commit is contained in:
parent
d1dd59cc8a
commit
433806957b
@ -23,6 +23,7 @@ export interface PickerProps extends ThemeProps, LocaleProps {
|
||||
value?: PickerValue[];
|
||||
swipeDuration?: number;
|
||||
visibleItemCount?: number;
|
||||
highlightTxt?: string;
|
||||
itemHeight?: number;
|
||||
columns: PickerColumnItem[] | PickerColumnItem;
|
||||
onChange?: (value?: PickerValue[], index?: number, confirm?: boolean) => void;
|
||||
@ -49,6 +50,7 @@ const Picker = memo<PickerProps>(props => {
|
||||
itemHeight = 48,
|
||||
showToolbar = true,
|
||||
className = '',
|
||||
highlightTxt = '',
|
||||
classnames: cx,
|
||||
classPrefix: ns,
|
||||
translate: __
|
||||
@ -93,6 +95,7 @@ const Picker = memo<PickerProps>(props => {
|
||||
return (
|
||||
<Column
|
||||
{...item}
|
||||
highlightTxt={highlightTxt}
|
||||
classnames={cx}
|
||||
classPrefix={ns}
|
||||
labelField={labelField || item.labelField}
|
||||
|
@ -12,7 +12,7 @@ import React, {
|
||||
} from 'react';
|
||||
import isObject from 'lodash/isObject';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {uncontrollable} from 'amis-core';
|
||||
import {uncontrollable, highlight} from 'amis-core';
|
||||
|
||||
import {useSetState, useUpdateEffect} from '../hooks';
|
||||
import {range} from 'amis-core';
|
||||
@ -28,6 +28,7 @@ export interface PickerColumnItem {
|
||||
visibleItemCount?: number;
|
||||
itemHeight?: number;
|
||||
options?: PickerOption[];
|
||||
highlightTxt?: string;
|
||||
optionRender?: (...params: any) => React.ReactNode;
|
||||
onChange?: (
|
||||
value?: PickerOption | string,
|
||||
@ -74,6 +75,7 @@ const PickerColumn = forwardRef<{}, PickerColumnProps>((props, ref) => {
|
||||
valueField = 'value',
|
||||
swipeDuration = 1000,
|
||||
labelField = 'text',
|
||||
highlightTxt = '',
|
||||
options = [],
|
||||
classnames: cx
|
||||
} = props;
|
||||
@ -294,7 +296,7 @@ const PickerColumn = forwardRef<{}, PickerColumnProps>((props, ref) => {
|
||||
lineHeight: `${itemHeight}px`
|
||||
};
|
||||
return state.options.map((option, index: number) => {
|
||||
const text: string | PickerOption = getOptionText(option);
|
||||
const text: string = getOptionText(option);
|
||||
const disabled = isOptionDisabled(option);
|
||||
|
||||
const data = {
|
||||
@ -313,7 +315,9 @@ const PickerColumn = forwardRef<{}, PickerColumnProps>((props, ref) => {
|
||||
|
||||
const childData = {
|
||||
className: 'text-ellipsis',
|
||||
children: text as React.ReactNode
|
||||
children: (highlightTxt
|
||||
? highlight(text, highlightTxt, cx('Select-option-hl'))
|
||||
: text) as React.ReactNode
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -420,6 +420,31 @@ export default class SelectMobile extends React.Component<Props, SelectState> {
|
||||
);
|
||||
};
|
||||
|
||||
const searchInput = (
|
||||
<div
|
||||
className={cx(`Select-input`, {
|
||||
'is-focused': this.state.isFocused
|
||||
})}
|
||||
>
|
||||
<Icon icon="search" className="icon" />
|
||||
<Input
|
||||
{...getInputProps({
|
||||
onFocus: this.onFocus,
|
||||
onBlur: this.onBlur,
|
||||
disabled: disabled,
|
||||
placeholder: __(searchPromptText),
|
||||
onChange: this.handleInputChange,
|
||||
ref: this.inputRef
|
||||
})}
|
||||
/>
|
||||
{inputValue?.length ? (
|
||||
<a onClick={this.clearSearchValue} className={cx('Select-clear')}>
|
||||
<Icon icon="close" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
const menu = (
|
||||
<div
|
||||
className={cx('Select-menu', {
|
||||
@ -427,30 +452,7 @@ export default class SelectMobile extends React.Component<Props, SelectState> {
|
||||
'is-mobile': true
|
||||
})}
|
||||
>
|
||||
{searchable ? (
|
||||
<div
|
||||
className={cx(`Select-input`, {
|
||||
'is-focused': this.state.isFocused
|
||||
})}
|
||||
>
|
||||
<Icon icon="search" className="icon" />
|
||||
<Input
|
||||
{...getInputProps({
|
||||
onFocus: this.onFocus,
|
||||
onBlur: this.onBlur,
|
||||
disabled: disabled,
|
||||
placeholder: __(searchPromptText),
|
||||
onChange: this.handleInputChange,
|
||||
ref: this.inputRef
|
||||
})}
|
||||
/>
|
||||
{inputValue?.length ? (
|
||||
<a onClick={this.clearSearchValue} className={cx('Select-clear')}>
|
||||
<Icon icon="close" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{searchable ? searchInput : null}
|
||||
{multiple && valuesNoWrap ? (
|
||||
<div className={cx('Select-option')}>
|
||||
已选择({selectionValues.length})
|
||||
@ -504,20 +506,24 @@ export default class SelectMobile extends React.Component<Props, SelectState> {
|
||||
{multiple ? (
|
||||
menu
|
||||
) : (
|
||||
<Picker
|
||||
className={'Select-picker'}
|
||||
columns={{
|
||||
options: filtedOptions as Option[],
|
||||
optionRender: renderMenu
|
||||
}}
|
||||
onChange={item => this.handleChange(item as any)}
|
||||
showToolbar={false}
|
||||
labelField={labelField}
|
||||
valueField={valueField}
|
||||
itemHeight={40}
|
||||
visibleItemCount={visibleItemCount}
|
||||
value={[selection[0]?.[valueField]]}
|
||||
/>
|
||||
<div className={cx(`Select-popup-inner`)}>
|
||||
{searchable ? searchInput : null}
|
||||
<Picker
|
||||
className={'Select-picker'}
|
||||
columns={{
|
||||
options: filtedOptions as Option[],
|
||||
optionRender: renderMenu
|
||||
}}
|
||||
highlightTxt={inputValue}
|
||||
onChange={item => this.handleChange(item as any)}
|
||||
showToolbar={false}
|
||||
labelField={labelField}
|
||||
valueField={valueField}
|
||||
itemHeight={40}
|
||||
visibleItemCount={visibleItemCount}
|
||||
value={[selection[0]?.[valueField]]}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</PopUp>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user