UNPKG

6.15 kBSource Map (JSON)View Raw
1{"version":3,"names":["getScrollableNode","ref","current","getScrollResponder","getNode","useScrollToTop","navigation","useNavigation","route","useRoute","React","useEffect","getState","type","getParent","unsubscribe","addListener","e","isFocused","isFirst","routes","key","requestAnimationFrame","scrollable","defaultPrevented","scrollToTop","scrollTo","x","y","animated","scrollToOffset","offset","scrollResponderScrollTo"],"sources":["useScrollToTop.tsx"],"sourcesContent":["import { EventArg, useNavigation, useRoute } from '@react-navigation/core';\nimport * as React from 'react';\n\ntype ScrollOptions = { x?: number; y?: number; animated?: boolean };\n\ntype ScrollableView =\n | { scrollToTop(): void }\n | { scrollTo(options: ScrollOptions): void }\n | { scrollToOffset(options: { offset?: number; animated?: boolean }): void }\n | { scrollResponderScrollTo(options: ScrollOptions): void };\n\ntype ScrollableWrapper =\n | { getScrollResponder(): React.ReactNode }\n | { getNode(): ScrollableView }\n | ScrollableView;\n\nfunction getScrollableNode(ref: React.RefObject<ScrollableWrapper>) {\n if (ref.current == null) {\n return null;\n }\n\n if (\n 'scrollToTop' in ref.current ||\n 'scrollTo' in ref.current ||\n 'scrollToOffset' in ref.current ||\n 'scrollResponderScrollTo' in ref.current\n ) {\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}\n\nexport default function useScrollToTop(\n ref: React.RefObject<ScrollableWrapper>\n) {\n const navigation = useNavigation();\n const route = useRoute();\n\n React.useEffect(() => {\n let current = navigation;\n\n // The screen might be inside another navigator such as stack nested in tabs\n // We need to find the closest tab navigator and add the listener there\n while (current && current.getState().type !== 'tab') {\n current = current.getParent();\n }\n\n if (!current) {\n return;\n }\n\n const unsubscribe = current.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',\n (e: EventArg<'tabPress', true>) => {\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 =\n navigation === current ||\n 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) as ScrollableWrapper;\n\n if (isFocused && isFirst && scrollable && !e.defaultPrevented) {\n if ('scrollToTop' in scrollable) {\n scrollable.scrollToTop();\n } else if ('scrollTo' in scrollable) {\n scrollable.scrollTo({ x: 0, y: 0, animated: true });\n } else if ('scrollToOffset' in scrollable) {\n scrollable.scrollToOffset({ offset: 0, animated: true });\n } else if ('scrollResponderScrollTo' in scrollable) {\n scrollable.scrollResponderScrollTo({ y: 0, animated: true });\n }\n }\n });\n }\n );\n\n return unsubscribe;\n }, [navigation, ref, route.key]);\n}\n"],"mappings":";;;;;;;AAAA;;AACA;;;;;;AAeA,SAASA,iBAAT,CAA2BC,GAA3B,EAAoE;EAClE,IAAIA,GAAG,CAACC,OAAJ,IAAe,IAAnB,EAAyB;IACvB,OAAO,IAAP;EACD;;EAED,IACE,iBAAiBD,GAAG,CAACC,OAArB,IACA,cAAcD,GAAG,CAACC,OADlB,IAEA,oBAAoBD,GAAG,CAACC,OAFxB,IAGA,6BAA6BD,GAAG,CAACC,OAJnC,EAKE;IACA;IACA,OAAOD,GAAG,CAACC,OAAX;EACD,CARD,MAQO,IAAI,wBAAwBD,GAAG,CAACC,OAAhC,EAAyC;IAC9C;IACA;IACA,OAAOD,GAAG,CAACC,OAAJ,CAAYC,kBAAZ,EAAP;EACD,CAJM,MAIA,IAAI,aAAaF,GAAG,CAACC,OAArB,EAA8B;IACnC;IACA;IACA;IACA;IACA,OAAOD,GAAG,CAACC,OAAJ,CAAYE,OAAZ,EAAP;EACD,CANM,MAMA;IACL,OAAOH,GAAG,CAACC,OAAX;EACD;AACF;;AAEc,SAASG,cAAT,CACbJ,GADa,EAEb;EACA,MAAMK,UAAU,GAAG,IAAAC,mBAAA,GAAnB;EACA,MAAMC,KAAK,GAAG,IAAAC,cAAA,GAAd;EAEAC,KAAK,CAACC,SAAN,CAAgB,MAAM;IACpB,IAAIT,OAAO,GAAGI,UAAd,CADoB,CAGpB;IACA;;IACA,OAAOJ,OAAO,IAAIA,OAAO,CAACU,QAAR,GAAmBC,IAAnB,KAA4B,KAA9C,EAAqD;MACnDX,OAAO,GAAGA,OAAO,CAACY,SAAR,EAAV;IACD;;IAED,IAAI,CAACZ,OAAL,EAAc;MACZ;IACD;;IAED,MAAMa,WAAW,GAAGb,OAAO,CAACc,WAAR,EAClB;IACA;IACA;IACA,UAJkB,EAKjBC,CAAD,IAAmC;MACjC;MACA,MAAMC,SAAS,GAAGZ,UAAU,CAACY,SAAX,EAAlB,CAFiC,CAIjC;MACA;;MACA,MAAMC,OAAO,GACXb,UAAU,KAAKJ,OAAf,IACAI,UAAU,CAACM,QAAX,GAAsBQ,MAAtB,CAA6B,CAA7B,EAAgCC,GAAhC,KAAwCb,KAAK,CAACa,GAFhD,CANiC,CAUjC;MACA;;MACAC,qBAAqB,CAAC,MAAM;QAC1B,MAAMC,UAAU,GAAGvB,iBAAiB,CAACC,GAAD,CAApC;;QAEA,IAAIiB,SAAS,IAAIC,OAAb,IAAwBI,UAAxB,IAAsC,CAACN,CAAC,CAACO,gBAA7C,EAA+D;UAC7D,IAAI,iBAAiBD,UAArB,EAAiC;YAC/BA,UAAU,CAACE,WAAX;UACD,CAFD,MAEO,IAAI,cAAcF,UAAlB,EAA8B;YACnCA,UAAU,CAACG,QAAX,CAAoB;cAAEC,CAAC,EAAE,CAAL;cAAQC,CAAC,EAAE,CAAX;cAAcC,QAAQ,EAAE;YAAxB,CAApB;UACD,CAFM,MAEA,IAAI,oBAAoBN,UAAxB,EAAoC;YACzCA,UAAU,CAACO,cAAX,CAA0B;cAAEC,MAAM,EAAE,CAAV;cAAaF,QAAQ,EAAE;YAAvB,CAA1B;UACD,CAFM,MAEA,IAAI,6BAA6BN,UAAjC,EAA6C;YAClDA,UAAU,CAACS,uBAAX,CAAmC;cAAEJ,CAAC,EAAE,CAAL;cAAQC,QAAQ,EAAE;YAAlB,CAAnC;UACD;QACF;MACF,CAdoB,CAArB;IAeD,CAhCiB,CAApB;IAmCA,OAAOd,WAAP;EACD,CAjDD,EAiDG,CAACT,UAAD,EAAaL,GAAb,EAAkBO,KAAK,CAACa,GAAxB,CAjDH;AAkDD"}
\No newline at end of file