feat(studio): arrow-key nudge step math (unwired)#2203
Conversation
a5ce90b to
f6dd7eb
Compare
9d0fa02 to
78c55d1
Compare
f6dd7eb to
f45f759
Compare
miga-heygen
left a comment
There was a problem hiding this comment.
Reviewed as part of the 25-PR NLE overhaul stack. Full stack review on #2205 (the keystone). No blockers on this PR. — Miga
vanceingalls
left a comment
There was a problem hiding this comment.
Verdict: LGTM (green) — smallest of the batch, correct at every boundary
Two pure helpers: resolveCanvasNudgeDelta maps arrow keys (plain / Shift) to a { dx, dy } in composition pixels; canCanvasNudgeTargets gates the whole nudge on target capabilities. Nothing to trip over.
The pointed queries
- Step math is unambiguous.
packages/studio/src/components/editor/domEditNudge.ts:11–:12—CANVAS_NUDGE_STEP_PX = 1,CANVAS_NUDGE_SHIFT_STEP_PX = 10. Constants are integers in composition-space pixels; the returned{ dx, dy }is likewise in pixels. Test at :24–:52 pins all four cardinal directions × {plain, Shift}. - Chord passthrough. :28 rejects
metaKey || ctrlKey || altKey→ returnsnullso browser/app shortcuts route past the nudge. Tested at :54–:58 for all three modifiers. Correct. - Non-arrow rejection. :29 gates on
CANVAS_NUDGE_KEYS.has(event.key); non-arrows fall through tonull. Tested at :60–:63. - Target-capability gate.
canCanvasNudgeTargetsat :42–:44 requires at least one target AND every target'scanApplyManualOffset === true. Test at :66–:79 covers[](false),[movable](true),[movable, movable](true),[locked](false),[movable, locked](false). All four boundary cases. - Debounce constant. :14 (
CANVAS_NUDGE_COMMIT_DEBOUNCE_MS = 400) is exported but not yet consumed at this SHA — exempted in.fallowrc.jsoncat :93–:97 with the TEMP marker pointing at studio-dnd/pr22. Honest. - No accumulation logic here. Delta accumulation for holding an arrow key (the "burst commit" pattern named in the docstring at :13) is NOT in this file — it belongs to the wiring PR. This module is a pure per-event mapper. Right scope.
- Wiring with
#2200(canvas nudge gate). No import at this SHA — verified via grep againstDomEditOverlay.tsxhead. As with#2200, the pair is expected to be wired together by studio-dnd/pr22. This PR's math is independently testable and it is tested.
R1 by Via
f45f759 to
a15be5a
Compare
ad7cd13 to
97977b2
Compare
a15be5a to
f20cc98
Compare
f20cc98 to
f3e5bb2
Compare
143e573 to
a087215
Compare
f3e5bb2 to
b72f457
Compare
802df15 to
4d17f3c
Compare
50e9bb0 to
d103af6
Compare
miguel-heygen
left a comment
There was a problem hiding this comment.
Re-review at current head d103af6: diff remains unwired pure step math, prior tests and contracts intact; required checks green. Approving.
138ede6 to
0d1397b
Compare
d103af6 to
ee960b6
Compare
What: domEditNudge — pure nudge-step math (direction × modifier → delta, commit debounce constant) with tests. Shipped unwired. Why: small standalone concept consumed by the canvas nudge hook in the chrome-components PR. How: new files; one TEMP(studio-dnd) ignoreExports entry until the consumer lands (removed by the app-shell swap PR). Test plan: bunx vitest run domEditNudge.test.ts; tsc --noEmit; fallow audit clean.
0d1397b to
8229961
Compare
ee960b6 to
951fda3
Compare
miguel-heygen
left a comment
There was a problem hiding this comment.
Re-reviewed current head and verified the addressed feedback and required behavior. Approval is for this exact head; Graphite mergeability may still be pending.

What
domEditNudge — pure nudge-step math (direction × modifier → delta, commit debounce constant) with tests. Shipped unwired.
Why
small standalone concept consumed by the canvas nudge hook in the chrome-components PR.
How
new files; one TEMP(studio-dnd) ignoreExports entry until the consumer lands (removed by the app-shell swap PR).
Test plan
bunx vitest run domEditNudge.test.ts; tsc --noEmit; fallow audit clean.
Stack position 12/25 — studio NLE overhaul (CapCut-parity timeline + canvas). Graphite manages bases; merge from #2192 upward. Temporary
TEMP(studio-dnd)fallow entries (unwired-component windows) are all removed by #2213 (app-shell swap), whose tree is byte-identical to the fully-verified integration branch.