fix(resize): keep pivot corner fixed across all object types #68
No reviewers
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_whiteboard!68
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "development_fix_resize_drift_all_objects"
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?
Summary
Resizing any object via the top-left (or any left/top) anchor now shrinks it in place. The pivot corner (opposite the dragged anchor) stays anchored even when the new size is clamped to the type's minimum. Applies to every object type, not just calendar.
Related Issue
Closes #58
Root cause
Konva's Transformer sets
node.x/node.yeach tick assuming the visible size equalsoldSize * scale. When our code rounds or clamps the committed size to something different (e.g. calendar's per-view minimum, kanban'scolWidth >= 100), left/top-anchored drags shift the pivot corner by the delta. The more we clamp, the more the object drifts.Changes
crates/hero_whiteboard_ui/static/web/js/whiteboard/tools.jscorrectResizeDrift(node, expectedW, expectedH, newW, newH). Reads the active anchor from the transformer; shiftsnode.xby(expectedW - newW)when a left anchor is active andnode.yby(expectedH - newH)when a top anchor is active. No-op for rotater and for right/bottom-only anchors.transformlive-redraw handler for both calendar and kanban. For kanban, old bg width/height are read BEFOREWhiteboardKanban.redrawdestroys children; new bg is re-found afterwards.WhiteboardTools.correctResizeDrift.crates/hero_whiteboard_ui/static/web/js/whiteboard/objects.jsapplyTransformnow calls the helper in every branch that mutates size:sticky,shape(Rect, Ellipse, RegularPolygon, Star, Path, Line),frame,document,image,webframe,emoji,calendar,kanban,mindmap.textanddrawing/generic branches are deliberately skipped because they do not resize meaningfully.getClientRect({skipTransform: true})to read its intrinsic bbox and comparesexpectedW = intrinsic.width * scaleXvsnewW = intrinsic.width * finalClampedScale(mindmap bakes a uniform scale onto the group instead of resetting to 1).elsetoelse if (cls === 'Rect'), so an unknownclsfalls through without a bogus drift correction. All six shape classes currently used are explicitly handled.Preserved
transformer.forceUpdate()._colLayoutWeakMap (rebuilt per render as before).Test Results
cargo check --workspace: passcargo test --workspace --lib: passcargo clippy --workspace -- -D warnings: passcargo fmt --check: passJS-only change; Rust checks confirm no regression. Manual QA required to verify the pivot corner stays anchored for every object type and every anchor handle, including at the clamp minima.
Konva's Transformer sets node.x / node.y each tick assuming the visible size equals oldSize * scale. When our applyTransform and live-redraw paths round or clamp the committed size to something other than oldSize * scale, left/top-anchored drags shift the pivot corner by the delta, producing visible drift (most obvious on calendar past its minimum). Introduce a shared correctResizeDrift helper in tools.js that shifts node.x by (expectedW - newW) for left anchors and node.y by (expectedH - newH) for top anchors. Wire it into the calendar and kanban live-redraw branches and into every applyTransform branch that mutates size: sticky, shape (Rect, Ellipse, RegularPolygon, Star, Path, Line), frame, document, image, webframe, emoji, calendar, kanban, and mindmap. Text and drawing branches are skipped because they do not resize. Mindmap is handled by reading the intrinsic bbox via getClientRect({skipTransform: true}) and comparing expectedW = intrinsic.width * scaleX against newW = intrinsic.width * finalClampedScale, since mindmap bakes a uniform scale onto the group instead of resetting scale to 1. The shape else-fallback is tightened to `else if (cls === 'Rect')` so unknown classes fall through without a bogus drift correction; all six currently used shape classes are explicitly handled. #58