| | 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); |
| |
|
| | |
| | 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; |