|
|
|
import React from 'react';
|
|
|
|
import RcCascader from 'rc-cascader';
|
|
|
|
import Input from '../input';
|
|
|
|
import Icon from '../icon';
|
|
|
|
import arrayTreeFilter from 'array-tree-filter';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import splitObject from '../_util/splitObject';
|
|
|
|
import omit from 'omit.js';
|
|
|
|
|
|
|
|
export interface CascaderOptionType {
|
|
|
|
value: string;
|
|
|
|
label: string;
|
|
|
|
disabled?: boolean;
|
|
|
|
children?: Array<CascaderOptionType>;
|
|
|
|
}
|
|
|
|
|
|
|
|
export type CascaderExpandTrigger = 'click' | 'hover'
|
|
|
|
|
|
|
|
export interface ShowSearchType {
|
|
|
|
filter?: (inputValue: string, path: CascaderOptionType[]) => boolean;
|
|
|
|
render?: (inputValue: string, path: CascaderOptionType[], prefixCls: string) => React.ReactNode;
|
|
|
|
sort?: (a: CascaderOptionType[], b: CascaderOptionType[], inputValue: string) => number;
|
|
|
|
matchInputWidth?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface CascaderProps {
|
|
|
|
/** 可选项数据源 */
|
|
|
|
options: Array<CascaderOptionType>;
|
|
|
|
/** 默认的选中项 */
|
|
|
|
defaultValue?: Array<CascaderOptionType>;
|
|
|
|
/** 指定选中项 */
|
|
|
|
value?: Array<CascaderOptionType>;
|
|
|
|
/** 选择完成后的回调 */
|
|
|
|
onChange?: (value: string, selectedOptions?: Array<CascaderOptionType>) => void;
|
|
|
|
/** 选择后展示的渲染函数 */
|
|
|
|
displayRender?: (label: Array<string>, selectedOptions?: Array<CascaderOptionType>) => React.ReactNode;
|
|
|
|
/** 自定义样式 */
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
/** 自定义类名 */
|
|
|
|
className?: string;
|
|
|
|
/** 自定义浮层类名 */
|
|
|
|
popupClassName?: string;
|
|
|
|
/** 浮层预设位置:`bottomLeft` `bottomRight` `topLeft` `topRight` */
|
|
|
|
popupPlacement?: string;
|
|
|
|
/** 输入框占位文本*/
|
|
|
|
placeholder?: string;
|
|
|
|
/** 输入框大小,可选 `large` `default` `small` */
|
|
|
|
size?: string;
|
|
|
|
/** 禁用*/
|
|
|
|
disabled?: boolean;
|
|
|
|
/** 是否支持清除*/
|
|
|
|
allowClear?: boolean;
|
|
|
|
showSearch?: boolean | ShowSearchType;
|
|
|
|
notFoundContent?: React.ReactNode;
|
|
|
|
/** 次级菜单的展开方式,可选 'click' 和 'hover' */
|
|
|
|
expandTrigger?: CascaderExpandTrigger;
|
|
|
|
/** 当此项为 true 时,点选每级菜单选项值都会发生变化 */
|
|
|
|
changeOnSelect?: boolean;
|
|
|
|
/** 浮层可见变化时回调 */
|
|
|
|
onPopupVisibleChange?: (popupVisible: boolean) => void;
|
|
|
|
prefixCls?: string;
|
|
|
|
inputPrefixCls?: string;
|
|
|
|
}
|
|
|
|
|
|
|
|
function highlightKeyword(str: string, keyword: string, prefixCls: string) {
|
|
|
|
return str.split(keyword)
|
|
|
|
.map((node: string, index: number) => index === 0 ? node : [
|
|
|
|
<span className={`${prefixCls}-menu-item-keyword`} key="seperator">{keyword}</span>,
|
|
|
|
node,
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
function defaultFilterOption(inputValue, path) {
|
|
|
|
return path.some(option => option.label.indexOf(inputValue) > -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
function defaultRenderFilteredOption(inputValue, path, prefixCls) {
|
|
|
|
return path.map(({ label }, index) => {
|
|
|
|
const node = label.indexOf(inputValue) > -1 ? highlightKeyword(label, inputValue, prefixCls) : label;
|
|
|
|
return index === 0 ? node : [' / ', node];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function defaultSortFilteredOption(a, b, inputValue) {
|
|
|
|
function callback(elem) {
|
|
|
|
return elem.label.indexOf(inputValue) > -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return a.findIndex(callback) - b.findIndex(callback);
|
|
|
|
}
|
|
|
|
|
|
|