chat / client /src /components /Prompts /PromptName.tsx
Zhitomir's picture
chat init
aa2e6af
Raw
History Blame Contribute Delete
2.77 kB
import React, { useEffect, useState, useRef } from 'react';
import { EditIcon, SaveIcon } from '~/components/svg';
type Props = {
name?: string;
onSave: (newName: string) => void;
};
const PromptName: React.FC<Props> = ({ name, onSave }) => {
const inputRef = useRef<HTMLInputElement>(null);
const blurTimeoutRef = useRef<NodeJS.Timeout>();
const [isEditing, setIsEditing] = useState(false);
const [newName, setNewName] = useState(name);
const handleEditClick = () => {
setIsEditing(true);
};
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewName(e.target.value);
};
const saveName = () => {
const savedName = newName?.trim();
onSave(savedName || '');
setIsEditing(false);
};
const handleSaveClick: React.MouseEventHandler<HTMLButtonElement> = () => {
saveName();
clearTimeout(blurTimeoutRef.current);
};
const handleBlur = () => {
blurTimeoutRef.current = setTimeout(() => {
if (document.activeElement !== inputRef.current) {
setIsEditing(false);
setNewName(name);
}
}, 200);
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
setIsEditing(false);
setNewName(name);
}
if (e.key === 'Enter' || e.key === 'Tab') {
saveName();
}
};
useEffect(() => {
if (isEditing) {
inputRef.current?.focus();
}
}, [isEditing]);
useEffect(() => {
setNewName(name);
}, [name]);
return (
<div className="mb-1 flex flex-row items-center font-bold sm:text-xl md:mb-0 md:text-2xl">
{isEditing ? (
<div className="mb-1 flex items-center md:mb-0">
<input
type="text"
value={newName ?? ''}
onChange={handleInputChange}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
ref={inputRef}
className="mr-2 w-56 rounded-md border bg-transparent p-2 focus:outline-none dark:border-gray-600 md:w-auto"
autoFocus={true}
/>
<button
type="button"
onClick={handleSaveClick}
className="rounded p-2 hover:bg-gray-300/50 dark:hover:bg-gray-700"
>
<SaveIcon className="icon-md" size="1.2em" />
</button>
</div>
) : (
<div className="mb-1 flex items-center md:mb-0">
<span className="border border-transparent p-2">{newName}</span>
<button
type="button"
onClick={handleEditClick}
className="rounded p-2 hover:bg-gray-300/50 dark:hover:bg-gray-700"
>
<EditIcon className="icon-md" />
</button>
</div>
)}
</div>
);
};
export default PromptName;