Skip to content

Commit 817211b

Browse files
committed
fix: calc width
1 parent 8ecbc38 commit 817211b

1 file changed

Lines changed: 48 additions & 6 deletions

File tree

packages/components/select-input/useSingle.tsx

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ export default function useSingle(props: SelectInputProps) {
5656

5757
const inputRef = useRef<InputRef>(null);
5858
const blurTimeoutRef = useRef(null);
59-
const customElementRef = useRef<HTMLDivElement>(null);
59+
const customElementRef = useRef<HTMLSpanElement>(null);
6060

6161
const [isTyping, setIsTyping] = useState<boolean>(false);
6262
const [labelWidth, setLabelWidth] = useState<number>(0);
6363
const [customElementWidth, setCustomElementWidth] = useState<number>(0);
64+
const [suffixSpace, setSuffixSpace] = useState<number>(0);
6465

6566
const singleValueDisplay = useMemo(
6667
() => props.valueDisplay ?? getOptionLabel(value, props.keys),
@@ -99,6 +100,45 @@ export default function useSingle(props: SelectInputProps) {
99100
}
100101
}, [showCustomElement, singleValueDisplay]);
101102

103+
useEffect(() => {
104+
const inputEl = inputRef.current?.inputElement;
105+
if (!inputEl || !props.autoWidth) return;
106+
if (showCustomElement && customElementWidth > 0) {
107+
inputEl.style.minWidth = `${customElementWidth}px`;
108+
} else {
109+
inputEl.style.minWidth = '';
110+
}
111+
}, [props.autoWidth, showCustomElement, customElementWidth]);
112+
113+
useEffect(() => {
114+
// 自定义 valueDisplay 时,labelNode 使用绝对定位
115+
// 避免内容延伸盖到右侧的 suffixIcon 区域,需要测量 input 右侧到 wrapper 右侧的距离作为 right 留白
116+
if (!showCustomElement) {
117+
setSuffixSpace(0);
118+
return;
119+
}
120+
const wrapperEl = inputRef.current?.currentElement;
121+
const inputEl = inputRef.current?.inputElement;
122+
if (!wrapperEl || !inputEl) return undefined;
123+
124+
const measure = () => {
125+
const wrapperRect = wrapperEl.getBoundingClientRect();
126+
const inputRect = inputEl.getBoundingClientRect();
127+
// wrapper 右内边距 + suffix 区域 + suffixIcon 区域
128+
const space = Math.max(wrapperRect.right - inputRect.right, 0);
129+
setSuffixSpace(space);
130+
};
131+
132+
measure();
133+
134+
wrapperEl.addEventListener('mouseenter', measure);
135+
wrapperEl.addEventListener('mouseleave', measure);
136+
return () => {
137+
wrapperEl.removeEventListener('mouseenter', measure);
138+
wrapperEl.removeEventListener('mouseleave', measure);
139+
};
140+
}, [showCustomElement, singleValueDisplay, props.clearable, props.suffixIcon, props.suffix]);
141+
102142
const renderSelectSingle = (
103143
popupVisible: boolean,
104144
onInnerBlur?: (context: { e: React.FocusEvent<HTMLInputElement> }) => void,
@@ -130,7 +170,7 @@ export default function useSingle(props: SelectInputProps) {
130170
// !popupVisible && setInputValue(getInputValue(value, keys), { ...context, trigger: 'input' });
131171
};
132172

133-
const displayedValue = () => {
173+
const displayedValue = (): string => {
134174
if (popupVisible && inputValue) {
135175
return inputValue;
136176
}
@@ -143,7 +183,7 @@ export default function useSingle(props: SelectInputProps) {
143183
return inputValue;
144184
};
145185

146-
const displayedPlaceholder = () => {
186+
const displayedPlaceholder = (): string => {
147187
if (popupVisible && singleValueDisplay && !showCustomElement) {
148188
return singleValueDisplay;
149189
}
@@ -153,20 +193,22 @@ export default function useSingle(props: SelectInputProps) {
153193

154194
const labelNode = showCustomElement ? (
155195
<div
156-
ref={customElementRef}
157196
style={{
158197
position: 'absolute',
159198
left: `${labelWidth + 8}px`,
199+
right: `${suffixSpace}px`,
160200
top: '50%',
161201
transform: 'translateY(-50%)',
162202
pointerEvents: 'none',
163203
textAlign: 'initial',
164-
zIndex: 3,
204+
overflow: 'hidden',
165205
// 输入状态,降低透明度,仿造 placeholder 效果
166206
opacity: popupVisible && props.allowInput ? 0.5 : undefined,
167207
}}
168208
>
169-
{singleValueDisplay}
209+
<span ref={customElementRef} style={{ display: 'inline-block', whiteSpace: 'nowrap' }}>
210+
{singleValueDisplay}
211+
</span>
170212
</div>
171213
) : null;
172214

0 commit comments

Comments
 (0)