import * as React from "react";
import {
ControlInlineGroup,
ControlList,
Field,
FieldLabel,
Input,
Select,
type ControlChangeMeta,
} from "@repo/ui";
import { toolcraftCanvasAspectRatioPresets } from "../../../schema/canvas-aspect-ratio-presets";
import {
asCanvasAspectRatioValue,
parseCanvasAspectRatioOption,
type CanvasAspectRatioValue,
} from "../values/controls-panel-aspect-ratio-values";
const options = [
...toolcraftCanvasAspectRatioPresets.map(({ value }) => ({ label: value, value })),
{ label: "Custom", value: "custom" },
];
function RatioPart({
axis,
value,
onCommit,
}: {
axis: "width" | "height";
value: number;
onCommit: (value: number) => void;
}): React.JSX.Element {
const id = React.useId();
const [draft, setDraft] = React.useState(String(value));
const skipBlur = React.useRef(false);
React.useEffect(() => setDraft(String(value)), [value]);
function commit(): void {
const next = Number(draft);
if (!draft.trim() || !Number.isSafeInteger(next) || next <= 0) {
setDraft(String(value));
return;
}
setDraft(String(next));
if (next !== value) onCommit(next);
}
return (
{axis === "width" ? "Ratio W" : "Ratio H"}
{
if (!skipBlur.current) commit();
skipBlur.current = false;
}}
onChange={(event) => setDraft(event.target.value)}
onFocus={() => { skipBlur.current = false; }}
onKeyDown={(event) => {
if (event.key !== "Enter" && event.key !== "Escape") return;
event.preventDefault();
if (event.key === "Enter") commit();
else setDraft(String(value));
skipBlur.current = true;
event.currentTarget.blur();
}}
value={draft}
/>
);
}
export function CanvasAspectRatioControl({
defaultValue,
name,
onValueChange,
value,
}: {
defaultValue: unknown;
name: string;
onValueChange?: (value: CanvasAspectRatioValue, meta?: ControlChangeMeta) => void;
value: unknown;
}): React.JSX.Element {
const ratio = asCanvasAspectRatioValue(value, defaultValue);
function updatePreset(next: string): void {
const nextRatio = next === "custom"
? { ...ratio, mode: "custom" as const, value: `${ratio.width}:${ratio.height}` }
: parseCanvasAspectRatioOption(next);
if (nextRatio) onValueChange?.(nextRatio);
}
function updatePart(axis: "width" | "height", next: number): void {
const parts = { width: ratio.width, height: ratio.height, [axis]: next };
onValueChange?.({ ...parts, mode: "custom", value: `${parts.width}:${parts.height}` });
}
return (
{ratio.mode === "custom" ? (
updatePart("width", next)} />
updatePart("height", next)} />
) : null}
);
}