mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(rotate): add editable angle input and fine-tune +/- buttons
Replace the static angle display between Left/Right buttons with an editable input field that accepts direct angle entry. Add - and + buttons for 1-degree fine-tuned control. All controls update the rotation state which triggers real-time CSS preview on the image.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { FlipHorizontal, FlipVertical, RotateCcw, RotateCw } from "lucide-react";
|
||||
import { FlipHorizontal, FlipVertical, Minus, Plus, RotateCcw, RotateCw } from "lucide-react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { ProgressCard } from "@/components/common/progress-card";
|
||||
import { useToolProcessor } from "@/hooks/use-tool-processor";
|
||||
@@ -44,9 +44,30 @@ export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
|
||||
prevProcessing.current = processing;
|
||||
}, [processing, error]);
|
||||
|
||||
// Display angle normalized to 0-359
|
||||
const displayAngle = ((totalAngle % 360) + 360) % 360;
|
||||
|
||||
const [angleInput, setAngleInput] = useState(String(displayAngle));
|
||||
const prevDisplayAngle = useRef(displayAngle);
|
||||
if (prevDisplayAngle.current !== displayAngle) {
|
||||
prevDisplayAngle.current = displayAngle;
|
||||
setAngleInput(String(displayAngle));
|
||||
}
|
||||
|
||||
const rotateLeft = () => setRotation((r) => r - 90);
|
||||
const rotateRight = () => setRotation((r) => r + 90);
|
||||
|
||||
const commitAngleInput = () => {
|
||||
const parsed = Number.parseInt(angleInput, 10);
|
||||
if (!Number.isNaN(parsed)) {
|
||||
const normalized = ((parsed % 360) + 360) % 360;
|
||||
setAngleInput(String(normalized));
|
||||
setRotation(normalized - straighten);
|
||||
} else {
|
||||
setAngleInput(String(displayAngle));
|
||||
}
|
||||
};
|
||||
|
||||
const handleProcess = () => {
|
||||
const backendAngle = ((totalAngle % 360) + 360) % 360;
|
||||
const settings = {
|
||||
@@ -76,9 +97,6 @@ export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
|
||||
setFlipV(false);
|
||||
};
|
||||
|
||||
// Display angle normalized to 0-359
|
||||
const displayAngle = ((totalAngle % 360) + 360) % 360;
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
{/* Quick rotate */}
|
||||
@@ -94,9 +112,41 @@ export function RotateSettings({ onPreviewTransform }: RotateSettingsProps) {
|
||||
<RotateCcw className="h-4 w-4" />
|
||||
Left
|
||||
</button>
|
||||
<div className="px-3 py-1.5 rounded-md bg-background border border-border text-center min-w-[4rem]">
|
||||
<span className="text-sm font-mono font-medium tabular-nums">{displayAngle}°</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRotation((r) => r - 1)}
|
||||
className="p-2 rounded-lg bg-muted text-muted-foreground hover:bg-primary hover:text-primary-foreground transition-colors"
|
||||
title="Decrease 1°"
|
||||
>
|
||||
<Minus className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<div className="relative flex items-center">
|
||||
<input
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
value={angleInput}
|
||||
onChange={(e) => setAngleInput(e.target.value)}
|
||||
onBlur={commitAngleInput}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
commitAngleInput();
|
||||
}
|
||||
}}
|
||||
className="w-14 text-center text-sm font-mono font-medium tabular-nums py-1.5 rounded-md bg-background border border-border focus:outline-none focus:ring-2 focus:ring-primary/50 pr-4"
|
||||
/>
|
||||
<span className="absolute right-2 text-sm font-mono text-muted-foreground pointer-events-none">
|
||||
°
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setRotation((r) => r + 1)}
|
||||
className="p-2 rounded-lg bg-muted text-muted-foreground hover:bg-primary hover:text-primary-foreground transition-colors"
|
||||
title="Increase 1°"
|
||||
>
|
||||
<Plus className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={rotateRight}
|
||||
|
||||
Reference in New Issue
Block a user