Files
playground/frontend/components/image-config.tsx
2025-11-26 19:00:04 +00:00

116 lines
3.7 KiB
TypeScript

'use client';
import { aspectRatioSizes, isValidAspectRatio } from '@/lib/google-ai';
interface ImageConfigProps {
model: string;
aspectRatio: string;
onAspectRatioChange: (ratio: string) => void;
numberOfImages: number;
onNumberOfImagesChange: (num: number) => void;
negativePrompt: string;
onNegativePromptChange: (prompt: string) => void;
safetyLevel: 'block_none' | 'block_some' | 'block_most';
onSafetyLevelChange: (level: 'block_none' | 'block_some' | 'block_most') => void;
}
export function ImageConfig({
model,
aspectRatio,
onAspectRatioChange,
numberOfImages,
onNumberOfImagesChange,
negativePrompt,
onNegativePromptChange,
safetyLevel,
onSafetyLevelChange,
}: ImageConfigProps) {
const availableRatios = Object.keys(aspectRatioSizes);
const size = aspectRatioSizes[aspectRatio];
return (
<div className="space-y-4">
<h3 className="text-sm font-medium text-foreground">Configuración de Imagen</h3>
{/* Aspect Ratio */}
<div className="space-y-2">
<label className="text-xs font-medium text-muted-foreground">
Aspect Ratio
</label>
<div className="grid grid-cols-5 gap-2">
{availableRatios.map((ratio) => (
<button
key={ratio}
onClick={() => onAspectRatioChange(ratio)}
disabled={!isValidAspectRatio(model, ratio) && !model.startsWith('gemini')}
className={`
px-3 py-2 text-xs rounded-lg font-medium transition-all
${aspectRatio === ratio
? 'bg-primary text-primary-foreground'
: 'bg-secondary hover:bg-accent'
}
${!isValidAspectRatio(model, ratio) && !model.startsWith('gemini')
? 'opacity-50 cursor-not-allowed'
: ''
}
`}
>
{ratio}
</button>
))}
</div>
{size && (
<p className="text-xs text-muted-foreground">
Dimensiones: {size.width}x{size.height}px
</p>
)}
</div>
{/* Número de imágenes */}
<div className="space-y-2">
<label className="text-xs font-medium text-muted-foreground">
Número de imágenes: {numberOfImages}
</label>
<input
type="range"
min="1"
max="4"
value={numberOfImages}
onChange={(e) => onNumberOfImagesChange(parseInt(e.target.value))}
className="w-full"
/>
</div>
{/* Negative Prompt */}
<div className="space-y-2">
<label className="text-xs font-medium text-muted-foreground">
Negative Prompt (opcional)
</label>
<textarea
value={negativePrompt}
onChange={(e) => onNegativePromptChange(e.target.value)}
placeholder="Elementos que NO quieres en la imagen..."
className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary resize-none"
rows={2}
/>
</div>
{/* Safety Level */}
<div className="space-y-2">
<label className="text-xs font-medium text-muted-foreground">
Nivel de Seguridad
</label>
<select
value={safetyLevel}
onChange={(e) => onSafetyLevelChange(e.target.value as any)}
className="w-full px-3 py-2 bg-secondary border border-border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-primary"
>
<option value="block_none">Sin bloqueo</option>
<option value="block_some">Bloqueo moderado</option>
<option value="block_most">Bloqueo alto</option>
</select>
</div>
</div>
);
}