diff --git a/src/PCBViewer.tsx b/src/PCBViewer.tsx index 6ce85371..ef37ff24 100644 --- a/src/PCBViewer.tsx +++ b/src/PCBViewer.tsx @@ -12,7 +12,6 @@ import useMouseMatrixTransform from "use-mouse-matrix-transform" import { CanvasElementsRenderer } from "./components/CanvasElementsRenderer" import type { ManualEditEvent } from "@tscircuit/props" import { zIndexMap } from "lib/util/z-index-map" -import { calculateCircuitJsonKey } from "lib/calculate-circuit-json-key" const defaultTransform = compose(translate(400, 300), scale(40, -40)) @@ -61,10 +60,32 @@ export const PCBViewer = ({ const initialRenderCompleted = useRef(false) const touchStartRef = useRef<{ x: number; y: number } | null>(null) - const circuitJsonKey = useMemo( - () => calculateCircuitJsonKey(circuitJson), - [circuitJson], - ) + + const pcbElmsPreEdit = useMemo(() => { + return ( + circuitJson?.filter( + (e: any) => e.type.startsWith("pcb_") || e.type.startsWith("source_"), + ) ?? [] + ) + }, [circuitJson]) + + const elements = useMemo(() => { + return applyEditEvents({ + circuitJson: pcbElmsPreEdit as any, + editEvents, + }) + }, [pcbElmsPreEdit, editEvents]) + + // Track the pcb_board element's explicit width/height + const boardDimensions = useMemo(() => { + const pcbBoard = elements.find((e) => e.type === "pcb_board") as any + if (!pcbBoard?.width || !pcbBoard?.height) return null + return { width: pcbBoard.width, height: pcbBoard.height } + }, [elements]) + + // Extract width/height as primitives to avoid object reference changes triggering useEffect + const boardWidth = boardDimensions?.width ?? null + const boardHeight = boardDimensions?.height ?? null const resetTransform = () => { const elmBounds = @@ -93,31 +114,29 @@ export const PCBViewer = ({ return } + useEffect(() => { + if (initialRenderCompleted.current === true) { + resetTransform() + } + }, [ + boardWidth, + boardHeight, + elements + .filter((e) => e.type === "pcb_board") + .flatMap((e: any) => [e.center?.x ?? 0, e.center?.y ?? 0]) + .join(","), + ]) + useEffect(() => { if (!refDimensions?.width) return - if (!circuitJson) return - if (circuitJson.length === 0) return + if (boardWidth === null || boardHeight === null) return if (!initialRenderCompleted.current) { resetTransform() initialRenderCompleted.current = true + return } - }, [circuitJson, refDimensions]) - - const pcbElmsPreEdit = useMemo(() => { - return ( - circuitJson?.filter( - (e: any) => e.type.startsWith("pcb_") || e.type.startsWith("source_"), - ) ?? [] - ) - }, [circuitJsonKey]) - - const elements = useMemo(() => { - return applyEditEvents({ - circuitJson: pcbElmsPreEdit as any, - editEvents, - }) - }, [pcbElmsPreEdit, editEvents]) + }, [boardWidth, boardHeight, refDimensions]) const onCreateEditEvent = (event: ManualEditEvent) => { setEditEvents([...editEvents, event]) diff --git a/src/examples/board-resize-test.fixture.tsx b/src/examples/board-resize-test.fixture.tsx new file mode 100644 index 00000000..0e099307 --- /dev/null +++ b/src/examples/board-resize-test.fixture.tsx @@ -0,0 +1,89 @@ +import { Circuit } from "@tscircuit/core" +import { PCBViewer } from "../PCBViewer" +import { useState, useMemo } from "react" + +export const BoardResizeTest = () => { + const [boardSize, setBoardSize] = useState<"small" | "medium" | "large">( + "small", + ) + const [showComponent, setShowComponent] = useState(false) + + // Generate circuit JSON for each board size - memoized to avoid recreation + const soup = useMemo(() => { + const circuit = new Circuit() + + const sizes = { + small: { width: "10mm", height: "10mm" }, + medium: { width: "30mm", height: "30mm" }, + large: { width: "60mm", height: "60mm" }, + } + + circuit.add( + + + {boardSize === "medium" && showComponent && ( + + )} + {boardSize === "large" && ( + <> + + + + )} + , + ) + + return circuit.getCircuitJson() + }, [boardSize, showComponent]) + + return ( +
+
+ + + + Current: {boardSize} + {boardSize === "medium" && ( + + )} +
+
+ +
+
+ ) +} + +export default BoardResizeTest