import { findNodeHandle as _findNodeHandle, type NodeHandle, } from 'react-native'; /** * Type bridge for accessing undocumented React Native scroll component internals. * These properties exist at runtime but aren't exposed in RN's public type definitions. * * @see https://github.com/facebook/react-native/blob/main/packages/virtualized-lists/Lists/VirtualizedList.js#L1252 */ interface ScrollComponentInternals { /** Available on ScrollView, FlatList, etc. to get the underlying native scroll ref */ getNativeScrollRef?: () => NodeHandle | null; getScrollableNode?: () => NodeHandle | null; /** Internal property on VirtualizedList storing the scroll ref */ _scrollRef?: NodeHandle | null; } export function findNodeHandle( componentOrHandle: Parameters['0'] ): NodeHandle | null | typeof componentOrHandle { // Early return for null/undefined (React 19 fix) if (componentOrHandle == null) { return null; } let nodeHandle: NodeHandle | null = null; try { nodeHandle = _findNodeHandle(componentOrHandle); if (nodeHandle) { return nodeHandle; } } catch {} // Type bridge: componentOrHandle may have scroll internals at runtime const scrollable = componentOrHandle as unknown as ScrollComponentInternals; try { if (typeof scrollable.getNativeScrollRef === 'function') { nodeHandle = scrollable.getNativeScrollRef(); if (nodeHandle) { return nodeHandle; } } } catch {} try { if (typeof scrollable.getScrollableNode === 'function') { nodeHandle = scrollable.getScrollableNode(); if (nodeHandle) { return nodeHandle; } } } catch {} if (scrollable._scrollRef != null) { return scrollable._scrollRef; } console.warn('could not find scrollable ref!'); return componentOrHandle; }