Spaces:
Sleeping
Sleeping
| import { useState, useEffect } from 'react'; | |
| const PromptEditor = ({ customPrompt, setCustomPrompt, isMac, isMobile }) => { | |
| const [isEditingPrompt, setIsEditingPrompt] = useState(false); | |
| const [tempPrompt, setTempPrompt] = useState(""); | |
| const [isCollapsed, setIsCollapsed] = useState(isMobile); // Collapsed by default on mobile | |
| // Update collapsed state if isMobile changes | |
| useEffect(() => { | |
| setIsCollapsed(isMobile); | |
| }, [isMobile]); | |
| const handleSave = (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setCustomPrompt(tempPrompt); | |
| setIsEditingPrompt(false); | |
| }; | |
| const handleCancel = (e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setIsEditingPrompt(false); | |
| }; | |
| return ( | |
| <div className={`w-full max-w-4xl ${isMobile ? 'mt-4' : 'mb-4'}`}> | |
| <div | |
| className="flex justify-between items-center mb-1" | |
| > | |
| <label | |
| htmlFor="system-prompt" | |
| className="block text-sm font-medium text-gray-700 cursor-pointer flex-grow" | |
| onClick={() => setIsCollapsed(!isCollapsed)} | |
| > | |
| System Prompt | |
| </label> | |
| <div className="flex items-center"> | |
| {!isEditingPrompt && !isCollapsed && ( | |
| <button | |
| onClick={(e) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| setTempPrompt(customPrompt); | |
| setIsEditingPrompt(true); | |
| }} | |
| className="text-sm text-blue-600 hover:text-blue-800 flex items-center mr-2 p-2" | |
| > | |
| <svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"> | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" /> | |
| </svg> | |
| Edit | |
| </button> | |
| )} | |
| {/* Down/Up caret icon with increased touch target */} | |
| <button | |
| onClick={() => setIsCollapsed(!isCollapsed)} | |
| className="p-2" | |
| aria-label={isCollapsed ? 'Expand prompt' : 'Collapse prompt'} | |
| > | |
| <svg | |
| xmlns="http://www.w3.org/2000/svg" | |
| className={`h-5 w-5 text-gray-500 transition-transform duration-200 ${isCollapsed ? '' : 'transform rotate-180'}`} | |
| fill="none" | |
| viewBox="0 0 24 24" | |
| stroke="currentColor" | |
| > | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| {!isCollapsed && ( | |
| <> | |
| {isEditingPrompt ? ( | |
| <div onClick={(e) => e.stopPropagation()}> | |
| <textarea | |
| id="system-prompt" | |
| value={tempPrompt} | |
| onChange={(e) => setTempPrompt(e.target.value)} | |
| onKeyDown={(e) => { | |
| // Save on Ctrl+Enter or Cmd+Enter | |
| if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { | |
| e.preventDefault(); | |
| handleSave(e); | |
| } | |
| }} | |
| className="w-full p-3 border border-gray-300 rounded-lg shadow-sm focus:ring-blue-500 focus:border-blue-500 text-sm" | |
| rows={4} | |
| placeholder="Enter your custom prompt for Gemini..." | |
| /> | |
| <div className="flex justify-end mt-2 space-x-2"> | |
| <span className="text-xs text-gray-500 self-center mr-auto"> | |
| Tip: Press {isMac ? '⌘' : 'Ctrl'}+Enter to save | |
| </span> | |
| <button | |
| onClick={handleCancel} | |
| className="px-4 py-2 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-100 min-w-[60px]" | |
| > | |
| Cancel | |
| </button> | |
| <button | |
| onClick={handleSave} | |
| className="px-4 py-2 text-sm text-white bg-blue-600 rounded-md hover:bg-blue-700 min-w-[60px]" | |
| > | |
| Save | |
| </button> | |
| </div> | |
| </div> | |
| ) : ( | |
| <div className="p-3 bg-gray-50 border border-gray-200 rounded-lg text-sm text-gray-800 whitespace-pre-wrap"> | |
| {customPrompt} | |
| </div> | |
| )} | |
| </> | |
| )} | |
| </div> | |
| ); | |
| }; | |
| export default PromptEditor; |