Two new files in packages/editor/src/components/editor-2d/ keep the
work out of the 18k-line floorplan-panel.tsx monolith. The panel
itself gets only four tiny additions (two imports, two component
mounts, one data attribute).
<FloorplanRegistryActionMenu>
- Reads useViewer.selection — when a registered kind is selected and
we're not in a move state, queries the rendered [data-node-id] <g>
for its bounding rect (polled via rAF for pan/zoom/move reactivity).
- Portals an HTML overlay above the bounding box with the existing
<NodeActionMenu>. Buttons gated by def.capabilities:
* Move → setMovingNode(node)
* Duplicate → structuredClone + schema.parse + createNode + set
movingNode (placement cursor) — matches 3D duplicate UX.
* Delete → deleteNode(id) + clear selection.
- Same visual styling as the legacy <FloorplanActionMenuLayer> per
kind, but driven by registry data.
<FloorplanRegistryMoveOverlay>
- Activates when useEditor.movingNode is a kind with def.floorplan.
- Listens on window for pointermove (to track cursor in floor plan
meters via the scene <g>'s getScreenCTM — matches the legacy
getSvgPointFromClientPoint coordinate path so cursor → meters
accounts for pan/zoom/building rotation).
- Renders a 50%-opacity ghost via portal into the floor-plan scene
<g>. Builder reused from def.floorplan — no per-kind ghost code.
- Click commits via updateNode({ position: [cx, oldY, cz] }) and
clears movingNode. Clears `isNew` metadata on duplicates so they
don't loop. Esc cancels.
floorplan-panel.tsx touches:
- Two imports (action menu + move overlay).
- data-floorplan-scene="" attribute on the floorplanSceneRef <g>
so the overlay can find the scene without sharing a ref.
- <FloorplanRegistryActionMenu /> mounted alongside the legacy
action menu layer.
- <FloorplanRegistryMoveOverlay /> mounted inside the SVG tree
alongside the registry render layer.
FloorplanRegistryLayer: also stopPropagation on click events so the
outer SVG's onClick={handleBackgroundClick} doesn't deselect right
after our pointerDown sets selection. Fixes "click-in-2D doesn't
select" bug.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>