/* Copyright (C) 2023-2026 QuantumNous This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ import { useState } from 'react' import { PaperclipIcon, FileIcon, ImageIcon, ScreenShareIcon, CameraIcon, GlobeIcon, SendIcon, SquareIcon, BarChartIcon, BoxIcon, NotepadTextIcon, CodeSquareIcon, GraduationCapIcon, } from 'lucide-react' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { PromptInput, PromptInputButton, PromptInputFooter, PromptInputTextarea, PromptInputTools, type PromptInputMessage, } from '@/components/ai-elements/prompt-input' import { Suggestion, Suggestions } from '@/components/ai-elements/suggestion' import { ModelGroupSelector } from '@/components/model-group-selector' import type { ModelOption, GroupOption } from '../types' interface PlaygroundInputProps { onSubmit: (text: string) => void onStop?: () => void disabled?: boolean isGenerating?: boolean models: ModelOption[] modelValue: string onModelChange: (value: string) => void isModelLoading?: boolean groups: GroupOption[] groupValue: string onGroupChange: (value: string) => void } const suggestions = [ { icon: BarChartIcon, text: 'Analyze data', color: '#76d0eb' }, { icon: BoxIcon, text: 'Surprise me', color: '#76d0eb' }, { icon: NotepadTextIcon, text: 'Summarize text', color: '#ea8444' }, { icon: CodeSquareIcon, text: 'Code', color: '#6c71ff' }, { icon: GraduationCapIcon, text: 'Get advice', color: '#76d0eb' }, { icon: null, text: 'More' }, ] export function PlaygroundInput({ onSubmit, onStop, disabled, isGenerating, models, modelValue, onModelChange, isModelLoading = false, groups, groupValue, onGroupChange, }: PlaygroundInputProps) { const { t } = useTranslation() const [text, setText] = useState('') const isModelSelectDisabled = disabled || isModelLoading || models.length === 0 const isGroupSelectDisabled = disabled || groups.length === 0 const handleSubmit = (message: PromptInputMessage) => { if (!message.text?.trim() || disabled) return onSubmit(message.text) setText('') } const handleFileAction = (action: string) => { toast.info(t('Feature in development'), { description: action, }) } const handleSuggestionClick = (suggestion: string) => { onSubmit(suggestion) } return (
setText(event.target.value)} placeholder={t('Ask anything')} value={text} /> } > {t('Attach')} {t('Attach')} handleFileAction('upload-file')} > {t('Upload file')} handleFileAction('upload-photo')} > {t('Upload photo')} handleFileAction('take-screenshot')} > {t('Take screenshot')} handleFileAction('take-photo')} > {t('Take photo')} toast.info(t('Search feature in development'))} variant='outline' > {t('Search')} {t('Search')}
{isGenerating && onStop ? ( {t('Stop')} {t('Stop')} ) : ( {t('Send')} {t('Send')} )}
{suggestions.map(({ icon: Icon, text, color }) => ( handleSuggestionClick(text)} suggestion={text} > {Icon && } {text} ))}
) }