102 lines
2.5 KiB
TypeScript
102 lines
2.5 KiB
TypeScript
import { EnterOutlined } from "@ant-design/icons";
|
|
import { useClickAway } from "ahooks";
|
|
import { Input, InputRef } from "antd";
|
|
import clsx from "clsx";
|
|
import { FC, useRef, useState } from "react";
|
|
|
|
import edit_name from "@/assets/images/chatSetting/edit_name.png";
|
|
|
|
interface IEditableContentProps {
|
|
editable?: boolean;
|
|
value?: string;
|
|
placeholder?: string;
|
|
className?: string;
|
|
textClassName?: string;
|
|
onChange?: (value: string) => Promise<void>;
|
|
}
|
|
|
|
const EditableContent: FC<IEditableContentProps> = ({
|
|
editable,
|
|
value,
|
|
placeholder,
|
|
className,
|
|
textClassName,
|
|
onChange,
|
|
}) => {
|
|
const wrapRef = useRef<HTMLDivElement>(null);
|
|
const inputRef = useRef<InputRef>(null);
|
|
const [editState, setEditState] = useState({
|
|
isEdit: false,
|
|
loading: false,
|
|
innerValue: value,
|
|
});
|
|
|
|
useClickAway(() => {
|
|
if (editState.isEdit) {
|
|
setEditState({
|
|
isEdit: false,
|
|
loading: false,
|
|
innerValue: value,
|
|
});
|
|
}
|
|
}, [wrapRef]);
|
|
|
|
const toggleEdit = (e: React.MouseEvent<HTMLImageElement, MouseEvent>) => {
|
|
e.stopPropagation();
|
|
setEditState({
|
|
isEdit: true,
|
|
loading: false,
|
|
innerValue: value === "-" ? "" : value,
|
|
});
|
|
setTimeout(() => inputRef.current?.focus());
|
|
};
|
|
|
|
const onPressEnter = async (
|
|
e: React.KeyboardEvent<HTMLInputElement> & { target: { value: string } },
|
|
) => {
|
|
setEditState((state) => ({ ...state, loading: true }));
|
|
await onChange?.(e.target.value);
|
|
setEditState({
|
|
isEdit: false,
|
|
loading: false,
|
|
innerValue: e.target.value,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div ref={wrapRef} className={clsx("ml-3 flex items-center", className)}>
|
|
{editState.isEdit ? (
|
|
<Input
|
|
spellCheck={false}
|
|
value={editState.innerValue}
|
|
placeholder={placeholder}
|
|
maxLength={20}
|
|
onChange={(e) =>
|
|
setEditState((state) => ({ ...state, innerValue: e.target.value }))
|
|
}
|
|
ref={inputRef}
|
|
onPressEnter={onPressEnter}
|
|
suffix={<EnterOutlined rev={undefined} />}
|
|
/>
|
|
) : (
|
|
<>
|
|
<div className={clsx("mr-1 max-w-[240px] truncate", textClassName)}>
|
|
{value}
|
|
</div>
|
|
{editable && (
|
|
<img
|
|
className="cursor-pointer"
|
|
width={14}
|
|
src={edit_name}
|
|
alt="edit name"
|
|
onClick={toggleEdit}
|
|
/>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EditableContent;
|