@amazon-devices/react-navigation__native 8.0.9000000000 → 8.0.9000000002

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/SystemModules/amzn__react-navigation__native-8.private.modules.txt +38 -33
  2. package/kepler-compatibility.json +4 -2
  3. package/lib/module/index.js +0 -19
  4. package/oss-attribution/attribution.txt +50 -0
  5. package/oss-attribution/licenseInfos.json +18 -0
  6. package/package.json +1 -1
  7. package/src/index.tsx +1 -17
  8. package/SystemBundles/0fc5c971c5cf41a0dab235bcc6d58e5c06d9aaff650fa9815b525f8b9bb70a03.bundle +0 -9116
  9. package/SystemBundles/0fc5c971c5cf41a0dab235bcc6d58e5c06d9aaff650fa9815b525f8b9bb70a03.map +0 -3543
  10. package/lib/module/Link.js +0 -62
  11. package/lib/module/LinkingContext.js +0 -11
  12. package/lib/module/LocaleDirContext.js +0 -6
  13. package/lib/module/NavigationContainer.js +0 -128
  14. package/lib/module/ServerContainer.js +0 -55
  15. package/lib/module/ServerContext.js +0 -5
  16. package/lib/module/UnhandledLinkingContext.js +0 -14
  17. package/lib/module/__stubs__/createStackNavigator.js +0 -18
  18. package/lib/module/__stubs__/window.js +0 -75
  19. package/lib/module/createMemoryHistory.js +0 -216
  20. package/lib/module/createStaticNavigation.js +0 -54
  21. package/lib/module/extractPathFromURL.js +0 -19
  22. package/lib/module/theming/DarkTheme.js +0 -16
  23. package/lib/module/theming/DefaultTheme.js +0 -16
  24. package/lib/module/theming/fonts.js +0 -61
  25. package/lib/module/types.js +0 -4
  26. package/lib/module/useBackButton.js +0 -7
  27. package/lib/module/useBackButton.native.js +0 -21
  28. package/lib/module/useDocumentTitle.js +0 -26
  29. package/lib/module/useDocumentTitle.native.js +0 -6
  30. package/lib/module/useLinkBuilder.js +0 -85
  31. package/lib/module/useLinkProps.js +0 -93
  32. package/lib/module/useLinkTo.js +0 -26
  33. package/lib/module/useLinking.js +0 -320
  34. package/lib/module/useLinking.native.js +0 -148
  35. package/lib/module/useLocale.js +0 -18
  36. package/lib/module/useRoutePath.js +0 -30
  37. package/lib/module/useScrollToTop.js +0 -91
  38. package/lib/module/useThenable.js +0 -36
  39. package/src/Link.tsx +0 -69
  40. package/src/LinkingContext.tsx +0 -16
  41. package/src/LocaleDirContext.tsx +0 -7
  42. package/src/NavigationContainer.tsx +0 -211
  43. package/src/ServerContainer.tsx +0 -57
  44. package/src/ServerContext.tsx +0 -12
  45. package/src/UnhandledLinkingContext.tsx +0 -18
  46. package/src/__stubs__/createStackNavigator.tsx +0 -46
  47. package/src/__stubs__/window.tsx +0 -77
  48. package/src/createMemoryHistory.tsx +0 -229
  49. package/src/createStaticNavigation.tsx +0 -109
  50. package/src/extractPathFromURL.tsx +0 -29
  51. package/src/theming/DarkTheme.tsx +0 -15
  52. package/src/theming/DefaultTheme.tsx +0 -15
  53. package/src/theming/fonts.tsx +0 -63
  54. package/src/types.tsx +0 -191
  55. package/src/useBackButton.native.tsx +0 -33
  56. package/src/useBackButton.tsx +0 -11
  57. package/src/useDocumentTitle.native.tsx +0 -3
  58. package/src/useDocumentTitle.tsx +0 -41
  59. package/src/useLinkBuilder.tsx +0 -127
  60. package/src/useLinkProps.tsx +0 -156
  61. package/src/useLinkTo.tsx +0 -31
  62. package/src/useLinking.native.tsx +0 -217
  63. package/src/useLinking.tsx +0 -442
  64. package/src/useLocale.tsx +0 -18
  65. package/src/useRoutePath.tsx +0 -34
  66. package/src/useScrollToTop.tsx +0 -120
  67. package/src/useThenable.tsx +0 -42
@@ -1,442 +0,0 @@
1
- import {
2
- findFocusedRoute,
3
- getActionFromState as getActionFromStateDefault,
4
- getPathFromState as getPathFromStateDefault,
5
- getStateFromPath as getStateFromPathDefault,
6
- type NavigationContainerRef,
7
- type NavigationState,
8
- type ParamListBase,
9
- useNavigationIndependentTree,
10
- } from '@amazon-devices/react-navigation__core';
11
- import isEqual from 'fast-deep-equal';
12
- import * as React from 'react';
13
-
14
- import { createMemoryHistory } from './createMemoryHistory';
15
- import { ServerContext } from './ServerContext';
16
- import type { LinkingOptions } from './types';
17
-
18
- type ResultState = ReturnType<typeof getStateFromPathDefault>;
19
-
20
- /**
21
- * Find the matching navigation state that changed between 2 navigation states
22
- * e.g.: a -> b -> c -> d and a -> b -> c -> e -> f, if history in b changed, b is the matching state
23
- */
24
- const findMatchingState = <T extends NavigationState>(
25
- a: T | undefined,
26
- b: T | undefined
27
- ): [T | undefined, T | undefined] => {
28
- if (a === undefined || b === undefined || a.key !== b.key) {
29
- return [undefined, undefined];
30
- }
31
-
32
- // Tab and drawer will have `history` property, but stack will have history in `routes`
33
- const aHistoryLength = a.history ? a.history.length : a.routes.length;
34
- const bHistoryLength = b.history ? b.history.length : b.routes.length;
35
-
36
- const aRoute = a.routes[a.index];
37
- const bRoute = b.routes[b.index];
38
-
39
- const aChildState = aRoute.state as T | undefined;
40
- const bChildState = bRoute.state as T | undefined;
41
-
42
- // Stop here if this is the state object that changed:
43
- // - history length is different
44
- // - focused routes are different
45
- // - one of them doesn't have child state
46
- // - child state keys are different
47
- if (
48
- aHistoryLength !== bHistoryLength ||
49
- aRoute.key !== bRoute.key ||
50
- aChildState === undefined ||
51
- bChildState === undefined ||
52
- aChildState.key !== bChildState.key
53
- ) {
54
- return [a, b];
55
- }
56
-
57
- return findMatchingState(aChildState, bChildState);
58
- };
59
-
60
- /**
61
- * Run async function in series as it's called.
62
- */
63
- export const series = (cb: () => Promise<void>) => {
64
- let queue = Promise.resolve();
65
- const callback = () => {
66
- // eslint-disable-next-line promise/no-callback-in-promise
67
- queue = queue.then(cb);
68
- };
69
- return callback;
70
- };
71
-
72
- const linkingHandlers: symbol[] = [];
73
-
74
- type Options = LinkingOptions<ParamListBase>;
75
-
76
- export function useLinking(
77
- ref: React.RefObject<NavigationContainerRef<ParamListBase> | null>,
78
- {
79
- enabled = true,
80
- config,
81
- getStateFromPath = getStateFromPathDefault,
82
- getPathFromState = getPathFromStateDefault,
83
- getActionFromState = getActionFromStateDefault,
84
- }: Options,
85
- onUnhandledLinking: (lastUnhandledLining: string | undefined) => void
86
- ) {
87
- const independent = useNavigationIndependentTree();
88
-
89
- React.useEffect(() => {
90
- if (process.env.NODE_ENV === 'production') {
91
- return undefined;
92
- }
93
-
94
- if (independent) {
95
- return undefined;
96
- }
97
-
98
- if (enabled !== false && linkingHandlers.length) {
99
- console.error(
100
- [
101
- 'Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:',
102
- "- You don't have multiple NavigationContainers in the app each with 'linking' enabled",
103
- '- Only a single instance of the root component is rendered',
104
- ]
105
- .join('\n')
106
- .trim()
107
- );
108
- }
109
-
110
- const handler = Symbol();
111
-
112
- if (enabled !== false) {
113
- linkingHandlers.push(handler);
114
- }
115
-
116
- return () => {
117
- const index = linkingHandlers.indexOf(handler);
118
-
119
- if (index > -1) {
120
- linkingHandlers.splice(index, 1);
121
- }
122
- };
123
- }, [enabled, independent]);
124
-
125
- const [history] = React.useState(createMemoryHistory);
126
-
127
- // We store these options in ref to avoid re-creating getInitialState and re-subscribing listeners
128
- // This lets user avoid wrapping the items in `React.useCallback` or `React.useMemo`
129
- // Not re-creating `getInitialState` is important coz it makes it easier for the user to use in an effect
130
- const enabledRef = React.useRef(enabled);
131
- const configRef = React.useRef(config);
132
- const getStateFromPathRef = React.useRef(getStateFromPath);
133
- const getPathFromStateRef = React.useRef(getPathFromState);
134
- const getActionFromStateRef = React.useRef(getActionFromState);
135
-
136
- React.useEffect(() => {
137
- enabledRef.current = enabled;
138
- configRef.current = config;
139
- getStateFromPathRef.current = getStateFromPath;
140
- getPathFromStateRef.current = getPathFromState;
141
- getActionFromStateRef.current = getActionFromState;
142
- });
143
-
144
- const validateRoutesNotExistInRootState = React.useCallback(
145
- (state: ResultState) => {
146
- const navigation = ref.current;
147
- const rootState = navigation?.getRootState();
148
- // Make sure that the routes in the state exist in the root navigator
149
- // Otherwise there's an error in the linking configuration
150
- return state?.routes.some((r) => !rootState?.routeNames.includes(r.name));
151
- },
152
- [ref]
153
- );
154
-
155
- const server = React.useContext(ServerContext);
156
-
157
- const getInitialState = React.useCallback(() => {
158
- let value: ResultState | undefined;
159
-
160
- if (enabledRef.current) {
161
- const location =
162
- server?.location ??
163
- (typeof window !== 'undefined' ? window.location : undefined);
164
-
165
- const path = location ? location.pathname + location.search : undefined;
166
-
167
- if (path) {
168
- value = getStateFromPathRef.current(path, configRef.current);
169
- }
170
-
171
- // If the link were handled, it gets cleared in NavigationContainer
172
- onUnhandledLinking(path);
173
- }
174
-
175
- const thenable = {
176
- then(onfulfilled?: (state: ResultState | undefined) => void) {
177
- return Promise.resolve(onfulfilled ? onfulfilled(value) : value);
178
- },
179
- catch() {
180
- return thenable;
181
- },
182
- };
183
-
184
- return thenable as PromiseLike<ResultState | undefined>;
185
- // eslint-disable-next-line react-hooks/exhaustive-deps
186
- }, []);
187
-
188
- const previousIndexRef = React.useRef<number | undefined>(undefined);
189
- const previousStateRef = React.useRef<NavigationState | undefined>(undefined);
190
- const pendingPopStatePathRef = React.useRef<string | undefined>(undefined);
191
-
192
- React.useEffect(() => {
193
- previousIndexRef.current = history.index;
194
-
195
- return history.listen(() => {
196
- const navigation = ref.current;
197
-
198
- if (!navigation || !enabled) {
199
- return;
200
- }
201
-
202
- const { location } = window;
203
-
204
- const path = location.pathname + location.search;
205
- const index = history.index;
206
-
207
- const previousIndex = previousIndexRef.current ?? 0;
208
-
209
- previousIndexRef.current = index;
210
- pendingPopStatePathRef.current = path;
211
-
212
- // When browser back/forward is clicked, we first need to check if state object for this index exists
213
- // If it does we'll reset to that state object
214
- // Otherwise, we'll handle it like a regular deep link
215
- const record = history.get(index);
216
-
217
- if (record?.path === path && record?.state) {
218
- navigation.resetRoot(record.state);
219
- return;
220
- }
221
-
222
- const state = getStateFromPathRef.current(path, configRef.current);
223
-
224
- // We should only dispatch an action when going forward
225
- // Otherwise the action will likely add items to history, which would mess things up
226
- if (state) {
227
- // If the link were handled, it gets cleared in NavigationContainer
228
- onUnhandledLinking(path);
229
- // Make sure that the routes in the state exist in the root navigator
230
- // Otherwise there's an error in the linking configuration
231
- if (validateRoutesNotExistInRootState(state)) {
232
- return;
233
- }
234
-
235
- if (index > previousIndex) {
236
- const action = getActionFromStateRef.current(
237
- state,
238
- configRef.current
239
- );
240
-
241
- if (action !== undefined) {
242
- try {
243
- navigation.dispatch(action);
244
- } catch (e) {
245
- // Ignore any errors from deep linking.
246
- // This could happen in case of malformed links, navigation object not being initialized etc.
247
- console.warn(
248
- `An error occurred when trying to handle the link '${path}': ${
249
- typeof e === 'object' && e != null && 'message' in e
250
- ? e.message
251
- : e
252
- }`
253
- );
254
- }
255
- } else {
256
- navigation.resetRoot(state);
257
- }
258
- } else {
259
- navigation.resetRoot(state);
260
- }
261
- } else {
262
- // if current path didn't return any state, we should revert to initial state
263
- navigation.resetRoot(state);
264
- }
265
- });
266
- }, [
267
- enabled,
268
- history,
269
- onUnhandledLinking,
270
- ref,
271
- validateRoutesNotExistInRootState,
272
- ]);
273
-
274
- React.useEffect(() => {
275
- if (!enabled) {
276
- return;
277
- }
278
-
279
- const getPathForRoute = (
280
- route: ReturnType<typeof findFocusedRoute>,
281
- state: NavigationState
282
- ): string => {
283
- let path;
284
-
285
- // If the `route` object contains a `path`, use that path as long as `route.name` and `params` still match
286
- // This makes sure that we preserve the original URL for wildcard routes
287
- if (route?.path) {
288
- const stateForPath = getStateFromPathRef.current(
289
- route.path,
290
- configRef.current
291
- );
292
-
293
- if (stateForPath) {
294
- const focusedRoute = findFocusedRoute(stateForPath);
295
-
296
- if (
297
- focusedRoute &&
298
- focusedRoute.name === route.name &&
299
- isEqual(focusedRoute.params, route.params)
300
- ) {
301
- path = route.path;
302
- }
303
- }
304
- }
305
-
306
- if (path == null) {
307
- path = getPathFromStateRef.current(state, configRef.current);
308
- }
309
-
310
- const previousRoute = previousStateRef.current
311
- ? findFocusedRoute(previousStateRef.current)
312
- : undefined;
313
-
314
- // Preserve the hash if the route didn't change
315
- if (
316
- previousRoute &&
317
- route &&
318
- 'key' in previousRoute &&
319
- 'key' in route &&
320
- previousRoute.key === route.key
321
- ) {
322
- path = path + location.hash;
323
- }
324
-
325
- return path;
326
- };
327
-
328
- if (ref.current) {
329
- // We need to record the current metadata on the first render if they aren't set
330
- // This will allow the initial state to be in the history entry
331
- const state = ref.current.getRootState();
332
-
333
- if (state) {
334
- const route = findFocusedRoute(state);
335
- const path = getPathForRoute(route, state);
336
-
337
- if (previousStateRef.current === undefined) {
338
- previousStateRef.current = state;
339
- }
340
-
341
- history.replace({ path, state });
342
- }
343
- }
344
-
345
- const onStateChange = async () => {
346
- const navigation = ref.current;
347
-
348
- if (!navigation || !enabled) {
349
- return;
350
- }
351
-
352
- const previousState = previousStateRef.current;
353
- const state = navigation.getRootState();
354
-
355
- // root state may not available, for example when root navigators switch inside the container
356
- if (!state) {
357
- return;
358
- }
359
-
360
- const pendingPath = pendingPopStatePathRef.current;
361
- const route = findFocusedRoute(state);
362
- const path = getPathForRoute(route, state);
363
-
364
- previousStateRef.current = state;
365
- pendingPopStatePathRef.current = undefined;
366
-
367
- // To detect the kind of state change, we need to:
368
- // - Find the common focused navigation state in previous and current state
369
- // - If only the route keys changed, compare history/routes.length to check if we go back/forward/replace
370
- // - If no common focused navigation state found, it's a replace
371
- const [previousFocusedState, focusedState] = findMatchingState(
372
- previousState,
373
- state
374
- );
375
-
376
- if (
377
- previousFocusedState &&
378
- focusedState &&
379
- // We should only handle push/pop if path changed from what was in last `popstate`
380
- // Otherwise it's likely a change triggered by `popstate`
381
- path !== pendingPath
382
- ) {
383
- const historyDelta =
384
- (focusedState.history
385
- ? focusedState.history.length
386
- : focusedState.routes.length) -
387
- (previousFocusedState.history
388
- ? previousFocusedState.history.length
389
- : previousFocusedState.routes.length);
390
-
391
- if (historyDelta > 0) {
392
- // If history length is increased, we should pushState
393
- // Note that path might not actually change here, for example, drawer open should pushState
394
- history.push({ path, state });
395
- } else if (historyDelta < 0) {
396
- // If history length is decreased, i.e. entries were removed, we want to go back
397
-
398
- const nextIndex = history.backIndex({ path });
399
- const currentIndex = history.index;
400
-
401
- try {
402
- if (
403
- nextIndex !== -1 &&
404
- nextIndex < currentIndex &&
405
- // We should only go back if the entry exists and it's less than current index
406
- history.get(nextIndex)
407
- ) {
408
- // An existing entry for this path exists and it's less than current index, go back to that
409
- await history.go(nextIndex - currentIndex);
410
- } else {
411
- // We couldn't find an existing entry to go back to, so we'll go back by the delta
412
- // This won't be correct if multiple routes were pushed in one go before
413
- // Usually this shouldn't happen and this is a fallback for that
414
- await history.go(historyDelta);
415
- }
416
-
417
- // Store the updated state as well as fix the path if incorrect
418
- history.replace({ path, state });
419
- } catch (e) {
420
- // The navigation was interrupted
421
- }
422
- } else {
423
- // If history length is unchanged, we want to replaceState
424
- history.replace({ path, state });
425
- }
426
- } else {
427
- // If no common navigation state was found, assume it's a replace
428
- // This would happen if the user did a reset/conditionally changed navigators
429
- history.replace({ path, state });
430
- }
431
- };
432
-
433
- // We debounce onStateChange coz we don't want multiple state changes to be handled at one time
434
- // This could happen since `history.go(n)` is asynchronous
435
- // If `pushState` or `replaceState` were called before `history.go(n)` completes, it'll mess stuff up
436
- return ref.current?.addListener('state', series(onStateChange));
437
- }, [enabled, history, ref]);
438
-
439
- return {
440
- getInitialState,
441
- };
442
- }
package/src/useLocale.tsx DELETED
@@ -1,18 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { LocaleDirContext } from './LocaleDirContext';
4
-
5
- /**
6
- * Hook to access the text direction specified in the `NavigationContainer`.
7
- */
8
- export function useLocale() {
9
- const direction = React.useContext(LocaleDirContext);
10
-
11
- if (direction === undefined) {
12
- throw new Error(
13
- "Couldn't determine the text direction. Is your component inside NavigationContainer?"
14
- );
15
- }
16
-
17
- return { direction };
18
- }
@@ -1,34 +0,0 @@
1
- import { getPathFromState, useStateForPath } from '@amazon-devices/react-navigation__core';
2
- import * as React from 'react';
3
-
4
- import { LinkingContext } from './LinkingContext';
5
-
6
- /**
7
- * Hook to get the path for the current route based on linking options.
8
- *
9
- * @returns Path for the current route.
10
- */
11
- export function useRoutePath() {
12
- const { options } = React.useContext(LinkingContext);
13
- const state = useStateForPath();
14
-
15
- if (state === undefined) {
16
- throw new Error(
17
- "Couldn't find a state for the route object. Is your component inside a screen in a navigator?"
18
- );
19
- }
20
-
21
- const getPathFromStateHelper = options?.getPathFromState ?? getPathFromState;
22
-
23
- const path = React.useMemo(() => {
24
- if (options?.enabled === false) {
25
- return undefined;
26
- }
27
-
28
- const path = getPathFromStateHelper(state, options?.config);
29
-
30
- return path;
31
- }, [options?.enabled, options?.config, state, getPathFromStateHelper]);
32
-
33
- return path;
34
- }
@@ -1,120 +0,0 @@
1
- import {
2
- type EventArg,
3
- NavigationContext,
4
- type NavigationProp,
5
- type ParamListBase,
6
- useRoute,
7
- } from '@amazon-devices/react-navigation__core';
8
- import * as React from 'react';
9
- import type { ScrollView } from 'react-native';
10
-
11
- type ScrollOptions = { x?: number; y?: number; animated?: boolean };
12
-
13
- type ScrollableView =
14
- | { scrollToTop(): void }
15
- | { scrollTo(options: ScrollOptions): void }
16
- | { scrollToOffset(options: { offset: number; animated?: boolean }): void }
17
- | { scrollResponderScrollTo(options: ScrollOptions): void };
18
-
19
- type ScrollableWrapper =
20
- | { getScrollResponder(): React.ReactNode | ScrollView }
21
- | { getNode(): ScrollableView }
22
- | ScrollableView;
23
-
24
- function getScrollableNode(ref: React.RefObject<ScrollableWrapper>) {
25
- if (ref.current == null) {
26
- return null;
27
- }
28
-
29
- if (
30
- 'scrollToTop' in ref.current ||
31
- 'scrollTo' in ref.current ||
32
- 'scrollToOffset' in ref.current ||
33
- 'scrollResponderScrollTo' in ref.current
34
- ) {
35
- // This is already a scrollable node.
36
- return ref.current;
37
- } else if ('getScrollResponder' in ref.current) {
38
- // If the view is a wrapper like FlatList, SectionList etc.
39
- // We need to use `getScrollResponder` to get access to the scroll responder
40
- return ref.current.getScrollResponder();
41
- } else if ('getNode' in ref.current) {
42
- // When a `ScrollView` is wrapped in `Animated.createAnimatedComponent`
43
- // we need to use `getNode` to get the ref to the actual scrollview.
44
- // Note that `getNode` is deprecated in newer versions of react-native
45
- // this is why we check if we already have a scrollable node above.
46
- return ref.current.getNode();
47
- } else {
48
- return ref.current;
49
- }
50
- }
51
-
52
- export function useScrollToTop(ref: React.RefObject<ScrollableWrapper>) {
53
- const navigation = React.useContext(NavigationContext);
54
- const route = useRoute();
55
-
56
- if (navigation === undefined) {
57
- throw new Error(
58
- "Couldn't find a navigation object. Is your component inside NavigationContainer?"
59
- );
60
- }
61
-
62
- React.useEffect(() => {
63
- const tabNavigations: NavigationProp<ParamListBase>[] = [];
64
- let currentNavigation = navigation;
65
- // If the screen is nested inside multiple tab navigators, we should scroll to top for any of them
66
- // So we need to find all the parent tab navigators and add the listeners there
67
- while (currentNavigation) {
68
- if (currentNavigation.getState().type === 'tab') {
69
- tabNavigations.push(currentNavigation);
70
- }
71
-
72
- currentNavigation = currentNavigation.getParent();
73
- }
74
-
75
- if (tabNavigations.length === 0) {
76
- return;
77
- }
78
-
79
- const unsubscribers = tabNavigations.map((tab) => {
80
- return tab.addListener(
81
- // We don't wanna import tab types here to avoid extra deps
82
- // in addition, there are multiple tab implementations
83
- // @ts-expect-error the `tabPress` event is only available when navigation type is tab
84
- 'tabPress',
85
- (e: EventArg<'tabPress', true>) => {
86
- // We should scroll to top only when the screen is focused
87
- const isFocused = navigation.isFocused();
88
-
89
- // In a nested stack navigator, tab press resets the stack to first screen
90
- // So we should scroll to top only when we are on first screen
91
- const isFirst =
92
- tabNavigations.includes(navigation) ||
93
- navigation.getState().routes[0].key === route.key;
94
-
95
- // Run the operation in the next frame so we're sure all listeners have been run
96
- // This is necessary to know if preventDefault() has been called
97
- requestAnimationFrame(() => {
98
- const scrollable = getScrollableNode(ref) as ScrollableWrapper;
99
-
100
- if (isFocused && isFirst && scrollable && !e.defaultPrevented) {
101
- if ('scrollToTop' in scrollable) {
102
- scrollable.scrollToTop();
103
- } else if ('scrollTo' in scrollable) {
104
- scrollable.scrollTo({ y: 0, animated: true });
105
- } else if ('scrollToOffset' in scrollable) {
106
- scrollable.scrollToOffset({ offset: 0, animated: true });
107
- } else if ('scrollResponderScrollTo' in scrollable) {
108
- scrollable.scrollResponderScrollTo({ y: 0, animated: true });
109
- }
110
- }
111
- });
112
- }
113
- );
114
- });
115
-
116
- return () => {
117
- unsubscribers.forEach((unsubscribe) => unsubscribe());
118
- };
119
- }, [navigation, ref, route.key]);
120
- }
@@ -1,42 +0,0 @@
1
- import * as React from 'react';
2
-
3
- export function useThenable<T>(create: () => PromiseLike<T>) {
4
- const [promise] = React.useState(create);
5
-
6
- let initialState: [boolean, T | undefined] = [false, undefined];
7
-
8
- // Check if our thenable is synchronous
9
- // eslint-disable-next-line promise/catch-or-return, promise/always-return
10
- promise.then((result) => {
11
- initialState = [true, result];
12
- });
13
-
14
- const [state, setState] = React.useState(initialState);
15
- const [resolved] = state;
16
-
17
- React.useEffect(() => {
18
- let cancelled = false;
19
-
20
- const resolve = async () => {
21
- let result;
22
-
23
- try {
24
- result = await promise;
25
- } finally {
26
- if (!cancelled) {
27
- setState([true, result]);
28
- }
29
- }
30
- };
31
-
32
- if (!resolved) {
33
- resolve();
34
- }
35
-
36
- return () => {
37
- cancelled = true;
38
- };
39
- }, [promise, resolved]);
40
-
41
- return state;
42
- }