-
-
Notifications
You must be signed in to change notification settings - Fork 489
Expand file tree
/
Copy pathSingleContent.tsx
More file actions
124 lines (109 loc) · 3.99 KB
/
SingleContent.tsx
File metadata and controls
124 lines (109 loc) · 3.99 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
import * as React from 'react';
import { clsx } from 'clsx';
import Input from '../Input';
import { useSelectInputContext } from '../context';
import useBaseProps from '../../hooks/useBaseProps';
import Placeholder from './Placeholder';
import type { SharedContentProps } from '.';
import SelectContext from '../../SelectContext';
import { getTitle } from '../../utils/commonUtil';
const SingleContent = React.forwardRef<HTMLInputElement, SharedContentProps>(
({ inputProps }, ref) => {
const { prefixCls, searchValue, activeValue, displayValues, maxLength, mode, components } =
useSelectInputContext();
const { triggerOpen, title: rootTitle, showSearch, classNames, styles } = useBaseProps();
const selectContext = React.useContext(SelectContext);
const [inputChanged, setInputChanged] = React.useState(false);
const combobox = mode === 'combobox';
const displayValue = displayValues[0];
// Implement the same logic as the old SingleSelector
const mergedSearchValue = React.useMemo(() => {
if (combobox && activeValue && !inputChanged && triggerOpen) {
return activeValue;
}
return showSearch ? searchValue : '';
}, [combobox, activeValue, inputChanged, triggerOpen, searchValue, showSearch]);
const [optionClassName, optionStyle, optionTitle, hasOptionStyle] = React.useMemo(() => {
let className: string | undefined;
let style: React.CSSProperties | undefined;
let titleValue: string | undefined;
if (displayValue && selectContext?.flattenOptions) {
const option = selectContext.flattenOptions.find((opt) => opt.value === displayValue.value);
if (option?.data) {
className = option.data.className;
style = option.data.style;
titleValue = getTitle(option.data);
}
}
if (displayValue && !titleValue) {
titleValue = getTitle(displayValue);
}
if (rootTitle !== undefined) {
titleValue = rootTitle;
}
const nextHasStyle = !!className || !!style;
return [className, style, titleValue, nextHasStyle] as const;
}, [displayValue, selectContext?.flattenOptions, rootTitle]);
React.useEffect(() => {
if (combobox) {
setInputChanged(false);
}
}, [combobox, activeValue]);
// ========================== Render ==========================
const showHasValueCls =
displayValue &&
displayValue.label !== null &&
displayValue.label !== undefined &&
String(displayValue.label).trim() !== '';
// Render value
// Only render value when not using custom input in combobox mode
const shouldRenderValue = !(combobox && components?.input);
const renderValue = shouldRenderValue ? (
displayValue ? (
hasOptionStyle ? (
<div
className={clsx(`${prefixCls}-content-value`, optionClassName)}
style={{
...(mergedSearchValue ? { visibility: 'hidden' } : {}),
...optionStyle,
}}
title={optionTitle}
>
{displayValue.label}
</div>
) : (
displayValue.label
)
) : (
<Placeholder show={!mergedSearchValue} />
)
) : null;
// Render
return (
<div
className={clsx(
`${prefixCls}-content`,
showHasValueCls && `${prefixCls}-content-has-value`,
mergedSearchValue && `${prefixCls}-content-has-search-value`,
hasOptionStyle && `${prefixCls}-content-has-option-style`,
classNames?.content,
)}
style={styles?.content}
title={hasOptionStyle ? undefined : optionTitle}
>
{renderValue}
<Input
ref={ref}
{...inputProps}
value={mergedSearchValue}
maxLength={mode === 'combobox' ? maxLength : undefined}
onChange={(e) => {
setInputChanged(true);
inputProps.onChange?.(e);
}}
/>
</div>
);
},
);
export default SingleContent;