From df07f7bcb2eda4156cf492bbade0e61703108209 Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Fri, 15 May 2026 15:29:06 -0400 Subject: [PATCH] SelectionManager: route item to furnish phase before registry fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User report: items needed a double click to select after the item kind registered (Phase 5). Root cause: `getSelectionTarget` checked `isRegistrySelectable(node.type)` as part of the FIRST branch (which routes to structure phase), matching `item` before the item-specific branch below could route door/window-category items to structure + everything else to furnish. Effect: clicking an item triggered phase switch (structure ← furnish), then the next click selected. Hence the double click. Fix: 1. Item-specific case moved to the TOP of getSelectionTarget. Its asset.category-driven routing (door/window items → structure; everything else → furnish) beats any generic registry fallback. 2. Generic registry fallback at the bottom now reads `def.category` to pick the phase — `category: 'furnish'` → furnish phase, everything else → structure/elements. Future furnish-category kinds (only shelf right now) route correctly without a special case. 3. `isRegistrySelectable(node.type)` clause removed from the structure branch — replaced by the def.category check at the bottom. Net: single-click selection works for items again, and the routing logic is now cleanly capability/category-driven instead of "all registered kinds → structure" which was a Stage A simplification that broke as soon as a furnish-category kind registered. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../components/editor/selection-manager.tsx | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/packages/editor/src/components/editor/selection-manager.tsx b/packages/editor/src/components/editor/selection-manager.tsx index e9907d4d..23d0ecbf 100644 --- a/packages/editor/src/components/editor/selection-manager.tsx +++ b/packages/editor/src/components/editor/selection-manager.tsx @@ -11,6 +11,7 @@ import { type ItemNode, isRegistrySelectable, type NodeEvent, + nodeRegistry, type RoofEvent, type RoofNode, type RoofSegmentEvent, @@ -691,6 +692,25 @@ const SELECTION_STRATEGIES: Record = { } const getSelectionTarget = (node: AnyNode): SelectionTarget | null => { + // Item is checked FIRST so its asset.category-driven routing (door/ + // window items land in structure phase, everything else in furnish) + // beats the generic registry fallback below. Without this, registering + // `item` (Phase 5) made isRegistrySelectable('item') match the + // structure branch first, breaking single-click selection: first click + // switched the editor to structure phase, second click selected. + if (node.type === 'item') { + const item = node as ItemNode + if (item.asset.category === 'door' || item.asset.category === 'window') { + return { + phase: 'structure', + structureLayer: 'elements', + } + } + return { + phase: 'furnish', + } + } + if (node.type === 'zone') { return { phase: 'structure', @@ -711,10 +731,7 @@ const getSelectionTarget = (node: AnyNode): SelectionTarget | null => { node.type === 'stair-segment' || node.type === 'spawn' || node.type === 'window' || - node.type === 'door' || - // Registry-driven kinds default to structure/elements (Phase 4 reads - // `definition.presentation.paletteSection` to route correctly). - isRegistrySelectable(node.type) + node.type === 'door' ) { return { phase: 'structure', @@ -722,18 +739,16 @@ const getSelectionTarget = (node: AnyNode): SelectionTarget | null => { } } - if (node.type === 'item') { - const item = node as ItemNode - if (item.asset.category === 'door' || item.asset.category === 'window') { - return { - phase: 'structure', - structureLayer: 'elements', - } - } - - return { - phase: 'furnish', + // Registry-driven kinds (Phase 5+): route by `def.category`. Built-ins + // above match before this fallback. Furnish-category kinds (shelf, + // item — already handled above) land on the furnish phase; structure- + // category kinds (everything else) on structure/elements. + const def = nodeRegistry.get(node.type) + if (def) { + if (def.category === 'furnish') { + return { phase: 'furnish' } } + return { phase: 'structure', structureLayer: 'elements' } } return null