phase 2 complete

This commit is contained in:
Oliver Bryan
2026-01-08 10:47:48 +00:00
parent 77a9b32841
commit e5a7030d9b
10 changed files with 232 additions and 132 deletions

View File

@@ -0,0 +1,53 @@
import { useState, useEffect, useRef } from "react";
import type { ShapeState } from "@/types/shape";
const DEFAULT_STATE: ShapeState = {
x: 0,
y: 0,
preset: "circle",
roundness: 100, // full circle
size: 50, // medium
wobble: 20, // subtle
wobbleSpeed: 50, // medium
grain: 0, // none
color: "#FF0000", // red (C)
octave: 4, // middle octave
};
export function useShapeState(centerX: number, centerY: number) {
const [state, setState] = useState<ShapeState>({
...DEFAULT_STATE,
x: centerX,
y: centerY,
});
const initialStateRef = useRef<ShapeState>({
...DEFAULT_STATE,
x: centerX,
y: centerY,
});
// update center position when canvas resizes
useEffect(() => {
setState((prev) => ({
...prev,
x: centerX,
y: centerY,
}));
}, [centerX, centerY]);
// beforeunload warning
useEffect(() => {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
const hasChanged = JSON.stringify(state) !== JSON.stringify(initialStateRef.current);
if (hasChanged) {
e.preventDefault();
}
};
window.addEventListener("beforeunload", handleBeforeUnload);
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
}, [state]);
return [state, setState] as const;
}