You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 line
8.6 KiB

{"ast":null,"code":"import { useNavigation, useRoute } from '@react-navigation/core';\nimport * as React from 'react';\nfunction getScrollableNode(ref) {\n if (ref.current == null) {\n return null;\n }\n if ('scrollToTop' in ref.current || 'scrollTo' in ref.current || 'scrollToOffset' in ref.current || 'scrollResponderScrollTo' in ref.current) {\n return ref.current;\n } else if ('getScrollResponder' in ref.current) {\n return ref.current.getScrollResponder();\n } else if ('getNode' in ref.current) {\n return ref.current.getNode();\n } else {\n return ref.current;\n }\n}\nexport default function useScrollToTop(ref) {\n var navigation = useNavigation();\n var route = useRoute();\n React.useEffect(function () {\n var tabNavigations = [];\n var currentNavigation = navigation;\n while (currentNavigation) {\n if (currentNavigation.getState().type === 'tab') {\n tabNavigations.push(currentNavigation);\n }\n currentNavigation = currentNavigation.getParent();\n }\n if (tabNavigations.length === 0) {\n return;\n }\n var unsubscribers = tabNavigations.map(function (tab) {\n return tab.addListener('tabPress', function (e) {\n var isFocused = navigation.isFocused();\n var isFirst = tabNavigations.includes(navigation) || navigation.getState().routes[0].key === route.key;\n requestAnimationFrame(function () {\n var scrollable = getScrollableNode(ref);\n if (isFocused && isFirst && scrollable && !e.defaultPrevented) {\n if ('scrollToTop' in scrollable) {\n scrollable.scrollToTop();\n } else if ('scrollTo' in scrollable) {\n scrollable.scrollTo({\n y: 0,\n animated: true\n });\n } else if ('scrollToOffset' in scrollable) {\n scrollable.scrollToOffset({\n offset: 0,\n animated: true\n });\n } else if ('scrollResponderScrollTo' in scrollable) {\n scrollable.scrollResponderScrollTo({\n y: 0,\n animated: true\n });\n }\n }\n });\n });\n });\n return function () {\n unsubscribers.forEach(function (unsubscribe) {\n return unsubscribe();\n });\n };\n }, [navigation, ref, route.key]);\n}","map":{"version":3,"sources":["useScrollToTop.tsx"],"names":["useNavigation","useRoute","React","getScrollableNode","ref","current","getScrollResponder","getNode","useScrollToTop","navigation","route","useEffect","tabNavigations","currentNavigation","getState","type","push","getParent","length","unsubscribers","map","tab","addListener","e","isFocused","isFirst","includes","routes","key","requestAnimationFrame","scrollable","defaultPrevented","scrollToTop","scrollTo","y","animated","scrollToOffset","offset","scrollResponderScrollTo","forEach","unsubscribe"],"mappings":"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","sourceRoot":"../../src","sourcesContent":["import { useNavigation, useRoute } from '@react-navigation/core';\nimport * as React from 'react';\nfunction getScrollableNode(ref) {\n if (ref.current == null) {\n return null;\n }\n if ('scrollToTop' in ref.current || 'scrollTo' in ref.current || 'scrollToOffset' in ref.current || 'scrollResponderScrollTo' in ref.current) {\n // This is already a scrollable node.\n return ref.current;\n } else if ('getScrollResponder' in ref.current) {\n // If the view is a wrapper like FlatList, SectionList etc.\n // We need to use `getScrollResponder` to get access to the scroll responder\n return ref.current.getScrollResponder();\n } else if ('getNode' in ref.current) {\n // When a `ScrollView` is wraped in `Animated.createAnimatedComponent`\n // we need to use `getNode` to get the ref to the actual scrollview.\n // Note that `getNode` is deprecated in newer versions of react-native\n // this is why we check if we already have a scrollable node above.\n return ref.current.getNode();\n } else {\n return ref.current;\n }\n}\nexport default function useScrollToTop(ref) {\n const navigation = useNavigation();\n const route = useRoute();\n React.useEffect(() => {\n let tabNavigations = [];\n let currentNavigation = navigation;\n\n // If the screen is nested inside multiple tab navigators, we should scroll to top for any of them\n // So we need to find all the parent tab navigators and add the listeners there\n while (currentNavigation) {\n if (currentNavigation.getState().type === 'tab') {\n tabNavigations.push(currentNavigation);\n }\n currentNavigation = currentNavigation.getParent();\n }\n if (tabNavigations.length === 0) {\n return;\n }\n const unsubscribers = tabNavigations.map(tab => {\n return tab.addListener(\n // We don't wanna import tab types here to avoid extra deps\n // in addition, there are multiple tab implementations\n // @ts-expect-error\n 'tabPress', e => {\n // We should scroll to top only when the screen is focused\n const isFocused = navigation.isFocused();\n\n // In a nested stack navigator, tab press resets the stack to first screen\n // So we should scroll to top only when we are on first screen\n const isFirst = tabNavigations.includes(navigation) || navigation.getState().routes[0].key === route.key;\n\n // Run the operation in the next frame so we're sure all listeners have been run\n // This is necessary to know if preventDefault() has been called\n requestAnimationFrame(() => {\n const scrollable = getScrollableNode(ref);\n if (isFocused && isFirst && scrollable && !e.defaultPrevented) {\n if ('scrollToTop' in scrollable) {\n scrollable.scrollToTop();\n } else if ('scrollTo' in scrollable) {\n scrollable.scrollTo({\n y: 0,\n animated: true\n });\n } else if ('scrollToOffset' in scrollable) {\n scrollable.scrollToOffset({\n offset: 0,\n animated: true\n });\n } else if ('scrollResponderScrollTo' in scrollable) {\n scrollable.scrollResponderScrollTo({\n y: 0,\n animated: true\n });\n }\n }\n });\n });\n });\n return () => {\n unsubscribers.forEach(unsubscribe => unsubscribe());\n };\n }, [navigation, ref, route.key]);\n}\n//# sourceMappingURL=useScrollToTop.js.map"]},"metadata":{},"sourceType":"module"}