Skip to content

feat(wall): typed exact length during two-click wall drafting - #883

Open
dkbbdev wants to merge 3 commits into
pascalorg:mainfrom
dkbbdev:feat/wall-typed-length
Open

dkbbdev wants to merge 3 commits into
pascalorg:mainfrom
dkbbdev:feat/wall-typed-length

Conversation

@dkbbdev

@dkbbdev dkbbdev commented Sep 17, 2026

Copy link
Copy Markdown

Closes #308.

What

While drafting a wall in the two-click flow, typing an exact length (e.g. 3m, 180cm, 2500 in mm notation, 10'6") now locks the draft to that length along the current draft direction — the pointer keeps steering the direction only.

  • Enter commits the wall at the typed length.
  • Escape is two-stage: first press clears the typing buffer, second press cancels the draft (per the triage note on unit toggle only affects the display of dimensions, not the input #308).
  • Backspace/Delete edit the buffer.
  • The HUD label shows the buffer while typing and falls back to the normal drafting label when empty.

How

  • New shared store useWallDraftTyping (packages/editor/src/store/use-wall-draft-typing.ts) holds the buffer so the 2D floor-plan draft and the 3D wall tool stay in lockstep per the 2D ↔ 3D parity rule in wiki/architecture/tools.md.
  • 3D (packages/nodes/src/wall/tool.tsx): a window keydown listener mirrors the cabinet tool's applyTypedDimension pattern — parseMeasurement resolves the buffer with the same bare-unit defaults; grid:move projects the draft end onto the typed length; Enter synthesizes a grid:click at the projected endpoint so the normal commit pipeline (chain continuation, auto-close, support-slab election) runs unchanged.
  • 2D (floorplan-panel.tsx): the same projection in the wall-draft pointer move, the same key handling in the window keydown effect, and the HUD label override.
  • Angle snap / junction snap / magnetic alignment continue to work on untyped drafts; the typed commit intentionally bypasses endpoint snap so the typed length survives exactly (drafting direction is taken from the current snapped pointer, so snapped angles still steer it).

Testing

  • packages/editor/src/store/use-wall-draft-typing.test.ts — buffer lifecycle + accepted keys.
  • packages/nodes/src/wall/typed-length.test.ts — the projection math shared by both views.
  • Full @pascal-app/editor + @pascal-app/nodes suites pass (turbo run test: 3119 tests across 268 files, plus the editor suite).
  • tsgo --noEmit clean for both packages; biome check clean on touched files.

Verified end-to-end on a self-hosted deployment (design.dekorproduct.com) in both the 2D plan and 3D views with metric-m and mm notations.

Thanks for the detailed triage spec on #308 — the interaction follows it point by point.


Note

Medium Risk
Touches core wall placement/commit paths in 2D and 3D with global key handlers and intentional snap bypass on typed commits; regression risk is localized to drafting UX rather than persisted data.

Overview
Adds typed exact-length input while drafting walls in the two-click flow (#308), with matching behavior in 2D floor plan and 3D wall tool.

A new shared Zustand store (useWallDraftTyping, exported from @pascal-app/editor) holds the measurement buffer and a projected endpoint so preview, HUD, click, and Enter commit stay aligned. While typing, the draft end is projected onto the parsed length along the pointer direction; the length label shows the buffer instead of live distance. Enter commits at that length (3D via synthetic grid:click; 2D via wallPlacementPointRef to avoid stale closures); Escape first clears the buffer then cancels the draft; Backspace/Delete edit the buffer. Typed commits skip endpoint re-snap so the entered length is preserved; the buffer clears after each segment so chains do not inherit a stale length.

Unit tests cover the store/key filter and the shared projection math.

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

…org#308)

While drafting a wall, printable keys open a typing buffer; the draft
endpoint is projected onto the typed length along the current draft
direction, so the pointer keeps steering direction only. Enter commits
at the typed length, two-stage Escape clears the buffer first and then
cancels the draft, Backspace/Delete edit the buffer. Shared zustand
store keeps the 2D floor plan and the 3D view in lockstep (parity rule
in wiki/architecture/tools.md); angle/junction snapping is preserved on
untyped drafts and bypassed only for the typed commit.
@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: 91943371-ceba-4f22-9d28-001dcd5623f3

@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
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
Comment thread packages/editor/src/store/use-wall-draft-typing.ts
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx
- click/Enter commit reuses the projected endpoint the previews show
  instead of re-snapping the raw pointer (2D + 3D parity)
- HUD subscribes to the typing store so the label tracks keystrokes
- typing buffer cleared on every commit/cancel path; never carries
  into the next chain segment
- 2D typing keys stopPropagation so tool shortcuts don't fire mid-type
- drop unused begin() action
@dkbbdev

dkbbdev commented Sep 17, 2026

Copy link
Copy Markdown
Author

Addressed all 5 Bugbot findings in 11e8fa5:

  • Click commit ignores typed length / Enter re-snaps typed endpoint — the typing store now carries the projected endpoint (projectedEnd); click and Enter commits reuse it verbatim in both 2D and 3D, bypassing magnetic/angle/grid snap so the committed wall is exactly the previewed length.
  • HUD ignores typing store updates — the 2D layer subscribes to the store (useWallDraftTyping((s) => s.input)) instead of reading getState() inside useMemo.
  • Typing buffer persists after commitclearInput() now fires on every exit path: 3D commit, 2D commit + chain continuation, clearWallPlacementDraft, cancel; removed the unused begin().
  • 2D typing keys leak to shortcuts — typing/Enter/Escape handlers now stopPropagation() as well as preventDefault().

Full check-types + test suites pass (3,125 tests).

@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
Comment thread packages/editor/src/components/editor/floorplan-panel.tsx Outdated
… Enter commit

- 3D Enter keeps the buffer across the synthetic grid:click so the
  commit is recognized as typed (no re-snap), clears defensively after
- stopDrafting clears the typing store: double-click finish and chain
  auto-close no longer leak the old length into the next draft
- 2D Enter commits through a latest-ref instead of the first-render
  closure, which used to restart the draft at the typed point
- 2D move preview publishes projectedEnd so a click mid-type commits
  the projected endpoint, matching the 3D tool
@dkbbdev

dkbbdev commented Sep 17, 2026

Copy link
Copy Markdown
Author

Round 2 findings fixed in 596c7e7:

  • 3D Enter re-snaps the typed endpoint — the buffer now survives the synthetic grid:click (commit recognized as typed, snap bypassed), with a defensive clear after in case the commit path bails early.
  • Stopped draft keeps typed bufferstopDrafting clears the typing store, so double-click finish and chain auto-close no longer leak the old length into the next draft.
  • 2D Enter uses a stale callback — the placement callback is now kept current via a useEffect latest-ref instead of self-assigning on first call; typed Enter commits the wall instead of restarting the draft. The 2D move preview also publishes projectedEnd so a click mid-type commits the projected endpoint, matching 3D.

check-types + biome + full test suite 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 1 potential issue.

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 596c7e7. Configure here.

backspace: () =>
set((state) => ({ input: state.input.slice(0, Math.max(0, state.input.length - 1)) })),
clearInput: () => set({ input: '', projectedEnd: null }),
setProjectedEnd: (end) => set({ projectedEnd: end }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Click commits stale typed length

High Severity

append and backspace only change input. The draft end and projectedEnd update on pointer move, so a click after typing reuses the last pointer point. Enter recomputes the projection and commits the typed length; click does not. The HUD already shows the buffer, so the committed wall does not match the previewed length.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 596c7e7. Configure here.

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