Skip to content

feat(cabinet): support exact sizing and run-aware editing - #753

Merged
wass08 merged 51 commits into
pascalorg:mainfrom
sudhir9297:t3code/enhance-kitchen-cabinets
Sep 2, 2026
Merged

feat(cabinet): support exact sizing and run-aware editing#753
wass08 merged 51 commits into
pascalorg:mainfrom
sudhir9297:t3code/enhance-kitchen-cabinets

Conversation

@sudhir9297

@sudhir9297 sudhir9297 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

  • Wall- and opening-aware cabinet movement

    • Issue: Cabinets could be placed or dragged across doors and windows, while 2D and 3D movement could lose cabinet-run alignment.
    • Fixed: Placement and movement now validate wall openings, preserve run-local frames, keep corner relationships stable, and show aligned previews across both views.
  • Exact dimensions during placement

    • Issue: Cabinet placement depended on cursor position and did not provide reliable direct sizing.
    • Fixed: Width, depth, height, and wall-clearance dimensions can be entered during placement with unit-aware parsing and visual guides in 2D and 3D.
  • Continuous L-shaped cabinet runs

    • Issue: Continuous wall drawing could produce inconsistent cabinet structures at L-shaped turns.
    • Fixed: Follow-on legs now use consistent cabinet modules, corner transitions, spacing, and wall constraints.
  • Full-run cabinet insertion

    • Issue: Inserting a cabinet into a full run could shift neighboring items unpredictably and leave support surfaces misaligned.
    • Fixed: Run-aware insertion preserves anchored neighbors, pushes compatible modules within available space, and keeps countertops and support surfaces coherent.
  • Balanced cabinet widths

    • Issue: Cabinet widths in a run required individual adjustment.
    • Fixed: Run settings can balance eligible base cabinets while respecting appliance widths, fillers, corner links, and wall limits.
  • Duplicate along a cabinet run

    • Issue: Repeating a cabinet required manual placement and made count and spacing difficult to control.
    • Fixed: Run settings can create repeated copies with a selected source, copy count, spacing, direction, and attached cabinet structure.
  • Wall-cabinet height workflow

    • Issue: Wall cabinets lacked a consistent set of common height choices.
    • Fixed: Wall cabinet runs and modules expose height presets while retaining custom height control and ceiling validation.
  • Cabinet-matched finishes

    • Issue: Refrigerator faces and exposed run ends could diverge from the selected cabinet front design.
    • Fixed: Panel-ready refrigerator faces and finished run ends now follow the cabinet front style, handle treatment, and material behavior.
  • Live L-corner width-resize preview

    • Issue: Resizing a cabinet beside an L-shaped run moved the linked L section only after the resize was committed.
    • Fixed: Linked L runs, nested legs, wall companions, and their composite geometry now follow width changes continuously in both 2D and 3D.

How to test

  1. Place or drag cabinets near a wall containing a door or window in both 2D and 3D.

    • The cabinet should not cross the opening unless force placement is used, and its run alignment should remain stable.
  2. Start placing a cabinet and select the width, depth, height, or wall-clearance dimension.

    • Enter values such as 900 mm or 24 in.
    • The preview should update to the exact dimension and keep the visual guides synchronized.
  3. Enable continuous cabinet placement and draw an L-shaped run.

    • The corner legs should use the same cabinet structure and follow the wall geometry consistently.
  4. Resize a cabinet width on a run with an attached L-shaped section in both 2D and 3D.

    • The linked L section, nested legs, wall companions, and countertop geometry should move continuously while dragging, before the resize is committed.
  5. Place a cabinet into the interior of a full run.

    • The run should make room without moving anchored neighbors unpredictably, and countertops should remain coherent.
  6. Open the cabinet run settings and use Equalize widths.

    • Eligible base cabinets should balance while appliance and filler widths remain constrained.
  7. Use Duplicate along run with different copy counts, spacing, and directions.

    • Copies should retain the source structure and fit only when the run has enough space.
  8. Select a wall cabinet and choose a height preset.

    • The cabinet height should update, and ceiling overflow should be reported when applicable.
  9. Run the automated checks:

    • bun run lint
    • bun run checks
    • bun run check-types
    • bun run build (passes with the existing Turbopack filesystem-tracing warning in the SQLite scene store)
    • bun test packages/nodes/src/cabinet — 479 passing tests

Screenshots / screen recording

Not added yet.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

Note

Medium Risk
Touches shared editor move/resize/placement infrastructure and complex cabinet run layout; regressions could affect non-cabinet movables or snapping defaults, though behavior is heavily covered by new cabinet tests.

Overview
Extends the movable and handle registries so kinds can veto invalid drops (isValidPosition), preview linked nodes during parent-frame moves (previewOverrides), and react to Alt during linear resize (HandleDragModifiers). The generic 2D/3D move and resize paths wire those hooks through—green/red footprint feedback, cancel on invalid drop, Alt to force place, and Alt to bypass snap / resize a cabinet module without reflowing neighbors.

Cabinet placement and editing gain typed placement dimensions (wall clearance, neighbor gaps, W×D×H) with clickable labels in the 3D placement box, floor-plan preview layer, and new 3D dimension guides; the placement-preview store tracks active dimension input. Snapping now defaults item/group moves to magnetic alignment instead of grid.

On the cabinet side: schema adds panelReady and withFinishedEnds; geometry and run ops add panel-ready fridge fronts, decorative end panels, run insertion/array/equalize-width tooling, structure inheritance when extending runs, wall-opening checks for runs and modules, corner-run live preview on move/resize, and refined width-handle behavior (magnetic gap close, nested wall-cabinet-only resize). Flip hinge moves from floating quick actions into the compartment inspector.

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

sudhir9297 and others added 30 commits May 19, 2026 02:59
Items (e.g. solar panels) can now be placed on sloped roof surfaces.
The placement system computes euler rotation from the roof surface
normal so items sit flush on the slope instead of going inside.

- Add roofStrategy to placement-strategies with enter/move/click/leave
- Wire roof:enter/move/click/leave events in the placement coordinator
- Add calculateRoofRotation in placement-math using surface normals
- Support full 3D cursor rotation for sloped surfaces
- Items on roofs are parented to the level with world-space rotation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
}
const onKeyUp = (e: KeyboardEvent) => {
if (e.key === 'Alt') altKey = false
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Alt resize commits stale modifiers

High Severity

Resize ticks store altKey from key events and never re-run apply when Alt is pressed or released, while commit reuses lastModifiers from the last pointer move. Releasing the handle after toggling Alt without moving writes the opposite of the live preview, so a run can reflow or stay independent incorrectly.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d2af0d. Configure here.

if (resolvedWallPosition) {
position = resolvedWallPosition.position
wallLocalX = resolvedWallPosition.wallLocalX
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Size input snaps cabinets flush

Medium Severity

After a typed width, depth, or height change on a wall-snapped preview, placement is re-resolved with wall-clearance set to 0. Any existing gap to the wall is discarded, so a later size edit jumps the cabinet flush even when the user already entered a clearance or the preview was offset.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d2af0d. Configure here.

useAlignmentGuides.getState().clear()
setMovingNode(null)
swallowNextClick()
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2D drop ignores late Alt

Medium Severity

forcePlace is written only from pointermove altKey, and the drop path reads that stale flag instead of the pointer-up event. Holding Alt to force a cabinet over an opening after the last move still rejects the drop, while releasing Alt after a forced preview can still commit the invalid pose.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d2af0d. Configure here.

!siblingConflict &&
!moduleOverlapsWallOpening(moving, parent as CabinetNodeType, position, nodes)
)
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3D move skips corner edge shift

Medium Severity

cabinetModuleParentFrame.onCommit calls syncCornerRunsFromSourceModule without previousModule, so the new edge-shift fallback never runs on 3D parent-frame moves. When derived L-run re-layout bails, a moved source module leaves the linked leg behind, unlike the 2D floorplan path that now passes the pre-move module.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1d2af0d. Configure here.

@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.

There are 5 total unresolved issues (including 4 from previous reviews).

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 48add69. Configure here.

})
: []
const affectedIds = new Set<AnyNodeId>([moduleId, ...(run ? [run.id as AnyNodeId] : [])])
for (const [id] of initialCornerPreview) affectedIds.add(id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2D move leaks corner previews

High Severity

affectedIds is frozen from the initial no-op corner preview, so linked legs that only receive overrides after the module actually moves are never cleaned up. Overlay teardown only clears that start-time set, and commit only clears the moved module. After cancel, reject, or undo, L-runs can stay at the dragged pose.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 48add69. Configure here.

@wass08
wass08 merged commit 83400c9 into pascalorg:main Sep 2, 2026
4 checks passed
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.

2 participants