187 lines
6.8 KiB
TypeScript
187 lines
6.8 KiB
TypeScript
"use client";
|
|
|
|
import { Label } from "@/components/ui/label";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Checkbox } from "@/components/ui/checkbox";
|
|
import { ObjectPositionControl } from "@/components/object-position-control";
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipTrigger,
|
|
} from "@/components/ui/tooltip";
|
|
import { ArrowRightLeft, HelpCircle } from "lucide-react";
|
|
import { useTranslations } from "next-intl";
|
|
import { ScaleMode } from "@/hooks/use-image-converter";
|
|
|
|
interface ImageSettingsProps {
|
|
aspectRatio: string;
|
|
onAspectRatioChange: (value: string) => void;
|
|
width: number | string;
|
|
onWidthChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
height: number | string;
|
|
onHeightChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
onSwapDimensions: () => void;
|
|
keepOrientation: boolean;
|
|
onKeepOrientationChange: (checked: boolean) => void;
|
|
scaleMode: ScaleMode;
|
|
onScaleModeChange: (value: ScaleMode) => void;
|
|
objectPosition: string;
|
|
onObjectPositionChange: (value: string) => void;
|
|
}
|
|
|
|
export function ImageSettings({
|
|
aspectRatio,
|
|
onAspectRatioChange,
|
|
width,
|
|
onWidthChange,
|
|
height,
|
|
onHeightChange,
|
|
onSwapDimensions,
|
|
keepOrientation,
|
|
onKeepOrientationChange,
|
|
scaleMode,
|
|
onScaleModeChange,
|
|
objectPosition,
|
|
onObjectPositionChange,
|
|
}: ImageSettingsProps) {
|
|
const t = useTranslations("ImageConverter");
|
|
|
|
const aspectRatios = [
|
|
{ name: t("customAspectRatio"), value: "custom" },
|
|
{ name: t("squareAspectRatio"), value: "1/1" },
|
|
{ name: t("standardAspectRatio"), value: "4/3" },
|
|
{ name: t("photoAspectRatio"), value: "3/2" },
|
|
{ name: t("widescreenAspectRatio"), value: "16/9" },
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<div className="space-y-4">
|
|
<div>
|
|
<div className="flex items-center gap-1.5">
|
|
<Label htmlFor="aspect-ratio">{t("aspectRatioLabel")}</Label>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("aspectRatioTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<Select value={aspectRatio} onValueChange={onAspectRatioChange}>
|
|
<SelectTrigger id="aspect-ratio" className="mt-2">
|
|
<SelectValue placeholder={t("aspectRatioLabel")} />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{aspectRatios.map((ratio) => (
|
|
<SelectItem key={ratio.value} value={ratio.value}>
|
|
{ratio.name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
<div className="flex items-end gap-2">
|
|
<div className="space-y-2 flex-1">
|
|
<div className="flex items-center gap-1.5">
|
|
<Label htmlFor="width">{t("widthLabel")}</Label>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("widthTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<Input id="width" type="number" placeholder={t("originalPlaceholder")} value={width} onChange={onWidthChange} />
|
|
</div>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button variant="outline" size="icon" onClick={onSwapDimensions} className="shrink-0" aria-label="Swap width and height">
|
|
<ArrowRightLeft className="h-4 w-4" />
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("swapDimensionsTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
<div className="space-y-2 flex-1">
|
|
<div className="flex items-center gap-1.5">
|
|
<Label htmlFor="height">{t("heightLabel")}</Label>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("heightTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<Input id="height" type="number" placeholder={t("originalPlaceholder")} value={height} onChange={onHeightChange} />
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center space-x-2 pt-2">
|
|
<Checkbox id="keep-orientation" checked={keepOrientation} onCheckedChange={(checked) => onKeepOrientationChange(Boolean(checked))} />
|
|
<Label htmlFor="keep-orientation" className="cursor-pointer flex items-center gap-1.5">
|
|
{t("keepOrientationLabel")}
|
|
<Tooltip>
|
|
<TooltipTrigger onClick={(e) => e.preventDefault()}>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("keepOrientationTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
<div className="mt-4 space-y-2">
|
|
<div className="flex items-center gap-1.5">
|
|
<Label htmlFor="scale-mode">{t("scalingLabel")}</Label>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("scalingTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<Select value={scaleMode} onValueChange={(value: ScaleMode) => onScaleModeChange(value)}>
|
|
<SelectTrigger id="scale-mode"><SelectValue placeholder={t("scalingLabel")} /></SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="fill">{t("scalingFill")}</SelectItem>
|
|
<SelectItem value="cover">{t("scalingCover")}</SelectItem>
|
|
<SelectItem value="contain">{t("scalingContain")}</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
{scaleMode !== 'fill' && (
|
|
<div className="mt-4 space-y-2">
|
|
<div className="flex items-center gap-1.5">
|
|
<Label>{t("positionLabel")}</Label>
|
|
<Tooltip>
|
|
<TooltipTrigger>
|
|
<HelpCircle className="h-4 w-4 text-muted-foreground" />
|
|
</TooltipTrigger>
|
|
<TooltipContent>
|
|
<p>{t("positionTooltip")}</p>
|
|
</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
<ObjectPositionControl value={objectPosition} onChange={onObjectPositionChange} />
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
} |