1010 * governing permissions and limitations under the License.
1111 */
1212
13- import { DOMAttributes , FocusableElement , Key , RefObject } from '@react-types/shared' ;
14- import { focusSafely } from '../interactions/focusSafely' ;
13+ import { DOMAttributes , FocusableElement , Key , RefObject } from '@react-types/shared' ;
14+ import { focusSafely } from '../interactions/focusSafely' ;
1515import {
1616 getActiveElement ,
1717 getEventTarget ,
1818 isFocusWithin ,
1919 nodeContains
2020} from '../utils/shadowdom/DOMFunctions' ;
21- import { getFocusableTreeWalker } from '../focus/FocusScope' ;
22- import { getScrollParent } from '../utils/getScrollParent' ;
21+ import { getFocusableTreeWalker } from '../focus/FocusScope' ;
22+ import { getScrollParent } from '../utils/getScrollParent' ;
2323import {
2424 IGridCollection as GridCollection ,
2525 GridNode
2626} from 'react-stately/private/grid/GridCollection' ;
27- import { gridMap } from './utils' ;
28- import { GridState } from 'react-stately/private/grid/useGridState' ;
29- import { isFocusVisible } from '../interactions/useFocusVisible' ;
30- import { mergeProps } from '../utils/mergeProps' ;
31- import { KeyboardEvent as ReactKeyboardEvent , useRef } from 'react' ;
32- import { scrollIntoViewport } from '../utils/scrollIntoView' ;
33- import { useLocale } from '../i18n/I18nProvider' ;
34- import { useSelectableItem } from '../selection/useSelectableItem' ;
27+ import { gridMap } from './utils' ;
28+ import { GridState } from 'react-stately/private/grid/useGridState' ;
29+ import { isFocusVisible } from '../interactions/useFocusVisible' ;
30+ import { mergeProps } from '../utils/mergeProps' ;
31+ import { KeyboardEvent as ReactKeyboardEvent , useRef } from 'react' ;
32+ import { scrollIntoViewport } from '../utils/scrollIntoView' ;
33+ import { useLocale } from '../i18n/I18nProvider' ;
34+ import { useSelectableItem } from '../selection/useSelectableItem' ;
3535
3636export interface GridCellProps {
3737 /**
@@ -77,12 +77,12 @@ export function useGridCell<T, C extends GridCollection<T>>(
7777 state : GridState < T , C > ,
7878 ref : RefObject < FocusableElement | null >
7979) : GridCellAria {
80- let { node, isVirtualized, focusMode = 'child' , shouldSelectOnPressUp, onAction} = props ;
80+ let { node, isVirtualized, focusMode = 'child' , shouldSelectOnPressUp, onAction } = props ;
8181
82- let { direction} = useLocale ( ) ;
82+ let { direction } = useLocale ( ) ;
8383 let {
8484 keyboardDelegate,
85- actions : { onCellAction}
85+ actions : { onCellAction }
8686 } = gridMap . get ( state ) ! ;
8787
8888 // We need to track the key of the item at the time it was last focused so that we force
@@ -119,7 +119,7 @@ export function useGridCell<T, C extends GridCollection<T>>(
119119 }
120120 } ;
121121
122- let { itemProps, isPressed} = useSelectableItem ( {
122+ let { itemProps, isPressed } = useSelectableItem ( {
123123 selectionManager : state . selectionManager ,
124124 key : node . key ,
125125 ref,
@@ -161,7 +161,7 @@ export function useGridCell<T, C extends GridCollection<T>>(
161161 e . stopPropagation ( ) ;
162162 if ( focusable ) {
163163 focusSafely ( focusable ) ;
164- scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
164+ scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
165165 } else {
166166 // If there is no next focusable child, then move to the next cell to the left of this one.
167167 // This will be handled by useSelectableCollection. However, if there is no cell to the left
@@ -181,14 +181,14 @@ export function useGridCell<T, C extends GridCollection<T>>(
181181
182182 if ( focusMode === 'cell' && direction === 'rtl' ) {
183183 focusSafely ( ref . current ) ;
184- scrollIntoViewport ( ref . current , { containingElement : getScrollParent ( ref . current ) } ) ;
184+ scrollIntoViewport ( ref . current , { containingElement : getScrollParent ( ref . current ) } ) ;
185185 } else {
186186 walker . currentNode = ref . current ;
187187 focusable =
188188 direction === 'rtl' ? ( walker . firstChild ( ) as FocusableElement ) : last ( walker ) ;
189189 if ( focusable ) {
190190 focusSafely ( focusable ) ;
191- scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
191+ scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
192192 }
193193 }
194194 }
@@ -208,7 +208,7 @@ export function useGridCell<T, C extends GridCollection<T>>(
208208 e . stopPropagation ( ) ;
209209 if ( focusable ) {
210210 focusSafely ( focusable ) ;
211- scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
211+ scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
212212 } else {
213213 let next = keyboardDelegate . getKeyRightOf ?.( node . key ) ;
214214 if ( next !== node . key ) {
@@ -223,14 +223,14 @@ export function useGridCell<T, C extends GridCollection<T>>(
223223
224224 if ( focusMode === 'cell' && direction === 'ltr' ) {
225225 focusSafely ( ref . current ) ;
226- scrollIntoViewport ( ref . current , { containingElement : getScrollParent ( ref . current ) } ) ;
226+ scrollIntoViewport ( ref . current , { containingElement : getScrollParent ( ref . current ) } ) ;
227227 } else {
228228 walker . currentNode = ref . current ;
229229 focusable =
230230 direction === 'rtl' ? last ( walker ) : ( walker . firstChild ( ) as FocusableElement ) ;
231231 if ( focusable ) {
232232 focusSafely ( focusable ) ;
233- scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
233+ scrollIntoViewport ( focusable , { containingElement : getScrollParent ( ref . current ) } ) ;
234234 }
235235 }
236236 }
@@ -254,28 +254,29 @@ export function useGridCell<T, C extends GridCollection<T>>(
254254
255255 // Grid cells can have focusable elements inside them. In this case, focus should
256256 // be marshalled to that element rather than focusing the cell itself.
257- let onFocus = e => {
257+ let onFocus = ( e : any ) => {
258258 keyWhenFocused . current = node . key ;
259+
260+ // FIX: If focus is moving directly to a specific inner child element
261+ // (like our restored Open Dialog button), update the selection state
262+ // and exit early. Do not call focus(), which resets to the first child.
259263 if ( getEventTarget ( e ) !== ref . current ) {
260- // useSelectableItem only handles setting the focused key when
261- // the focused element is the gridcell itself. We also want to
262- // set the focused key when a child element receives focus.
263- // If focus is currently visible (e.g. the user is navigating with the keyboard),
264- // then skip this. We want to restore focus to the previously focused row/cell
265- // in that case since the table should act like a single tab stop.
266264 if ( ! isFocusVisible ( ) ) {
267265 state . selectionManager . setFocusedKey ( node . key ) ;
268266 }
269267 return ;
270268 }
271269
272- // If the cell itself is focused, wait a frame so that focus finishes propagatating
273- // up to the tree, and move focus to a focusable child if possible.
274- requestAnimationFrame ( ( ) => {
275- if ( focusMode === 'child' && getActiveElement ( ) === ref . current ) {
276- focus ( ) ;
270+ if ( focusMode === 'child' ) {
271+ // Safeguard: Check if the browser's active element has already shifted
272+ // into a nested child node during this event loop tick before forcing a reset.
273+ let activeElement = getActiveElement ( ) ;
274+ if ( ref . current && isFocusWithin ( ref . current ) && activeElement !== ref . current ) {
275+ return ;
277276 }
278- } ) ;
277+
278+ focus ( ) ;
279+ }
279280 } ;
280281
281282 let gridCellProps : DOMAttributes = mergeProps ( itemProps , {
0 commit comments