Skip to content

fix(wall): typed exact length during drafting follows unit toggle - #884

Open
Frank-zhu0404 wants to merge 13 commits into
pascalorg:mainfrom
Frank-zhu0404:fix/issue-308-unit-toggle-input
Open

Frank-zhu0404 wants to merge 13 commits into
pascalorg:mainfrom
Frank-zhu0404:fix/issue-308-unit-toggle-input

Conversation

@Frank-zhu0404

@Frank-zhu0404 Frank-zhu0404 commented Sep 17, 2026

Copy link
Copy Markdown

Summary

  • While drafting a wall in the two-click flow, typing an exact length (e.g. 3m, 180cm, 2500 in mm notation, 10'6", or a bare number in the active unit) locks the draft to that length along the current heading — the pointer keeps steering direction only.
  • Enter commits at the typed length; Escape is two-stage (clear buffer, then cancel drafting); Backspace/Delete edit the buffer.
  • The HUD keeps DraftMeasurementLabel until typing begins (no always-mounted input over the segment).
  • Angle / junction / magnetic snap still own the heading; typed length only constrains distance.
  • Shared across the 2D floor-plan draft and the 3D wall tool via useWallDraftTyping, with parseWallDraftLength / constrainWallDraftLength as the shared parse+project helpers (bare units follow the unit toggle + metric mm notation, matching inspector parseUnit).

Testing

  • packages/editoruse-wall-draft-typing.test.ts + wall-drafting.test.ts (incl. new length-input cases): 39 pass
  • Biome check on touched files

Closes #308


Note

Medium Risk
Touches core wall drafting, keyboard capture, and 2D/3D commit ownership; regressions could duplicate walls or desync the draft rubber band.

Overview
Adds typed exact length while drawing walls in the two-click flow, matching 3D behavior on the 2D floor plan. Users can enter lengths (bare numbers in the active unit, 180cm, 10'6", etc.); the draft endpoint stays on that distance along the current heading while the pointer still sets direction. Enter commits, Escape clears the buffer first then cancels drafting, and the on-segment label shows the raw buffer while typing.

A shared useWallDraftTyping store plus parseWallDraftLength / constrainWallDraftLength (and related commit helpers) wire the floor plan panel and WallTool together. Capture-phase keyboard handling on the floor plan avoids shortcut conflicts (including Space as a length separator when mid-entry). Enter arms a one-shot pendingCommitMeters and emits grid:click so WallTool owns creation when mounted, with guards so 2D-only does not double-create walls or leave a stale rubber band after split-view / typed commits.

Reviewed by Cursor Bugbot for commit 3404b18. Bugbot is set up for automated code reviews on this repo. Configure here.

…scalorg#308)

Keep the normal wall measurement label until a digit starts editing, then
parse bare values with the active unit (ft / m / mm) while explicit suffixes
still win. Enter commits the typed length along the current heading; Escape
clears the buffer first and cancels on the second press. Shared across the
2D floor-plan draft and the 3D wall tool.

Closes pascalorg#308
@pascal

pascal Bot commented Sep 17, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 4d2683ef-f5b2-46f8-9e42-68db0e331135

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/nodes/src/wall/tool.tsx Outdated
Bugbot: 2D typed-length keys only prevented default, so Escape/digits/unit
letters still hit the global tool listener. Also pull store wallDraftStart
back into panel draftStart so split-view Enter (3D capture → grid:click)
advances the 2D rubber-band chain start.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx Outdated
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx Outdated
… store null (pascalorg#308)

Bugbot on PR pascalorg#884: 2D Enter was calling a first-click closure, typing keys
lost to bubble use-keyboard, and split Enter left the 2D rubber band open.

- Assign wallPlacementPointRef after handleWallPlacementPoint so Enter
  commits when draftStart is set.
- Register the 2D keydown listener in the capture phase (add/remove with
  the same flag); skip keys 3D already preventDefaulted.
- Sync-clear local draftStart/end/cursor when the store start is null.

Self-test:
- bun test packages/editor/src/components/tools/wall/wall-drafting.test.ts
  packages/editor/src/store/use-wall-draft-typing.test.ts
  → 43 pass, 0 fail
- bunx biome check on the three touched files → clean

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/wall/tool.tsx Outdated
Comment thread packages/nodes/src/wall/tool.tsx Outdated
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot follow-up (b6a9b3d5)

Addressed the three unresolved Bugbot threads on head 0628835:

  1. Stale wallPlacementPointRef (High) — assign the ref after handleWallPlacementPoint on every render so 2D Enter uses the callback that sees current draftStart and commits instead of treating the typed end as a new start.
  2. 2D typing vs global shortcuts (High) — register/remove the 2D wall typing keydown listener in the capture phase so digits/unit letters beat bubble use-keyboard; skip when defaultPrevented (3D already owned the key in split view).
  3. Split Enter dangling 2D draft (Medium) — sync clears local draftStart / draft end / cursor when wallDraftStart in the store becomes null after 3D ends the chain; non-null store still advances the chain. Helper nextLocalWallDraftStartFromStore + unit tests.

Self-test: bun test wall-drafting + use-wall-draft-typing → 43 pass; Biome clean on touched files.
Muse: cline-free/muse-spark-1.3-contributor --thinking xhighVERDICT=PASS.

@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot round 2 — Muse PASS

Fixed both new Mediums on 90388596:

  1. Unit toggle clears typed lengthunit / metricNotation moved to refs; effect deps [] so toggle no longer tears down listeners or calls clearInput() / nulls draft preview. Bare buffer re-parses under the new unit on next move/Enter.
  2. Typed endpoint re-snappedresolveWallDraftCommitEnd skips snap when a typed commit length is pending; 2D grid:move emits pre-constraint snapped heading while local preview keeps the length-constrained point.

Self-test: focused wall-drafting tests. Cline Muse (cline-free/muse-spark-1.3-contributor, --thinking xhigh) VERDICT=PASS.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/editor/src/store/use-wall-draft-typing.ts
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot round-3 fixes (Medium ×3) + Muse PASS

Head: a4dbcecafix(wall): space pan vs typing, live typed preview, letter-safe buffer start (#308)

Fixes

  1. Space pan steals typed length — Typing runs before Space pan; shouldArmFloorplanSpacePan honors defaultPrevented and skips pan while the length buffer is non-empty; Space only extends a started buffer (imperial 5' 6"). 3D capture returns early on defaultPrevented so split view does not pan+append.
  2. Typed length preview stays stale — New refreshWallDraftTypedEnd re-projects along the current heading (no re-snap). 2D FloorplanLinearDraftLayer and 3D WallTool effects refresh wallDraftEnd / preview when the buffer or unit/notation changes.
  3. Letters always start length bufferisWallTypingKey(key, buffer) only starts on digit/. when empty; letters/c/m/f/Space no longer seed an invalid buffer or swallow cycle-continuation.

Prior 90388596 / b6a9b3d5 behavior preserved (unit-toggle refs, typed Enter skip re-snap).

Self-test

bun test use-wall-draft-typing + wall-drafting → 54 pass / 0 fail

Muse

cline -P cline-pass -m cline-free/muse-spark-1.3-contributor --thinking xhigh (desktop cline-muse-884) → VERDICT=PASS

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx Outdated
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r4 (604682f)

Fixed both new Medium threads on top of a4dbcec:

  1. Enter drops wall after view switch — Typed Enter now sets pendingCommitMeters and emits grid:click so WallTool commits in split/3D (no-re-snap preserved; 2D-only start adopted when buildingState is 0).
  2. 3D end leaves 2D chain dirty — Null store start during wall build now runs clearWallPlacementDraft() so wallChainWallIdsRef resets.

Self-test: Bun wall-draft-typing + wall-drafting tests; biome on touched files.
Muse (cline-muse-884): VERDICT=PASS.
Unresolved review threads after: 0.
Push: OK to existing PR branch.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/nodes/src/wall/tool.tsx
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r5 — Muse PASS

Head: 549410d6 (+ tests 320839c6) — typed Enter single-commit path; clear draft on 3D stop.

Bugbot High (16aa0c3c): Typed Enter in 2D-only emitted grid:click and called createWallOnCurrentLevel → twin walls / dirty rubber band after WallTool stopDrafting.

Fix:

  1. Typed Enter sets wallToolOwnsTypedCommitRef, emits grid:click (WallTool owns create via adopt + pending meters); floorplan syncs only.
  2. shouldCreateWallLocallyOnFloorplanPlacement — 2D pointer still creates locally; typed Enter with WallTool ownership skips local create.
  3. shouldClearFloorplanDraftAfterWallToolCommit — clears rubber band when !publishedNextStart && (!viewIs2DOnly || wallToolOwnedTypedCommit).
  4. Unit tests for both helpers (bun test wall-drafting + use-wall-draft-typing → 71 pass).

Muse (cline-free/muse-spark-1.3-contributor --thinking xhigh): VERDICT=PASS.

Note: Bugbot has since filed 2 new Highs on this head (null store wipe / typed Enter skip-create) — fixing next.

@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r5 (28fa33be)

  • Typed Enter: single commit path (WallTool owns via grid:click + adopt; skip local twin when pending taken).
  • 2D rubber band clears after WallTool stopDrafting (incl. 2D-only typed Enter).
  • Null-store reset only on published→null transition (no wipe of 2D first click).
  • Pending take moved after WallTool preview guard; ownership from pending consumption.

Muse on 549410d6: VERDICT=PASS. Self-test: 80 pass (wall-drafting + use-wall-draft-typing).

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r6 — both Highs fixed @ 0a8a2d04:

  1. Null-store reset only on non-null→null; WallTool idle unmount preserves 2D draft
  2. Typed Enter: take meters only past preview guard; restore on create failure; ownership/clear gated on real WallTool commit

Self-test: bun wall-drafting + use-wall-draft-typing → 80 pass. Muse: VERDICT=PASS. Unresolved actionable Bugbot: 0.

@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r6 (final) @ f4ff70bd:

  1. Null-store reset: non-null→null only; idle WallTool unmount preserves 2D draft
  2. Typed Enter: take after preview guard; restore pending on fail; ownership/clear gated
  3. Pointer twin: skip local 2D create when WallTool already committed; clearInput after success

Self-test: 86 pass. Muse: VERDICT=PASS.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread packages/nodes/src/wall/tool.tsx
Comment thread packages/nodes/src/wall/tool.tsx Outdated
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r6b — Muse PASS @ f4ff70bd

Third High (post-r6): skip 2D twin createWallOnCurrentLevel when WallTool already committed the typed Enter (wallToolCommittedOnFloorplanClickshouldCreateWallLocally); clearInput only after successful create.

Self-test: bun test wall-drafting + use-wall-draft-typing → 86 pass / 0 fail.
Unresolved review threads: 0.

…Enter (pascalorg#308)

Pointer clicks with a live typing buffer now adopt the 2D published start
instead of begin()-clearing it. Failed Enter keeps the buffer and stops
propagation so global shortcuts cannot fire.
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r7 (39dd6257 on fix/issue-308-unit-toggle-input)

  • High pointer click ignores typed length — adopt 2D start when live typing buffer present; no begin() wipe
  • Medium failed Enter drops buffer — keep buffer + stop propagation; clearInput only after successful arm

Self-test: wall-drafting + use-wall-draft-typing → 88 pass / 0 fail
Muse (code-reviewer): VERDICT=PASS

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 39dd625. Configure here.

Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/nodes/src/wall/tool.tsx
@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r8 (3404b181 on fix/issue-308-unit-toggle-input)

Fixed both new Medium threads after r7:

  1. Enter drops length without heading — 2D typed Enter now returns before clearInput/arm/emit when the draft has no heading (hasWallDraftHeading), matching parse-failure keep-buffer and the 3D path.
  2. Failed Enter rearms silent commit — after 3D typed Enter, failed createWall skips restoreTypedCommitArm (createAttempted:true) so the next pointer click cannot consume stale pendingCommitMeters with an empty HUD.

Self-test: bun test wall-drafting + use-wall-draft-typing → 92 pass / 0 fail
Muse (cline-free/muse-spark-1.3-contributor --thinking xhigh, SYSTEM-REVIEW): VERDICT=PASS
Unresolved review threads: 0

@Frank-zhu0404

Copy link
Copy Markdown
Author

Bugbot r8 follow-up (Cline Muse PASS)

Head 3404b181 — Muse (cline-free/muse-spark-1.3-contributor, --thinking xhigh) VERDICT=PASS.

Addresses the two Mediums after r7:

  1. Keep typed length buffer when 2D Enter fails due to missing heading (match parse-failure / 3D degenerate keep).
  2. On failed createWall after 3D typed Enter, clear pendingCommitMeters / disarm silent commit.

Self-test: bun test wall-drafting / use-wall-draft-typing — 92 pass / 0 fail. Review threads unresolved=0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

unit toggle only affects the display of dimensions, not the input

1 participant