[dyad] Einstellungen bei Preset-Nutzung gesperrt - wrote 5 file(s)

This commit is contained in:
[dyad]
2026-01-19 10:36:38 +01:00
parent 917a8b5d48
commit ed032d247a
5 changed files with 43 additions and 23 deletions

View File

@@ -22,11 +22,15 @@ const positions: Position[] = [
interface ObjectPositionControlProps {
value: string;
onChange: (value: Position) => void;
disabled?: boolean;
}
export function ObjectPositionControl({ value, onChange }: ObjectPositionControlProps) {
export function ObjectPositionControl({ value, onChange, disabled = false }: ObjectPositionControlProps) {
return (
<div className="grid grid-cols-3 gap-px w-16 h-16 rounded-md border bg-border overflow-hidden">
<div className={cn(
"grid grid-cols-3 gap-px w-16 h-16 rounded-md border bg-border overflow-hidden",
disabled && "opacity-50 cursor-not-allowed"
)}>
{positions.map((pos) => (
<button
key={pos}
@@ -38,6 +42,7 @@ export function ObjectPositionControl({ value, onChange }: ObjectPositionControl
value === pos && "bg-accent"
)}
aria-label={`Set object position to ${pos.replace(' ', ' ')}`}
disabled={disabled}
>
<div
className={cn(

View File

@@ -1,5 +1,6 @@
"use client";
import { useState } from "react";
import { ConversionSettings } from "@/types";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import { ImageSettings } from "./settings/image-settings";
@@ -24,11 +25,17 @@ export function SettingsPanel({
onApplyDefaultBaseNameToAll,
hasImages,
}: SettingsPanelProps) {
const [presetsEnabled, setPresetsEnabled] = useState(false);
return (
<div className="space-y-4">
<PresetSettings onSettingsChange={onSettingsChange} />
<PresetSettings
onSettingsChange={onSettingsChange}
enabled={presetsEnabled}
onEnabledChange={setPresetsEnabled}
/>
<Accordion type="single" collapsible defaultValue="image-settings" className="w-full space-y-4">
<AccordionItem value="image-settings" className="border rounded-lg bg-card">
<AccordionItem value="image-settings" className="border rounded-lg bg-card" disabled={presetsEnabled}>
<AccordionTrigger className="p-6 hover:no-underline">
<div className="text-left">
<h3 className="text-lg font-medium leading-none">Bildeinstellungen</h3>
@@ -41,6 +48,7 @@ export function SettingsPanel({
onSettingsChange={onSettingsChange}
onAspectRatioChange={onAspectRatioChange}
onSwapDimensions={onSwapDimensions}
disabled={presetsEnabled}
/>
</AccordionContent>
</AccordionItem>
@@ -62,7 +70,7 @@ export function SettingsPanel({
</AccordionContent>
</AccordionItem>
<AccordionItem value="quality-settings" className="border rounded-lg bg-card">
<AccordionItem value="quality-settings" className="border rounded-lg bg-card" disabled={presetsEnabled}>
<AccordionTrigger className="p-6 hover:no-underline">
<div className="text-left">
<h3 className="text-lg font-medium leading-none">Qualitätseinstellungen</h3>
@@ -70,7 +78,11 @@ export function SettingsPanel({
</div>
</AccordionTrigger>
<AccordionContent className="px-6 pb-6">
<QualitySettings settings={settings} onSettingsChange={onSettingsChange} />
<QualitySettings
settings={settings}
onSettingsChange={onSettingsChange}
disabled={presetsEnabled}
/>
</AccordionContent>
</AccordionItem>
</Accordion>

View File

@@ -9,6 +9,7 @@ import { Checkbox } from "@/components/ui/checkbox";
import { ArrowRightLeft, HelpCircle } from "lucide-react";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { ObjectPositionControl } from "@/components/object-position-control";
import { cn } from "@/lib/utils";
const aspectRatios = [
{ name: "Benutzerdefiniert", value: "custom" },
@@ -23,6 +24,7 @@ interface ImageSettingsProps {
onSettingsChange: (settings: Partial<ConversionSettings>) => void;
onAspectRatioChange: (value: string) => void;
onSwapDimensions: () => void;
disabled?: boolean;
}
export function ImageSettings({
@@ -30,6 +32,7 @@ export function ImageSettings({
onSettingsChange,
onAspectRatioChange,
onSwapDimensions,
disabled = false,
}: ImageSettingsProps) {
return (
<div className="space-y-4">
@@ -41,7 +44,7 @@ export function ImageSettings({
<TooltipContent><p>Wählen Sie ein voreingestelltes Seitenverhältnis oder 'Benutzerdefiniert', um die Abmessungen manuell einzugeben.</p></TooltipContent>
</Tooltip>
</div>
<Select value={settings.aspectRatio} onValueChange={onAspectRatioChange}>
<Select value={settings.aspectRatio} onValueChange={onAspectRatioChange} disabled={disabled}>
<SelectTrigger id="aspect-ratio" className="mt-2"><SelectValue placeholder="Seitenverhältnis auswählen" /></SelectTrigger>
<SelectContent>
{aspectRatios.map((ratio) => (
@@ -59,11 +62,11 @@ export function ImageSettings({
<TooltipContent><p>Legen Sie die Ausgabebreite in Pixeln fest. Leer lassen, um die Originalbreite zu verwenden.</p></TooltipContent>
</Tooltip>
</div>
<Input id="width" type="number" placeholder="Auto" value={settings.width} onChange={(e) => { onSettingsChange({ width: e.target.value, aspectRatio: 'custom' }) }} />
<Input id="width" type="number" placeholder="Auto" value={settings.width} onChange={(e) => { onSettingsChange({ width: e.target.value, aspectRatio: 'custom' }) }} disabled={disabled} />
</div>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" onClick={onSwapDimensions} className="shrink-0" aria-label="Breite und Höhe tauschen">
<Button variant="outline" size="icon" onClick={onSwapDimensions} className="shrink-0" aria-label="Breite und Höhe tauschen" disabled={disabled}>
<ArrowRightLeft className="h-4 w-4" />
</Button>
</TooltipTrigger>
@@ -77,12 +80,12 @@ export function ImageSettings({
<TooltipContent><p>Legen Sie die Ausgabehöhe in Pixeln fest. Leer lassen, um die Originalhöhe zu verwenden.</p></TooltipContent>
</Tooltip>
</div>
<Input id="height" type="number" placeholder="Auto" value={settings.height} onChange={(e) => { onSettingsChange({ height: e.target.value, aspectRatio: 'custom' }) }} />
<Input id="height" type="number" placeholder="Auto" value={settings.height} onChange={(e) => { onSettingsChange({ height: e.target.value, aspectRatio: 'custom' }) }} disabled={disabled} />
</div>
</div>
<div className="flex items-center space-x-2 pt-2">
<Checkbox id="keep-orientation" checked={settings.keepOrientation} onCheckedChange={(checked) => onSettingsChange({ keepOrientation: Boolean(checked) })} />
<Label htmlFor="keep-orientation" className="cursor-pointer flex items-center gap-1.5">
<Checkbox id="keep-orientation" checked={settings.keepOrientation} onCheckedChange={(checked) => onSettingsChange({ keepOrientation: Boolean(checked) })} disabled={disabled} />
<Label htmlFor="keep-orientation" className={cn("cursor-pointer flex items-center gap-1.5", disabled && "cursor-not-allowed opacity-70")}>
Originalausrichtung beibehalten
<Tooltip>
<TooltipTrigger onClick={(e) => e.preventDefault()}><HelpCircle className="h-4 w-4 text-muted-foreground" /></TooltipTrigger>
@@ -98,7 +101,7 @@ export function ImageSettings({
<TooltipContent><p>Bestimmt, wie das Bild in die neuen Abmessungen passt.</p></TooltipContent>
</Tooltip>
</div>
<Select value={settings.scaleMode} onValueChange={(value) => onSettingsChange({ scaleMode: value as any })}>
<Select value={settings.scaleMode} onValueChange={(value) => onSettingsChange({ scaleMode: value as any })} disabled={disabled}>
<SelectTrigger id="scale-mode"><SelectValue placeholder="Skalierungsmodus auswählen" /></SelectTrigger>
<SelectContent>
<SelectItem value="fill">Füllen (strecken)</SelectItem>
@@ -116,7 +119,7 @@ export function ImageSettings({
<TooltipContent><p>Legt den Ankerpunkt für die Skalierung 'Abdecken' oder 'Enthalten' fest.</p></TooltipContent>
</Tooltip>
</div>
<ObjectPositionControl value={settings.objectPosition} onChange={(pos) => onSettingsChange({ objectPosition: pos as ObjectPosition })} />
<ObjectPositionControl value={settings.objectPosition} onChange={(pos) => onSettingsChange({ objectPosition: pos as ObjectPosition })} disabled={disabled} />
</div>
)}
</div>

View File

@@ -1,6 +1,5 @@
"use client";
import { useState } from "react";
import { ConversionSettings } from "@/types";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
@@ -30,11 +29,11 @@ const presets: Preset[] = [
interface PresetSettingsProps {
onSettingsChange: (settings: Partial<ConversionSettings>) => void;
enabled: boolean;
onEnabledChange: (enabled: boolean) => void;
}
export function PresetSettings({ onSettingsChange }: PresetSettingsProps) {
const [presetsEnabled, setPresetsEnabled] = useState(false);
export function PresetSettings({ onSettingsChange, enabled, onEnabledChange }: PresetSettingsProps) {
const handlePresetSelect = (presetName: string) => {
const selectedPreset = presets.find(p => p.name === presetName);
if (selectedPreset) {
@@ -51,10 +50,10 @@ export function PresetSettings({ onSettingsChange }: PresetSettingsProps) {
<CardTitle className="text-lg font-medium leading-none">Presets</CardTitle>
<p className="text-sm text-muted-foreground mt-1">Schnell gängige Einstellungen anwenden.</p>
</div>
<Switch id="enable-presets" checked={presetsEnabled} onCheckedChange={setPresetsEnabled} />
<Switch id="enable-presets" checked={enabled} onCheckedChange={onEnabledChange} />
</div>
</CardHeader>
{presetsEnabled && (
{enabled && (
<CardContent>
<div className="space-y-2">
<Label htmlFor="presets">Preset auswählen</Label>

View File

@@ -10,9 +10,10 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip
interface QualitySettingsProps {
settings: ConversionSettings;
onSettingsChange: (settings: Partial<ConversionSettings>) => void;
disabled?: boolean;
}
export function QualitySettings({ settings, onSettingsChange }: QualitySettingsProps) {
export function QualitySettings({ settings, onSettingsChange, disabled = false }: QualitySettingsProps) {
return (
<div className="space-y-6">
<div className="space-y-2">
@@ -23,7 +24,7 @@ export function QualitySettings({ settings, onSettingsChange }: QualitySettingsP
<TooltipContent><p>Wählen Sie das Ausgabedateiformat für die Bilder.</p></TooltipContent>
</Tooltip>
</div>
<Select value={settings.format} onValueChange={(value: ImageFormat) => onSettingsChange({ format: value })}>
<Select value={settings.format} onValueChange={(value: ImageFormat) => onSettingsChange({ format: value })} disabled={disabled}>
<SelectTrigger id="format"><SelectValue placeholder="Format auswählen" /></SelectTrigger>
<SelectContent>
<SelectItem value="png">PNG</SelectItem>
@@ -50,7 +51,7 @@ export function QualitySettings({ settings, onSettingsChange }: QualitySettingsP
step={1}
value={[settings.quality]}
onValueChange={(value) => onSettingsChange({ quality: value[0] })}
disabled={settings.format === 'png'}
disabled={disabled || settings.format === 'png'}
/>
{settings.format === 'png' && (
<p className="text-xs text-muted-foreground pt-1">Der Qualitätsregler ist für PNG (verlustfreies Format) deaktiviert.</p>