@gorhom/bottom-sheet
Version:
A performant interactive bottom sheet with fully configurable options 🚀
65 lines (55 loc) • 1.85 kB
text/typescript
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<typeof _findNodeHandle>['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;
}