126 lines
3.3 KiB
TypeScript

import { Button, Divider, Flex, Space } from "antd";
import { createStyles } from "antd-style";
import ButtonGroup from "antd/es/button/button-group";
import Search from "antd/es/input/Search";
import React, { useEffect, useRef, useState } from "react";
interface SearchBoxProps {
children: React.ReactNode;
placeholder?: string;
searchKey?: string | undefined;
onClear?: () => void;
onCancel?: () => void;
onConfirm?: () => void;
onSearch?: (searchKey: string) => void;
visible?: boolean;
}
const SearchBox: React.FC<SearchBoxProps> = ({
children,
placeholder = "请输入搜索内容",
searchKey,
onCancel,
onClear,
onConfirm,
onSearch,
visible,
}) => {
const { styles } = useStyles();
const [operateVisible, setOperateVisible] = useState(false);
const clickRef = useRef<HTMLDivElement>(null);
const handleClickOutside = (event: MouseEvent) => {
if (clickRef.current && !clickRef.current.contains(event.target as Node)) {
setOperateVisible(false);
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
return (
<div className={styles.searchBoxContainer}>
<Search
placeholder={placeholder}
className="search"
onClick={() => setOperateVisible(true)}
value={searchKey}
onChange={(e) => onSearch?.(e.target.value)}
/>
<Flex
vertical
ref={clickRef}
className="operate"
style={{ display: operateVisible ? "flex" : "none" }}
>
<div className="operate-content">{children}</div>
<Flex className="operate-area">
<Divider className="divider" />
<ButtonGroup className="button-group">
<Button onClick={() => {
onClear?.();
}}></Button>
<Space onClick={() => setOperateVisible(false)}>
<Button onClick={() => onCancel?.()}></Button>
<Button type="primary" onClick={() => onConfirm?.()}></Button>
</Space>
</ButtonGroup>
</Flex>
</Flex>
</div>
);
};
export default SearchBox;
const useStyles = createStyles(({ token }) => {
return {
searchBoxContainer: {
position: "relative",
width: "300px",
"& .search": {
width: "100%",
},
"& .operate": {
position: "absolute",
left: 0,
boxSizing: "border-box",
padding: `${token.padding}px ${token.padding}px 0`,
zIndex: 999,
backgroundColor: token.colorBgContainer,
boxShadow: token.boxShadow,
borderRadius: token.borderRadius,
width: "100%",
marginTop: token.marginXXS,
height: "300px",
overflow: "hidden",
},
"& .operate-content": {
flex: 1,
padding: `${token.paddingContentVertical}px 0`,
},
"& .operate-area": {
height: "50px",
position: "relative",
width: "100%",
"& .divider": {
margin: 0,
},
},
"& .button-group": {
position: "absolute",
transform: "translateY(-50%)",
top: 'calc(50% + 2px)',
right: 0,
display: 'flex',
justifyContent: 'space-between',
width: '100%'
},
},
};
});