Format presets included: **Video Presets:** - YouTube Video (1080p, H.264, optimized) - Instagram Video (Square format, 1:1) - Twitter Video (720p, small file) - Web Optimized (Streaming, low bitrate) **Audio Presets:** - Podcast (MP3, voice optimized, 128k) - High Quality Music (MP3, 320k) - Audiobook (Mono, 64k, small size) **Image Presets:** - Web Thumbnail (JPG, 800px width) - HD Image (PNG, lossless, high quality) - Social Media (JPG, 1200px, optimized) - Web Optimized (WebP, small size) Implementation: - Created formatPresets.ts with 11 predefined presets - FormatPresets component with responsive grid layout - One-click preset application - Automatically configures format and options - Toast notification on preset selection - Visual feedback with ring highlight - Organized by category (video/audio/image) - Emoji icons for visual appeal User experience: - Quick access to common conversion scenarios - No need to manually configure complex settings - Preset descriptions explain use case - Disabled during active conversion - Clear visual indication of selected preset 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
68 lines
2.3 KiB
TypeScript
68 lines
2.3 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { Sparkles } from 'lucide-react';
|
|
import { Card } from '@/components/ui/Card';
|
|
import { Button } from '@/components/ui/Button';
|
|
import { cn } from '@/lib/utils/cn';
|
|
import { getPresetsByCategory, type FormatPreset } from '@/lib/utils/formatPresets';
|
|
import type { ConversionFormat } from '@/types/conversion';
|
|
|
|
interface FormatPresetsProps {
|
|
inputFormat: ConversionFormat;
|
|
onPresetSelect: (preset: FormatPreset) => void;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
export function FormatPresets({ inputFormat, onPresetSelect, disabled = false }: FormatPresetsProps) {
|
|
const [selectedPresetId, setSelectedPresetId] = React.useState<string | null>(null);
|
|
|
|
// Get presets for the input format's category
|
|
const presets = getPresetsByCategory(inputFormat.category);
|
|
|
|
if (presets.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const handlePresetClick = (preset: FormatPreset) => {
|
|
setSelectedPresetId(preset.id);
|
|
onPresetSelect(preset);
|
|
};
|
|
|
|
return (
|
|
<Card className="p-4">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<Sparkles className="h-5 w-5 text-primary" />
|
|
<h3 className="text-sm font-semibold">Quick Presets</h3>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
|
{presets.map((preset) => (
|
|
<Button
|
|
key={preset.id}
|
|
onClick={() => handlePresetClick(preset)}
|
|
variant={selectedPresetId === preset.id ? 'default' : 'outline'}
|
|
className={cn(
|
|
'h-auto py-4 px-4 flex flex-col items-start text-left gap-2',
|
|
selectedPresetId === preset.id && 'ring-2 ring-primary ring-offset-2'
|
|
)}
|
|
disabled={disabled}
|
|
>
|
|
<div className="flex items-center gap-2 w-full">
|
|
<span className="text-2xl">{preset.icon}</span>
|
|
<div className="flex-1 min-w-0">
|
|
<div className="font-semibold text-sm">{preset.name}</div>
|
|
</div>
|
|
</div>
|
|
<p className="text-xs text-muted-foreground w-full">{preset.description}</p>
|
|
</Button>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mt-3 text-xs text-muted-foreground">
|
|
Select a preset to automatically configure optimal settings for your use case
|
|
</div>
|
|
</Card>
|
|
);
|
|
}
|