'use client'; import { type ReactNode, createContext, useContext, useState } from 'react'; import { cn } from '@udecode/cn'; import { CopilotPlugin } from '@udecode/plate-ai/react'; import { useEditorPlugin } from '@udecode/plate/react'; import { Check, ChevronsUpDown, ExternalLinkIcon, Eye, EyeOff, Settings, Wand2Icon, } from 'lucide-react'; import { Button } from '@plone/plate/components/plate-ui/button'; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from '@plone/plate/components/plate-ui/command'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '@plone/plate/components/plate-ui/dialog'; import { Input } from '@plone/plate/components/plate-ui/input'; import { Popover, PopoverContent, PopoverTrigger, } from '@plone/plate/components/plate-ui/popover'; interface Model { label: string; value: string; } interface SettingsContextType { keys: Record; model: Model; setKey: (service: string, key: string) => void; setModel: (model: Model) => void; } export const models: Model[] = [ { label: 'gpt-4o-mini', value: 'gpt-4o-mini' }, { label: 'gpt-4o', value: 'gpt-4o' }, { label: 'gpt-4-turbo', value: 'gpt-4-turbo' }, { label: 'gpt-4', value: 'gpt-4' }, { label: 'gpt-3.5-turbo', value: 'gpt-3.5-turbo' }, { label: 'gpt-3.5-turbo-instruct', value: 'gpt-3.5-turbo-instruct' }, ]; const SettingsContext = createContext( undefined, ); export function SettingsProvider({ children }: { children: ReactNode }) { const [keys, setKeys] = useState({ openai: '', uploadthing: '', }); const [model, setModel] = useState(models[0]); const setKey = (service: string, key: string) => { setKeys((prev) => ({ ...prev, [service]: key })); }; return ( {children} ); } export function useSettings() { const context = useContext(SettingsContext); return ( context ?? { keys: { openai: '', uploadthing: '', }, model: models[0], setKey: () => {}, setModel: () => {}, } ); } export function SettingsDialog() { const { keys, model, setKey, setModel } = useSettings(); const [tempKeys, setTempKeys] = useState(keys); const [showKey, setShowKey] = useState>({}); const [open, setOpen] = useState(false); const [openModel, setOpenModel] = useState(false); const { getOptions, setOption } = useEditorPlugin(CopilotPlugin); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); Object.entries(tempKeys).forEach(([service, key]) => { setKey(service, key); }); setOpen(false); // Update AI options if needed const completeOptions = getOptions().completeOptions ?? {}; setOption('completeOptions', { ...completeOptions, body: { ...completeOptions.body, apiKey: tempKeys.openai, model: model.value, }, }); }; const toggleKeyVisibility = (key: string) => { setShowKey((prev) => ({ ...prev, [key]: !prev[key] })); }; const renderApiKeyInput = (service: string, label: string) => (
setTempKeys((prev) => ({ ...prev, [service]: e.target.value })) } placeholder="" data-1p-ignore type={showKey[service] ? 'text' : 'password'} />
); return ( Settings Configure your API keys and preferences.
{/* AI Settings Group */}

AI

{renderApiKeyInput('openai', 'OpenAI API key')}
No model found. {models.map((m) => ( { setModel(m); setOpenModel(false); }} > {m.label} ))}
{/* Upload Settings Group */} {/*

Upload

{renderApiKeyInput('uploadthing', 'Uploadthing API key')}
*/}

Not stored anywhere. Used only for current session requests.

); }