Skip to content

Refactor: split ResultPanel.tsx (2,276 lines) along its natural seams; unify the duplicated pen-snapping pipelines #102

Description

@dompm

ResultPanel.tsx mixes pure geometry, three drawing tools, keyboard handling, toolbar config, and overlay UI in one 2,276-line component. Beyond readability, the structure is actively producing bugs — most notably:

The pen tool has two separately-implemented ~150-line snapping pipelines — hover preview (updateHoverPoint, :703-842) vs click commit (:1034-1190). The click path applies an extra "ABSOLUTE SHIFT CONSTRAINT ENFORCER" (:1139-1180) that the hover path lacks, so when Shift-drawing near a crop edge or fraction line, the marker shows one point and the committed vertex lands somewhere else. The duplication guarantees future drift.

Extraction plan, in order of payoff

  1. utils/penSnapping.ts — lines 266-648 (getSquareSegmentDistance, simplifyPath, isStructuralCorner, findPenSnapTarget, getCanvasSnapping, findAlignmentGuides, findShiftAlignmentGuides, findLengthSnap) are pure functions with zero component coupling. Extract → unit-testable (nothing in the repo is tested today), ~400 lines gone.
  2. usePenTool() + <PenOverlay> — the pen state cluster, updateHoverPoint, the pointerdown pen branch, and the render block (:1789-1930). Design it so the click commit consumes the already-computed hover point instead of re-running a second pipeline — fixes the WYSIWYG bug by construction.
  3. useCanvasShortcuts(panel) — one shared hook replacing the near-duplicate keydown effects in ResultPanel (:922-990) and SheetPanel (:196-220), with modifier guards, panel scoping, and a single registration point (fixes the modifier/both-panels/ordering bugs filed separately).
  4. <PolygonEditHandles> — vertex/midpoint drag handles (:2034-2159) + the draggedCorner/draggedMidpoint/dragStartPolygon state cluster.
  5. <SolderPopover> (:1516-1626), toolbar tool definitions (:1404-1512, a static factory over t), onboarding cards (:1632-1666), lamp underlay (:1693-1749), and PieceOverlay to their own files. (DragHandle + getTooltipAnchor get deleted outright if Docked right-side inspector (replace floating piece-properties popover) #34 lands.)

Result: ResultPanel becomes a ~500-line orchestrator (viewport, tool dispatch, layer composition).

SheetPanel benefits from the same shortcuts hook and from de-duplicating its measure-tool init (the handleToolChange measure block at SheetPanel.tsx:377-403 vs the effect at :241-262 is exactly the duplication that let the forceTool ReferenceError rot unnoticed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions