-
Notifications
You must be signed in to change notification settings - Fork 358
Expand file tree
/
Copy pathuseSingle.tsx
More file actions
134 lines (116 loc) · 4 KB
/
useSingle.tsx
File metadata and controls
134 lines (116 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import React, { useRef } from 'react';
import classNames from 'classnames';
import { isObject, pick } from 'lodash-es';
import useConfig from '../hooks/useConfig';
import useControlled from '../hooks/useControlled';
import Input, { type InputRef, type TdInputProps } from '../input';
import Loading from '../loading';
import type { SelectInputCommonProperties } from './interface';
import type { TdSelectInputProps } from './type';
export interface RenderSelectSingleInputParams {
tPlaceholder: string;
}
// single 和 multiple 共有特性
const COMMON_PROPERTIES = [
'status',
'clearable',
'disabled',
'label',
'placeholder',
'readonly',
'suffix',
'suffixIcon',
'onPaste',
'onEnter',
'onMouseenter',
'onMouseleave',
'size',
'prefixIcon',
];
const DEFAULT_KEYS: TdSelectInputProps['keys'] = {
label: 'label',
value: 'value',
};
function getInputValue(value: TdSelectInputProps['value'], keys: TdSelectInputProps['keys']) {
const iKeys = keys || DEFAULT_KEYS;
return isObject(value) ? value[iKeys.label] : value;
}
export default function useSingle(props: TdSelectInputProps) {
const { value, keys, loading } = props;
const { classPrefix } = useConfig();
const inputRef = useRef<InputRef>(null);
const [inputValue, setInputValue] = useControlled(props, 'inputValue', props.onInputChange);
const commonInputProps: SelectInputCommonProperties = {
...pick(props, COMMON_PROPERTIES),
suffixIcon: loading ? <Loading loading size="small" /> : props.suffixIcon,
};
const onInnerClear = (context: { e: React.MouseEvent<SVGSVGElement> }) => {
context?.e?.stopPropagation();
props.onClear?.(context);
setInputValue('', { trigger: 'clear' });
};
const onInnerInputChange: TdInputProps['onChange'] = (value, context) => {
if (props.allowInput) {
setInputValue(value, { ...context, trigger: 'input' });
}
};
const renderSelectSingle = (
popupVisible: boolean,
onInnerBlur?: (context: { e: React.FocusEvent<HTMLInputElement> }) => void,
) => {
// 单选,值的呈现方式
const singleValueDisplay: any = !props.multiple ? props.valueDisplay : null;
const displayedValue = popupVisible && props.allowInput ? inputValue : getInputValue(value, keys);
const handleBlur = (value, ctx) => {
if (!popupVisible) {
onInnerBlur(ctx);
} else if (!props.panel) {
props.onBlur?.(value, { e: ctx.e, inputValue: value });
}
};
const handleFocus = (val, context) => {
props.onFocus?.(value, { ...context, inputValue: val });
// focus might not need to change input value. it will caught some curious errors in tree-select
// !popupVisible && setInputValue(getInputValue(value, keys), { ...context, trigger: 'input' });
};
return (
<Input
ref={inputRef}
{...commonInputProps}
autoWidth={props.autoWidth}
allowInput={props.allowInput}
placeholder={singleValueDisplay ? '' : props.placeholder}
value={singleValueDisplay ? ' ' : displayedValue}
label={
(props.label || singleValueDisplay) && (
<>
{props.label}
{singleValueDisplay as React.ReactNode}
</>
)
}
onChange={onInnerInputChange}
onClear={onInnerClear}
// [Important Info]: SelectInput.blur is not equal to Input, example: click popup panel
onFocus={handleFocus}
onEnter={(val, context) => {
props.onEnter?.(value, { ...context, inputValue: val });
}}
// onBlur need to triggered by input when popup panel is null or when popupVisible is forced to false
onBlur={handleBlur}
{...props.inputProps}
inputClass={classNames(props.inputProps?.className, {
[`${classPrefix}-input--focused`]: popupVisible,
[`${classPrefix}-is-focused`]: popupVisible,
})}
/>
);
};
return {
inputRef,
commonInputProps,
singleInputValue: inputValue,
onInnerClear,
renderSelectSingle,
};
}