@@ -50,6 +50,23 @@ interface RemoteSelectionOverlayProps {
5050 scrollElement : HTMLElement | null
5151}
5252
53+ /**
54+ * Whether a selection endpoint lands in the frozen left zone. Rows are virtualized, so an
55+ * endpoint's own cell may not exist; fall back to any rendered row's cell in that column,
56+ * since pinning is a per-column property. An endpoint whose column is gone entirely (hidden
57+ * or deleted locally) can't be classified and is treated as unpinned — the safe direction,
58+ * since the frozen zone then occludes it rather than being painted over.
59+ */
60+ function endpointIsPinned (
61+ scrollEl : HTMLElement ,
62+ cell : HTMLElement | null ,
63+ columnIndex : number | undefined
64+ ) : boolean {
65+ if ( cell !== null ) return cell . hasAttribute ( 'data-pinned' )
66+ if ( columnIndex === undefined ) return false
67+ return scrollEl . querySelector ( `[data-col="${ columnIndex } "][data-pinned]` ) !== null
68+ }
69+
5370/** The cell `<td>` for a (rowId, columnIndex), or null when virtualized off-window. */
5471function cellElement (
5572 scrollEl : HTMLElement ,
@@ -177,15 +194,11 @@ export function RemoteSelectionOverlay({
177194 const cells = [ anchorCell , focusCell ] . filter ( ( cell ) : cell is HTMLElement => cell !== null )
178195 if ( cells . length === 0 ) continue
179196 const rects = cells . map ( ( cell ) => cell . getBoundingClientRect ( ) )
180- // Both endpoints must be resolved AND pinned. Anything else — a range straddling the
181- // boundary, or one whose other endpoint is virtualized off-window and so can't be
182- // classified — defers to the frozen zone, where the worst case is a selection the zone
183- // hides rather than one painting over the gutter.
197+ // Only a selection pinned at BOTH ends renders above the frozen zone. One that straddles
198+ // the boundary goes below it, so its unpinned half can't paint over the gutter.
184199 const pinned =
185- anchorCell !== null &&
186- focusCell !== null &&
187- anchorCell . hasAttribute ( 'data-pinned' ) &&
188- focusCell . hasAttribute ( 'data-pinned' )
200+ endpointIsPinned ( scrollEl , anchorCell , anchorCol ) &&
201+ endpointIsPinned ( scrollEl , focusCell , focusCol )
189202
190203 const viewportTop = Math . min ( ...rects . map ( ( r ) => r . top ) )
191204 const viewportLeft = Math . min ( ...rects . map ( ( r ) => r . left ) )
0 commit comments