File size: 4,539 Bytes
128b839 065d164 128b839 065d164 128b839 065d164 b4dece4 065d164 128b839 b4dece4 128b839 b4dece4 987ec04 065d164 128b839 987ec04 128b839 b4dece4 128b839 987ec04 b4dece4 987ec04 128b839 987ec04 128b839 b4dece4 128b839 b4dece4 987ec04 128b839 b4dece4 128b839 b4dece4 128b839 b4dece4 128b839 b4dece4 128b839 065d164 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
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; |