Editor has no path mirror/flip/rotate — no way to reflect a path horizontally, vertically, or rotate around its bounding box center #205
Labels
No labels
blocked:commit-ready-failed
blocked:gate-fetch
blocked:gate-lint
blocked:gate-plan
blocked:gate-research
blocked:needs-attention
blocked:needs-decision
blocked:needs-human
blocked:no-changes
blocked:verify-failed
bug
deferred
feature-request
in-progress
needs-decompose
needs-triage
quickfix
security/medium
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/Kimi_Agent_Brother_10_Digitizing_App#205
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Finding
grep -n 'mirror\|flip\b' src/pages/Editor.tsxreturns 0 hits for path operations (the matches are about ref-mirroring state, not path transforms).grep -n 'rotate\b' src/pages/Editor.tsxalso returns 0.The Editor allows:
It does NOT allow:
A user with a left-facing leaf path who wants a right-facing version has to redraw it or use manual node coordinate math.
src/components/workspace/ImageEditToolbar.tsxhas rotate 90°/180°/270° and flip-horizontal for the source image, but the Editor has no equivalent for vector paths.Where
src/pages/Editor.tsx(no path transform handlers)src/components/editor/EditorRightPanel.tsx(no mirror/rotate buttons)src/components/workspace/ImageEditToolbar.tsx(rotate/flip UI for raster)grep -n 'TRANSFORM_PATH' src/components/editor/returns 0Suggested fix shape
Add a "Transform" section to the right panel's "Path Properties" with three buttons:
onTransformPathdispatches aTRANSFORM_PATHaction that:(x, y) → (2*cx - x, y)for flipX;(x, y) → (x, 2*cy - y)for flipY; rotation matrix for rotate90controlIn/controlOutBezier handles (they get the same transform applied)The control point transform is the tricky part: the handles need to be transformed around the same center, not just the anchor points. The math is well-defined (rotation matrix is linear; reflection is affine); the implementation should be a single helper in
geometry.tsto keep it testable.Severity
Medium. Common operation in any vector editor; users expect it.
Discovered by
Gap analysis (2026-10-02) of editor path operations.
Related
ImageEditToolbar(the workspace-side raster transform) is the reference implementation for the UI shape.Shipped in
dd4c572onorigin/main. Right-panel Path Properties now has a Transform section with three buttons (Flip-H, Flip-V, Rotate-90° CW). Each transform pivots on the path's bbox center (anchor + control handles), so the mirror reflects in place rather than around the canvas origin. Bézier controlIn/controlOut ride along with their anchors so curvature is preserved.Multi-select fans out — every path in
selectedPathIdsgets its own bbox-pivoted transform in a single setPaths + history push. Mirrors the existinghandleUpdateSelectedPath*family.Files changed (+550/-17):
src/components/editor/geometry.ts— new helpers:pathBoundingBox(handles included),flipHorizontalNodes,flipVerticalNodes,rotate90Nodes,applyPathTransform.PathTransformunion as the op vocabulary.src/pages/Editor.tsx—handleTransformSelectedPathfan-out handler; localpathBoundingBoxreplaced by the geometry version.src/components/editor/EditorRightPanel.tsx— optionalonTransformSelectedPathprop + Transform section with three lucide icons (FlipHorizontal2,FlipVertical2,RotateCw). Draw-path-only, disabled on zero-node paths, hidden when the prop is not wired (back-compat).src/components/editor/geometry.test.ts— 16 new tests pinning the math: reflection formulas, control-handle preservation, rotation invariant (4× = identity within FP epsilon), empty/no-op safety, dispatch viaapplyPathTransform.src/components/editor/EditorRightPanel.test.tsx— 8 new tests pinning the UI: three buttons wire through with the right op arg, disabled on empty path, hidden when prop omitted (back-compat), draw-path-only, multi-select label reads "Transform (N paths)".Gates: vitest 953/953 (+24 new), eslint clean,
tsc -bclean,vite buildclean. Refs #187 (Duplicate) and #188 (Multi-path selection) — this is the third sibling in the same right-panel family.