| import React, { useEffect, useState, useRef } from 'react'; |
| import { Button, Label, Input, EditIcon, SaveIcon } from '@librechat/client'; |
|
|
| 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 handleKeyDown = (e: React.KeyboardEvent) => { |
| if (e.key === 'Escape') { |
| setIsEditing(false); |
| setNewName(name); |
| } |
| if (e.key === 'Enter') { |
| saveName(); |
| } |
| }; |
|
|
| useEffect(() => { |
| if (isEditing) { |
| inputRef.current?.focus(); |
| } |
| }, [isEditing]); |
|
|
| useEffect(() => { |
| setNewName(name); |
| }, [name]); |
|
|
| return ( |
| <div className="flex items-center"> |
| <div |
| style={{ |
| display: 'grid', |
| gridTemplateColumns: '1fr auto', |
| alignItems: 'center', |
| }} |
| className="gap-2" |
| > |
| {isEditing ? ( |
| <> |
| <Input |
| type="text" |
| value={newName ?? ''} |
| onChange={handleInputChange} |
| onKeyDown={handleKeyDown} |
| ref={inputRef} |
| className="flex w-full max-w-none rounded-lg text-2xl font-bold transition duration-200" |
| style={{ |
| whiteSpace: 'nowrap', |
| textOverflow: 'ellipsis', |
| }} |
| /> |
| |
| <Button |
| onClick={handleSaveClick} |
| variant="ghost" |
| size="sm" |
| className="h-10 flex-shrink-0" |
| aria-label="Save prompt name" |
| > |
| <SaveIcon className="icon-md" /> |
| </Button> |
| </> |
| ) : ( |
| <> |
| <Label |
| className="text-2xl font-bold" |
| style={{ |
| overflow: 'hidden', |
| whiteSpace: 'nowrap', |
| textOverflow: 'ellipsis', |
| }} |
| > |
| {newName} |
| </Label> |
| <Button |
| onClick={handleEditClick} |
| variant="ghost" |
| size="sm" |
| aria-label="Edit prompt name" |
| className="h-10 flex-shrink-0" |
| > |
| <EditIcon className="icon-md" /> |
| </Button> |
| </> |
| )} |
| </div> |
| </div> |
| ); |
| }; |
|
|
| export default PromptName; |
|
|