update typeaheadmodal

This commit is contained in:
Red Adaya 2024-10-23 13:41:06 +08:00
parent 8cb6fe01bc
commit 054a0098e9
2 changed files with 38 additions and 42 deletions

View File

@ -11,46 +11,49 @@ interface InputGroupProps {
className?: string; className?: string;
} }
const InputGroup = ({ children, className }: InputGroupProps) => { const InputGroup = memo(
const [isFocused, setIsFocused] = useState(false); forwardRef<HTMLDivElement, InputGroupProps>(({ children, className }: InputGroupProps, ref) => {
const [isFocused, setIsFocused] = useState(false);
const manageFocus = (focused: boolean) => { const manageFocus = (focused: boolean) => {
setIsFocused(focused); setIsFocused(focused);
}; };
return ( return (
<div <div
className={clsx("input-group", className, { ref={ref}
focused: isFocused, className={clsx("input-group", className, {
})} focused: isFocused,
> })}
{React.Children.map(children, (child) => { >
if (React.isValidElement(child)) { {React.Children.map(children, (child) => {
return React.cloneElement(child as any, { manageFocus }); if (React.isValidElement(child)) {
} return React.cloneElement(child as any, { manageFocus });
return child; }
})} return child;
</div> })}
); </div>
}; );
})
);
interface InputLeftElementProps { interface InputLeftElementProps {
children: React.ReactNode; children: React.ReactNode;
className?: string; className?: string;
} }
const InputLeftElement = ({ children, className }: InputLeftElementProps) => { const InputLeftElement = memo(({ children, className }: InputLeftElementProps) => {
return <div className={clsx("input-left-element", className)}>{children}</div>; return <div className={clsx("input-left-element", className)}>{children}</div>;
}; });
interface InputRightElementProps { interface InputRightElementProps {
children: React.ReactNode; children: React.ReactNode;
className?: string; className?: string;
} }
const InputRightElement = ({ children, className }: InputRightElementProps) => { const InputRightElement = memo(({ children, className }: InputRightElementProps) => {
return <div className={clsx("input-right-element", className)}>{children}</div>; return <div className={clsx("input-right-element", className)}>{children}</div>;
}; });
interface InputProps { interface InputProps {
label?: string; label?: string;
@ -67,7 +70,6 @@ interface InputProps {
autoFocus?: boolean; autoFocus?: boolean;
disabled?: boolean; disabled?: boolean;
isNumber?: boolean; isNumber?: boolean;
inputRef?: React.MutableRefObject<any>;
manageFocus?: (isFocused: boolean) => void; manageFocus?: (isFocused: boolean) => void;
} }
@ -126,7 +128,6 @@ const Input = memo(
return ( return (
<div <div
ref={ref}
className={clsx("input-wrapper", className, { className={clsx("input-wrapper", className, {
disabled: disabled, disabled: disabled,
})} })}

View File

@ -102,13 +102,12 @@ const TypeAheadModal = ({
const width = domRect?.width ?? 0; const width = domRect?.width ?? 0;
const height = domRect?.height ?? 0; const height = domRect?.height ?? 0;
const modalRef = useRef<HTMLDivElement>(null); const modalRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null); const inputGroupRef = useRef<HTMLInputElement>(null);
const realInputRef = useRef<HTMLInputElement>(null);
const suggestionsWrapperRef = useRef<HTMLDivElement>(null); const suggestionsWrapperRef = useRef<HTMLDivElement>(null);
const suggestionsRef = useRef<HTMLDivElement>(null); const suggestionsRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => { useLayoutEffect(() => {
if (!modalRef.current || !inputRef.current || !suggestionsRef.current || !suggestionsWrapperRef.current) { if (!modalRef.current || !inputGroupRef.current || !suggestionsRef.current || !suggestionsWrapperRef.current) {
return; return;
} }
@ -123,7 +122,8 @@ const TypeAheadModal = ({
const suggestionsWrapperStyles = window.getComputedStyle(suggestionsWrapperRef.current); const suggestionsWrapperStyles = window.getComputedStyle(suggestionsWrapperRef.current);
const suggestionsWrapperMarginTop = parseFloat(suggestionsWrapperStyles.marginTop) || 0; const suggestionsWrapperMarginTop = parseFloat(suggestionsWrapperStyles.marginTop) || 0;
const inputHeight = inputRef.current.getBoundingClientRect().height; const inputGroupHeight = inputGroupRef.current.getBoundingClientRect().height;
console.log("inputHeight=========", inputGroupHeight);
let suggestionsTotalHeight = 0; let suggestionsTotalHeight = 0;
const suggestionItems = suggestionsRef.current.children; const suggestionItems = suggestionsRef.current.children;
@ -131,14 +131,16 @@ const TypeAheadModal = ({
suggestionsTotalHeight += suggestionItems[i].getBoundingClientRect().height; suggestionsTotalHeight += suggestionItems[i].getBoundingClientRect().height;
} }
console.log("suggestionsTotalHeight", suggestionsTotalHeight);
const totalHeight = const totalHeight =
modalPadding + modalBorder + inputHeight + suggestionsTotalHeight + suggestionsWrapperMarginTop; modalPadding + modalBorder + inputGroupHeight + suggestionsTotalHeight + suggestionsWrapperMarginTop;
const maxHeight = height * 0.8; const maxHeight = height * 0.8;
const computedHeight = totalHeight > maxHeight ? maxHeight : totalHeight; const computedHeight = totalHeight > maxHeight ? maxHeight : totalHeight;
modalRef.current.style.height = `${computedHeight}px`; modalRef.current.style.height = `${computedHeight}px`;
suggestionsWrapperRef.current.style.height = `${computedHeight - inputHeight - modalPadding - modalBorder - suggestionsWrapperMarginTop}px`; suggestionsWrapperRef.current.style.height = `${computedHeight - inputGroupHeight - modalPadding - modalBorder - suggestionsWrapperMarginTop}px`;
}, [height, suggestions]); }, [height, suggestions]);
useLayoutEffect(() => { useLayoutEffect(() => {
@ -176,7 +178,7 @@ const TypeAheadModal = ({
useLayoutEffect(() => { useLayoutEffect(() => {
if (giveFocusRef) { if (giveFocusRef) {
giveFocusRef.current = () => { giveFocusRef.current = () => {
realInputRef.current?.focus(); inputGroupRef.current?.focus();
return true; return true;
}; };
} }
@ -215,15 +217,8 @@ const TypeAheadModal = ({
ref={modalRef} ref={modalRef}
className={clsx("type-ahead-modal", className, { "has-suggestions": suggestions?.length > 0 })} className={clsx("type-ahead-modal", className, { "has-suggestions": suggestions?.length > 0 })}
> >
<InputGroup> <InputGroup ref={inputGroupRef}>
<Input <Input onChange={handleChange} value={value} autoFocus={autoFocus} placeholder={label} />
ref={inputRef}
inputRef={realInputRef}
onChange={handleChange}
value={value}
autoFocus={autoFocus}
placeholder={label}
/>
<InputRightElement> <InputRightElement>
<i className="fa-regular fa-magnifying-glass"></i> <i className="fa-regular fa-magnifying-glass"></i>
</InputRightElement> </InputRightElement>