[dyad] Fixed unresponsive buttons - wrote 1 file(s)
This commit is contained in:
@@ -267,130 +267,120 @@ export function ImageConverter() {
|
|||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 w-full">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 w-full">
|
||||||
<div className="lg:col-span-1 flex flex-col gap-8">
|
<div className="lg:col-span-1 flex flex-col gap-8">
|
||||||
<Accordion type="single" collapsible defaultValue="image-settings" className="w-full">
|
<Accordion type="single" collapsible defaultValue="image-settings" className="w-full space-y-8">
|
||||||
<div className="space-y-8">
|
<AccordionItem value="image-settings" className="border rounded-lg bg-card">
|
||||||
<Card>
|
<AccordionTrigger className="p-6 hover:no-underline">
|
||||||
<AccordionItem value="image-settings" className="border-none">
|
<div className="text-left">
|
||||||
<AccordionTrigger className="p-6 hover:no-underline">
|
<h3 className="text-lg font-medium leading-none">Image Settings</h3>
|
||||||
<div className="text-left">
|
<p className="text-sm text-muted-foreground mt-1">
|
||||||
<CardTitle>Image Settings</CardTitle>
|
Adjust resolution for all uploaded images.
|
||||||
<CardDescription className="mt-1">
|
</p>
|
||||||
Adjust resolution for all uploaded images.
|
</div>
|
||||||
</CardDescription>
|
</AccordionTrigger>
|
||||||
</div>
|
<AccordionContent className="px-6 pb-6">
|
||||||
</AccordionTrigger>
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
<AccordionContent className="px-6 pb-6">
|
<div className="space-y-2">
|
||||||
<div className="space-y-6">
|
<Label htmlFor="width">Width (px)</Label>
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
<Input id="width" type="number" placeholder="e.g., 1920" value={width} onChange={(e) => setWidth(e.target.value)} />
|
||||||
<div className="space-y-2">
|
</div>
|
||||||
<Label htmlFor="width">Width (px)</Label>
|
<div className="space-y-2">
|
||||||
<Input id="width" type="number" placeholder="e.g., 1920" value={width} onChange={(e) => setWidth(e.target.value)} />
|
<Label htmlFor="height">Height (px)</Label>
|
||||||
</div>
|
<Input id="height" type="number" placeholder="e.g., 1080" value={height} onChange={(e) => setHeight(e.target.value)} />
|
||||||
<div className="space-y-2">
|
</div>
|
||||||
<Label htmlFor="height">Height (px)</Label>
|
</div>
|
||||||
<Input id="height" type="number" placeholder="e.g., 1080" value={height} onChange={(e) => setHeight(e.target.value)} />
|
</AccordionContent>
|
||||||
</div>
|
</AccordionItem>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
<AccordionItem value="filename-settings" className="border rounded-lg bg-card">
|
||||||
<AccordionItem value="filename-settings" className="border-none">
|
<AccordionTrigger className="p-6 hover:no-underline">
|
||||||
<AccordionTrigger className="p-6 hover:no-underline">
|
<div className="text-left">
|
||||||
<div className="text-left">
|
<h3 className="text-lg font-medium leading-none">Filename Settings</h3>
|
||||||
<CardTitle>Filename Settings</CardTitle>
|
<p className="text-sm text-muted-foreground mt-1">Customize the output filenames.</p>
|
||||||
<CardDescription className="mt-1">Customize the output filenames.</CardDescription>
|
</div>
|
||||||
</div>
|
</AccordionTrigger>
|
||||||
</AccordionTrigger>
|
<AccordionContent className="px-6 pb-6">
|
||||||
<AccordionContent className="px-6 pb-6">
|
<div className="space-y-6">
|
||||||
<div className="space-y-6">
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="prefix">Prefix</Label>
|
||||||
|
<Input id="prefix" placeholder="e.g., travel-" value={prefix} onChange={(e) => setPrefix(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="suffix">Suffix</Label>
|
||||||
|
<Input id="suffix" placeholder="e.g., -edit" value={suffix} onChange={(e) => setSuffix(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2 pt-2">
|
||||||
|
<Switch id="use-counter" checked={useCounter} onCheckedChange={setUseCounter} />
|
||||||
|
<Label htmlFor="use-counter">Add sequential number</Label>
|
||||||
|
</div>
|
||||||
|
{useCounter && (
|
||||||
|
<div className="grid grid-cols-2 gap-4 pt-2">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label htmlFor="prefix">Prefix</Label>
|
<Label htmlFor="counter-start">Start number</Label>
|
||||||
<Input id="prefix" placeholder="e.g., travel-" value={prefix} onChange={(e) => setPrefix(e.target.value)} />
|
<Input
|
||||||
</div>
|
id="counter-start"
|
||||||
<div className="space-y-2">
|
type="number"
|
||||||
<Label htmlFor="suffix">Suffix</Label>
|
value={counterStart}
|
||||||
<Input id="suffix" placeholder="e.g., -edit" value={suffix} onChange={(e) => setSuffix(e.target.value)} />
|
onChange={(e) => setCounterStart(Math.max(0, Number(e.target.value)))}
|
||||||
</div>
|
min="0"
|
||||||
<div className="flex items-center space-x-2 pt-2">
|
/>
|
||||||
<Switch id="use-counter" checked={useCounter} onCheckedChange={setUseCounter} />
|
</div>
|
||||||
<Label htmlFor="use-counter">Add sequential number</Label>
|
<div className="space-y-2">
|
||||||
</div>
|
<Label htmlFor="counter-digits">Padding digits</Label>
|
||||||
{useCounter && (
|
<Input
|
||||||
<div className="grid grid-cols-2 gap-4 pt-2">
|
id="counter-digits"
|
||||||
<div className="space-y-2">
|
type="number"
|
||||||
<Label htmlFor="counter-start">Start number</Label>
|
value={counterDigits}
|
||||||
<Input
|
onChange={(e) => setCounterDigits(Math.max(1, Number(e.target.value)))}
|
||||||
id="counter-start"
|
min="1"
|
||||||
type="number"
|
|
||||||
value={counterStart}
|
|
||||||
onChange={(e) => setCounterStart(Math.max(0, Number(e.target.value)))}
|
|
||||||
min="0"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="counter-digits">Padding digits</Label>
|
|
||||||
<Input
|
|
||||||
id="counter-digits"
|
|
||||||
type="number"
|
|
||||||
value={counterDigits}
|
|
||||||
onChange={(e) => setCounterDigits(Math.max(1, Number(e.target.value)))}
|
|
||||||
min="1"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<AccordionItem value="quality-settings" className="border-none">
|
|
||||||
<AccordionTrigger className="p-6 hover:no-underline">
|
|
||||||
<div className="text-left">
|
|
||||||
<CardTitle>Quality Settings</CardTitle>
|
|
||||||
<CardDescription className="mt-1">Choose format and compression level.</CardDescription>
|
|
||||||
</div>
|
|
||||||
</AccordionTrigger>
|
|
||||||
<AccordionContent className="px-6 pb-6">
|
|
||||||
<div className="space-y-6">
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label htmlFor="format">Format</Label>
|
|
||||||
<Select value={format} onValueChange={(value: "png" | "jpeg" | "webp") => setFormat(value)}>
|
|
||||||
<SelectTrigger id="format"><SelectValue placeholder="Select format" /></SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="png">PNG</SelectItem>
|
|
||||||
<SelectItem value="jpeg">JPEG</SelectItem>
|
|
||||||
<SelectItem value="webp">WEBP</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2">
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<Label htmlFor="quality">Quality</Label>
|
|
||||||
<span className="text-sm text-muted-foreground">{quality}%</span>
|
|
||||||
</div>
|
|
||||||
<Slider
|
|
||||||
id="quality"
|
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
step={1}
|
|
||||||
value={[quality]}
|
|
||||||
onValueChange={(value) => setQuality(value[0])}
|
|
||||||
disabled={format === 'png'}
|
|
||||||
/>
|
/>
|
||||||
{format === 'png' && (
|
|
||||||
<p className="text-xs text-muted-foreground pt-1">Quality slider is disabled for PNG (lossless format).</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AccordionContent>
|
)}
|
||||||
</AccordionItem>
|
</div>
|
||||||
</Card>
|
</AccordionContent>
|
||||||
</div>
|
</AccordionItem>
|
||||||
|
|
||||||
|
<AccordionItem value="quality-settings" className="border rounded-lg bg-card">
|
||||||
|
<AccordionTrigger className="p-6 hover:no-underline">
|
||||||
|
<div className="text-left">
|
||||||
|
<h3 className="text-lg font-medium leading-none">Quality Settings</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mt-1">Choose format and compression level.</p>
|
||||||
|
</div>
|
||||||
|
</AccordionTrigger>
|
||||||
|
<AccordionContent className="px-6 pb-6">
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="space-y-2">
|
||||||
|
<Label htmlFor="format">Format</Label>
|
||||||
|
<Select value={format} onValueChange={(value: "png" | "jpeg" | "webp") => setFormat(value)}>
|
||||||
|
<SelectTrigger id="format"><SelectValue placeholder="Select format" /></SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="png">PNG</SelectItem>
|
||||||
|
<SelectItem value="jpeg">JPEG</SelectItem>
|
||||||
|
<SelectItem value="webp">WEBP</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<Label htmlFor="quality">Quality</Label>
|
||||||
|
<span className="text-sm text-muted-foreground">{quality}%</span>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
id="quality"
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
step={1}
|
||||||
|
value={[quality]}
|
||||||
|
onValueChange={(value) => setQuality(value[0])}
|
||||||
|
disabled={format === 'png'}
|
||||||
|
/>
|
||||||
|
{format === 'png' && (
|
||||||
|
<p className="text-xs text-muted-foreground pt-1">Quality slider is disabled for PNG (lossless format).</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccordionContent>
|
||||||
|
</AccordionItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleConvertAndDownload}
|
onClick={handleConvertAndDownload}
|
||||||
|
|||||||
Reference in New Issue
Block a user