Compare commits

...

121 Commits

Author SHA1 Message Date
Satyajit Sahoo
2477db47a0 chore: publish
- @react-navigation/bottom-tabs@5.6.1
 - @react-navigation/compat@5.1.28
 - @react-navigation/core@5.11.1
 - @react-navigation/devtools@5.1.1
 - @react-navigation/drawer@5.8.4
 - @react-navigation/material-bottom-tabs@5.2.12
 - @react-navigation/material-top-tabs@5.2.12
 - @react-navigation/native@5.6.1
 - @react-navigation/stack@5.6.2
2020-06-25 17:31:40 +02:00
Satyajit Sahoo
d1210a861b fix: fix error with type definitions. closes #8511 2020-06-25 17:27:48 +02:00
Satyajit Sahoo
c4d2a8a828 chore: publish
- @react-navigation/stack@5.6.1
2020-06-25 11:45:59 +02:00
Satyajit Sahoo
fc95d7a256 fix: fix showing back button with headerMode=screen. fixes #8508 2020-06-25 11:42:19 +02:00
Satyajit Sahoo
978b197446 chore: publish
- @react-navigation/bottom-tabs@5.6.0
 - @react-navigation/compat@5.1.27
 - @react-navigation/core@5.11.0
 - @react-navigation/devtools@5.1.0
 - @react-navigation/drawer@5.8.3
 - @react-navigation/material-bottom-tabs@5.2.11
 - @react-navigation/material-top-tabs@5.2.11
 - @react-navigation/native@5.6.0
 - @react-navigation/routers@5.4.8
 - @react-navigation/stack@5.6.0
2020-06-24 22:29:01 +02:00
Satyajit Sahoo
c65f9ef1a9 fix: make sure we don't miss dimensions updates 2020-06-24 22:09:00 +02:00
Satyajit Sahoo
d85d27c432 fix: fix forward with history API. closes #8409 2020-06-24 21:50:30 +02:00
Satyajit Sahoo
f00091d7ab refactor: use ts-expect-errpr instead of ts-ignore 2020-06-24 20:07:32 +02:00
Satyajit Sahoo
67cd44d24b refactor: handle unhandled action in container 2020-06-24 17:09:06 +02:00
Satyajit Sahoo
a021cfb8af feat: rework linking configuration to be more strict (#8502)
The PR changes a few things about linking configuration:

- Moves the configuration for screens to a screens property so that it's possible to specify other options like `initialRouteName` for the navigator at root
- The nesting in the configuration needs to strictly match the shape of the navigation tree, it can't just rely on URL's shape anymore
- If a screen is not specified in the configuration, it won't be parsed to/from the URL (this is essential to handle unmatched screens)
- Treat `path: ''` and no specified path in the same way, unless `exact` is specified
- Disallow specifying unmatched screen with old format
- Add support for `initialRouteName` at top level
- Automatically adapt old configuration to new format
2020-06-24 16:54:24 +02:00
Satyajit Sahoo
a2d649faf1 feat: show back button in nested stack 2020-06-24 12:45:40 +02:00
Attila Szabo
1024a86a07 docs: updated description for drawer (#8497)
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
2020-06-23 22:21:10 +02:00
Satyajit Sahoo
c94d79d3a5 chore: add a sponsorship button to the repo 2020-06-23 22:15:00 +02:00
Satyajit Sahoo
37bbbbe869 fix: workaround keyboard dismissing on focus
closes #8414, closes #8478
2020-06-23 19:17:03 +02:00
Steven Conaway
84aea698f2 docs: fix grammar issue in a readme 2020-06-22 16:23:20 +02:00
Satyajit Sahoo
8177c45d14 feat: add an onReady callback to the container (#8491) 2020-06-22 14:03:57 +02:00
Satyajit Sahoo
16128199ed fix: remove broken showIcon option from bottom-tabs 2020-06-22 12:05:05 +02:00
Satyajit Sahoo
ea5affd914 fix: use interpolateNode in drawer to support Reanimated 2 2020-06-22 11:45:52 +02:00
Satyajit Sahoo
d2444887be fix: more improvements to types 2020-06-22 11:45:52 +02:00
Wojciech Lewicki
962456beb6 fix: fix screen disappearing on Android (#8473)
Added `collapsable={false}` to the View in order for the Android to render screens properly. This issue is most probably similar to 9c06a92d09 but fixes it on Android since the View seems to be removed from a native view hierarchy due to not drawing anything. To see the bug go to https://github.com/software-mansion/react-native-screens/issues/544.
2020-06-19 19:38:32 +02:00
Satyajit Sahoo
1aadc79fb8 refactor: enforce import type everywhere 2020-06-17 12:05:40 +02:00
Satyajit Sahoo
b14fd9453d chore: better check versions action 2020-06-16 22:44:03 +02:00
Satyajit Sahoo
cc3728fc95 chore: tweak repository field in package.json. closes #8423 2020-06-16 21:46:09 +02:00
Satyajit Sahoo
bf1ee2d9ff chore: master -> main 2020-06-16 21:42:22 +02:00
Satyajit Sahoo
6730690529 fix: fix getCurrentOptions for nested screens 2020-06-16 15:38:09 +02:00
Satyajit Sahoo
afc83eedf8 fix: fix getCurrentOptions for nested screens 2020-06-16 15:27:15 +02:00
Satyajit Sahoo
24e4333ec6 chore: update github workflows 2020-06-16 14:05:27 +02:00
Guilherme Pacheco
4480d2fe04 feat: add iconStyle prop to bottom tab bar options (#8188)
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
2020-06-15 19:11:03 +02:00
Satyajit Sahoo
33476b9cb5 refactor: tweak type for screen options 2020-06-15 18:34:08 +02:00
Satyajit Sahoo
07c30b2847 refactor: tweak types for bottom tab bar 2020-06-15 18:01:37 +02:00
Michał Osadnik
fe3f98eb9c feat: add event for options on container (#8334) 2020-06-15 17:56:01 +02:00
Kang Byung Seon
35d6b9e3a4 fix: don't use deprecated currentlyFocusedField (#8365)
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
2020-06-15 15:12:56 +02:00
Satyajit Sahoo
95b044ecf9 feat: add devtools package (#8436)
The `devtools` package extracts the redux devtools extension integration to a separate package. In future we can add more tools such as flipper integration to this package.

Usage:

```js
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { useReduxDevToolsExtension } from '@react-navigation/devtools';

export default function App() {
  const navigationRef = React.useRef();

  useReduxDevToolsExtension(navigationRef);

  return (
    <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
  );
}
```
2020-06-15 13:53:17 +02:00
Satyajit Sahoo
f51f9c8493 feat: add helper to get focused route name from nested state (#8435)
Currently, to access the focused child screen, we need to do something like this:

```js
const routeName = route.state
  ? route.state.routes[route.state.index].name
  : route.params?.screen || 'Feed';
```

However, it doesn't handle some cases, such as when `route.state` is partial. This helper will make it easier:

```js
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Feed';
```
2020-06-15 13:52:38 +02:00
Rajendran Nadar
e000138fe5 chore: add v5 package versions in readme (#8413) 2020-06-15 10:13:44 +02:00
Satyajit Sahoo
5042c86a09 chore: upgrade depenendecies 2020-06-12 18:37:40 +02:00
Satyajit Sahoo
34c907ec0a chore: publish
- @react-navigation/stack@5.5.1
2020-06-08 11:21:27 +02:00
Satyajit Sahoo
1ae07af796 fix: make sure the header is on top of the view 2020-06-08 11:17:53 +02:00
Satyajit Sahoo
220af93db5 chore: publish
- @react-navigation/stack@5.5.0
2020-06-08 10:56:32 +02:00
Satyajit Sahoo
1f27e4b1f6 fix: ignore onOpen from route that wasn't closing
closes #8257
2020-06-08 10:48:04 +02:00
Satyajit Sahoo
9c06a92d09 fix: fix blank screen with animationEnabled: false & headerShown: false
closes #8391
2020-06-08 10:17:02 +02:00
Satyajit Sahoo
e0e0f79793 feat: automatically hide header in nested stacks 2020-06-08 08:14:34 +02:00
Jeroen Verfallie
c7e4bf94e6 fix: pass gestureRef to PanGestureHandlerNative (#8394)
In the current implementation the ref is unused, resulting in a constant `current: {null}` on the context.
2020-06-08 08:05:59 +02:00
Satyajit Sahoo
7024d4bb81 docs: fix comment about headerBacktitleVisible 2020-06-08 01:47:09 +02:00
Satyajit Sahoo
21f61d6eeb chore: publish
- @react-navigation/bottom-tabs@5.5.2
 - @react-navigation/compat@5.1.26
 - @react-navigation/core@5.10.0
 - @react-navigation/drawer@5.8.2
 - @react-navigation/material-bottom-tabs@5.2.10
 - @react-navigation/material-top-tabs@5.2.10
 - @react-navigation/native@5.5.1
 - @react-navigation/stack@5.4.2
2020-06-06 02:15:26 +02:00
Jean Regisser
8774ca97e1 fix: catch missing params when they are required in navigate (#8389)
There is a problem with the enforcement of required params in `navigation.navigate(...)` in TypeScript as described in https://github.com/react-navigation/react-navigation/issues/7936

@Miyou found a fix 🥳. All credits go to him.

I needed this so went ahead and submitted a PR and added a test to avoid it from breaking in the future.

However note that until this project switches to TypeScript 3.9 with support for [`@ts-expect-error`](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9-beta/#ts-expect-error-comments), it can still break silently.

Before the change, this is how the test looks:
<img width="861" alt="Screenshot 2020-06-05 at 22 51 00" src="https://user-images.githubusercontent.com/57791/83923057-c53dc180-a781-11ea-8c35-36406a23a717.png">
As you can see it doesn't catch the missing params which are required on line 28.

After the change, all expected errors are raised:
<img width="812" alt="Screenshot 2020-06-05 at 22 51 59" src="https://user-images.githubusercontent.com/57791/83923413-80665a80-a782-11ea-8ff2-f5af3f4e1f32.png">

Let me know what you think.
2020-06-06 00:57:28 +02:00
Satyajit Sahoo
e653d55479 refactor: minor tweaks 2020-06-06 00:38:38 +02:00
Ashoat Tevosyan
78afbffe97 fix: relatively position float Header if !headerTransparent (#8285)
## Motivation

Right now `headerMode: float` renders an absolutely-positioned header. To offset the content appropriately, it then measures the height of the header and compensates with a margin. This approach unfortunately doesn't work well for animations.

Before             |  After
:-------------------------:|:-------------------------:
<img src="http://ashoat.com/jerky_absolute.gif" width="300" />  |  <img src="http://ashoat.com/smooth_relative.gif" width="300" />

## Approach

When rendering the header absolutely we want to render it above (after, in sibling order) the content. But when rendering it relatively we want to render it first (before, in sibling order).

The margin compensation code is no longer necessary so I removed it.

## Test plan

I used the `StackHeaderCustomization` example to make sure transitions between `headerTransparent` and `!headerTransparent` looked good. I added a custom (taller) header to test if height transitions looked good, and toggled `headerShown` to make sure that transitioned well too.

Would be open to any other suggestions of things to test!
2020-06-06 00:12:00 +02:00
Diego Mello
762cc44578 fix: typo on drawerPosition default props (#8357)
Fix a minor typo from `drawerPostion` to `drawerPosition` :)

Fix https://github.com/react-navigation/react-navigation/issues/8358
2020-06-05 23:48:10 +02:00
Satyajit Sahoo
c3bd349d77 fix: make sure the wildcard pattern catches nested unmatched routes 2020-06-05 23:03:37 +02:00
Satyajit Sahoo
5dcaf903f3 refactor: rework history stack integration (#8367)
The PR reworks history integration to better integrate with browser's history stack and supports nested navigation more reliably:

- On each navigation, save the navigation in memory and use it to reset the state when user presses back/forward
- Improve heuristic to determine if we should do a push, replace or back

This closes #8230, closes #8284 and closes #8344
2020-06-05 23:02:35 +02:00
Satyajit Sahoo
2d66ef93ec fix: only use the query params for focused route in path 2020-06-05 20:01:52 +02:00
Satyajit Sahoo
4fe72e3ce7 feat: add wildcard patterns for paths
Currently, if we don't have matching routes for a path, we'll reuse the path name for the route name. This doesn't produce an error, and renders the initial route in the navigator. However, the user doesn't have a way of handling this with the default configuration.

This PR adds support for a wildcard pattern ('*'). The wildcard pattern will be matched after all other patterns were matched and will always match unmatched screens. This allows the user to implement a 404 screen.

Example:

```js
{
  Home: '',
  Profile: 'user/:id',
  404: '*',
}
```

This config will return the `404` route for paths which didn't match `Home` or `Profile`, e.g. - `/test`

Closes #8019

Co-authored-by: Evan Bacon <baconbrix@gmail.com>
2020-06-05 17:13:00 +02:00
Satyajit Sahoo
ab1f79c096 fix: prevent state change being emitted unnecessarily 2020-06-01 21:32:08 +02:00
Satyajit Sahoo
9305bfa939 chore: try to fix yarn caching on gh actions 2020-05-27 20:12:33 +02:00
Satyajit Sahoo
0c3c450f5f chore: tweak SSR output 2020-05-27 19:55:37 +02:00
Satyajit Sahoo
7ac4c13d44 chore: publish
- @react-navigation/bottom-tabs@5.5.1
 - @react-navigation/compat@5.1.25
 - @react-navigation/core@5.9.0
 - @react-navigation/drawer@5.8.1
 - @react-navigation/material-bottom-tabs@5.2.9
 - @react-navigation/material-top-tabs@5.2.9
 - @react-navigation/native@5.5.0
 - @react-navigation/stack@5.4.1
2020-05-27 18:32:30 +02:00
Raviraj
a0b9f94120 refactor: remove unnecessary check for type of bottom tab bar label 2020-05-27 18:12:21 +02:00
Satyajit Sahoo
717dffdb81 chore: improve caching of yarn on gh actions 2020-05-27 13:31:50 +02:00
Satyajit Sahoo
9016ba00e3 chore: improve caching of yarn on circleci 2020-05-27 13:19:41 +02:00
Satyajit Sahoo
9d822b95a6 fix: fix type of style for various options 2020-05-26 17:33:50 +02:00
Satyajit Sahoo
52d5cb4179 chore: add an example for SSR (#8298)
<img width="740" alt="Screen Shot 2020-05-20 at 16 31 30" src="https://user-images.githubusercontent.com/1174278/82458770-673d8880-9ab7-11ea-81d3-8ac0c1e52705.png">
2020-05-26 16:07:47 +02:00
Satyajit Sahoo
af1722d1e9 fix: export types from /native 2020-05-26 14:11:48 +02:00
Satyajit Sahoo
0b1a718756 feat: add ref to get current options in ServerContainer (#8333)
User can pass a `ref` to the container to get current options, like they can with `NavigationContainer`:

```js
const ref = React.createRef();

const html = renderToString(
  <ServerContainer ref={ref}>
    <App />
  </ServerContainer>
);

ref.current.getCurrentOptions(); // Options for screen
```
2020-05-26 13:55:06 +02:00
Michał Osadnik
9ab29558d0 refactor: remove useless callback arg in useSubscription (#8332) 2020-05-26 13:21:51 +02:00
Bright Lee
00c23f2c9e fix: allow HeaderBackground's subViews to be touchable (#8317) 2020-05-25 15:50:24 +02:00
Satyajit Sahoo
68e750d5a6 feat: add a ServerContainer component for SSR (#8297)
When doing SSR, the app needs to be aware of request URL to render correct navigation state.
The `ServerContainer` component lets us pass the `location` object to use for SSR.
The shape of the `location` object matches the `location` object in the browser.

Usage:

```js
ReactDOM.renderToString(
  <ServerContainer location={{ pathname: req.path, search: req.search }}>
    <App />
  </ServerContainer>
);
```

Updated example: https://github.com/react-navigation/react-navigation/pull/8298
2020-05-24 14:28:16 +02:00
Satyajit Sahoo
ced2a24aa6 chore: publish
- @react-navigation/bottom-tabs@5.5.0
 - @react-navigation/compat@5.1.24
 - @react-navigation/core@5.8.2
 - @react-navigation/drawer@5.8.0
 - @react-navigation/material-bottom-tabs@5.2.8
 - @react-navigation/material-top-tabs@5.2.8
 - @react-navigation/native@5.4.3
 - @react-navigation/routers@5.4.7
 - @react-navigation/stack@5.4.0
2020-05-23 18:36:57 +02:00
Satyajit Sahoo
ebf1345b39 refactor: simplify bottom tab bar 2020-05-23 18:34:12 +02:00
Satyajit Sahoo
df3544d9b4 Revert "fix: allow HeaderBackground's subViews to be touchable" (#8316) 2020-05-23 18:22:35 +02:00
Ashoat Tevosyan
c1e46f8e33 feat: animate changes to tabBarVisible in BottomTabBar (#8286)
## Motivation

Some designs call for custom keyboard inputs, or other bottom-aligned views meant overlap over the keyboard. Right now the best option on Android for this case is to set `tabBarVisible`. However changes to `tabBarVisible` doesn't get animated currently, which makes the custom-keyboard-open experience a bit more jarring than the native-keyboard-open one.

## Approach

I basically cribbed the `Animated.Value` we were using for `keyboardHidesTabBar` and made it depend on both. Note that the offset height depends on which of the two uses cases we're dealing with, which is explained in the code.

## Test plan

I played around with the `BottomTabs` example, setting certain screens to `tabBarVisible: true` and making sure it animated.
2020-05-23 18:16:30 +02:00
Bright Lee
021a9111d7 fix: allow HeaderBackground's subViews to be touchable (#8314)
When you're using the following options on `Stack`, the touch event goes to the behind of the Header and we can't really solve this problem in given `headerBackground` component level.
```
 options={{
          headerTransparent: true,
          headerBackground: 
```

### Problem
![May-23-2020 09-31-01](https://user-images.githubusercontent.com/916690/82726502-ebc11e80-9ce4-11ea-81d0-cc6a18bd70a7.gif)
2020-05-23 18:14:59 +02:00
Satyajit Sahoo
d3ace96981 chore: add linking prefix for expo to slience the warning 2020-05-23 17:37:45 +02:00
Satyajit Sahoo
edbc6b1e84 chore: tweak metro config 2020-05-23 17:33:34 +02:00
Satyajit Sahoo
c52d19bec8 chore: add example to hide and show bottom tab bar 2020-05-21 15:31:34 +02:00
Satyajit Sahoo
6dd45fcff9 fix: don't ignore previous header heights on layout update 2020-05-21 12:54:12 +02:00
Janic Duplessis
d62fbfe255 feat: update react-native-safe-area-context to 1.0.0 (#8182)
I made sure 1.0 is backwards compatible with react-navigation, which means using rn-safe-area-context@1+ with older versions of react-navigation will still work.
2020-05-21 11:25:36 +02:00
Evan Bacon
b14094619f chore: ignore __tests__ in prod builds (#8307)
The tests are being bundled and shipped in prod, this adds a bit of unneeded weight to npm installs. Now they won't be included.

```
@react-navigation/core
- before: 274 files - pkg: 211.0 kB - unpkg: 1 MB
- after: 238 files - pkg: 192.1 kB - unpkg: 827.3 kB
```
2020-05-21 11:15:12 +02:00
Ashoat Tevosyan
4c4d864af2 refactor: memoize initializedState in useNavigationBuilder (#8281) 2020-05-21 11:13:06 +02:00
Michał Osadnik
e1969f4e17 refactor: extract NavigationStateContext (#8304) 2020-05-21 10:41:34 +02:00
Satyajit Sahoo
175c07a28c chore: publish
- @react-navigation/example@5.1.0
 - @react-navigation/bottom-tabs@5.4.7
 - @react-navigation/compat@5.1.23
 - @react-navigation/core@5.8.1
 - @react-navigation/drawer@5.7.7
 - @react-navigation/material-bottom-tabs@5.2.7
 - @react-navigation/material-top-tabs@5.2.7
 - @react-navigation/native@5.4.2
 - @react-navigation/routers@5.4.6
 - @react-navigation/stack@5.3.9
2020-05-20 13:27:29 +02:00
osdnk
2980627cbf chore: publish
- @react-navigation/bottom-tabs@5.4.6
 - @react-navigation/compat@5.1.22
 - @react-navigation/core@5.8.0
 - @react-navigation/drawer@5.7.6
 - @react-navigation/material-bottom-tabs@5.2.6
 - @react-navigation/material-top-tabs@5.2.6
 - @react-navigation/native@5.4.1
 - @react-navigation/routers@5.4.5
 - @react-navigation/stack@5.3.8
2020-05-20 10:29:05 +02:00
Michał Osadnik
d024ec6d74 feat: add getCurrentOptions (#8277) 2020-05-19 20:53:08 +02:00
Satyajit Sahoo
4d1b85c751 chore: limit height of material top tabs example 2020-05-19 19:27:05 +02:00
Satyajit Sahoo
4a818fdfb3 chore: tweak master-detail example 2020-05-19 18:56:51 +02:00
Satyajit Sahoo
0194de1061 chore: upgrade bob 2020-05-19 14:25:20 +02:00
Michał Osadnik
7b25c8eb2e feat: add getCurrentRoute (#8254) 2020-05-18 01:55:09 +02:00
Satyajit Sahoo
9304a8a16c chore: publish
- @react-navigation/bottom-tabs@5.4.5
 - @react-navigation/compat@5.1.21
 - @react-navigation/core@5.7.0
 - @react-navigation/drawer@5.7.5
 - @react-navigation/material-bottom-tabs@5.2.5
 - @react-navigation/material-top-tabs@5.2.5
 - @react-navigation/native@5.4.0
 - @react-navigation/stack@5.3.7
2020-05-17 01:20:24 +02:00
Satyajit Sahoo
51b40879bd fix: center icons in material tab bar. fixes #8248 2020-05-17 01:06:29 +02:00
Satyajit Sahoo
51f4d11fdf fix: don't use Object.fromEntries 2020-05-17 00:56:19 +02:00
Satyajit Sahoo
c2aa4bb2eb test: fix integration tests 2020-05-16 21:18:42 +02:00
Satyajit Sahoo
199a892a6d chore: fix the links in the example 2020-05-16 01:58:05 +02:00
Satyajit Sahoo
60cb3c9ba7 feat: add a PathConfig type 2020-05-15 18:57:28 +02:00
Satyajit Sahoo
6ccceaea8b chore: tweak linking config in the example 2020-05-15 18:48:03 +02:00
Satyajit Sahoo
d14f38b80a fix: fix types for linking options 2020-05-15 18:37:58 +02:00
Satyajit Sahoo
c481748f00 chore: publish
- @react-navigation/stack@5.3.6
2020-05-15 17:39:47 +02:00
Satyajit Sahoo
d45dbe97dc fix: reduce header title margin. fixes #8267 2020-05-15 17:39:33 +02:00
Janic Duplessis
7623945f6e chore: fix repo url in readme (#8235) 2020-05-14 19:10:08 +02:00
Satyajit Sahoo
1dddaff45c chore: publish
- @react-navigation/bottom-tabs@5.4.4
 - @react-navigation/compat@5.1.20
 - @react-navigation/core@5.6.1
 - @react-navigation/drawer@5.7.4
 - @react-navigation/material-bottom-tabs@5.2.4
 - @react-navigation/material-top-tabs@5.2.4
 - @react-navigation/native@5.3.2
 - @react-navigation/stack@5.3.5
2020-05-14 13:22:54 +02:00
Satyajit Sahoo
21b397f0d6 fix: don't use flat since it's not supported in node 2020-05-14 13:22:14 +02:00
Satyajit Sahoo
2ff0531695 chore: publish
- @react-navigation/bottom-tabs@5.4.3
 - @react-navigation/compat@5.1.19
 - @react-navigation/core@5.6.0
 - @react-navigation/drawer@5.7.3
 - @react-navigation/material-bottom-tabs@5.2.3
 - @react-navigation/material-top-tabs@5.2.3
 - @react-navigation/native@5.3.1
 - @react-navigation/stack@5.3.4
2020-05-14 12:45:50 +02:00
Satyajit Sahoo
0149e85a95 fix: ignore state updates when we're not mounted
closes #8226
2020-05-14 12:43:44 +02:00
Satyajit Sahoo
3c47716826 fix: ignore extra slashes in the pattern 2020-05-14 04:40:44 +02:00
Satyajit Sahoo
acc9646426 feat: merge path patterns for nested screens (#8253)
Currently, when we define path patterns in the linking config, they ignore the parent screen's path when parsing, for example, say we have this config:

{
  Home: {
    path: 'home',
    screens: {
      Profile: 'u/:id',
    },
  },
}
If we parse the URL /home, we'll get this state:

{
  routes: [{ name: 'Home' }],
}
If we parse the URL /home/u/cal, we'll get this state:

{
  routes: [
    {
      name: 'Home',
      state: {
        routes: [
          {
            name: 'Home',
            state: {
              routes: [
                {
                  name: 'Profile',
                  params: { id: 'cal' },
                },
              ],
            },
          },
        ],
      },
    },
  ],
}
Note how we have 2 Home screens nested inside each other. This is not something people usually expect and it seems to trip up a lot of people. Something like following will be more intuitive:

{
  routes: [
    {
      name: 'Home',
      state: {
        routes: [
          {
            name: 'Profile',
            params: { id: 'cal' },
          },
        ],
      },
    },
  ],
}
Essentially, we're treating patterns as relative to their parent rather than matching the exact segments. This PR changes the behavior of parsing links to treat configs like so. I hope it'll be easier to understand for people.

There is also a new option, exact, which brings back the olde behavior of matching the exact pattern:

{
  Home: {
    path: 'home',
    screens: {
      Profile: {
        path: 'u/:id',
        exact: true,
      },
    },
  },
}
Which will be useful if home is not in the URL, e.g. /u/cal.

This change only affects situations where both parent and child screen configuration have a pattern defined. If the parent didn't have a pattern defined, nothing changes from previous behavior:

{
  Home: {
    screens: {
      Profile: {
        path: 'u/:id',
      },
    },
  },
}
2020-05-14 00:39:32 +02:00
Satyajit Sahoo
6dce0780ed chore: publish
- @react-navigation/stack@5.3.3
2020-05-11 17:31:35 +02:00
Hein Rutjes
dd7cff2016 fix: fix ios transitionspec settle time (#8028)
# Why

When using the stack navigator on iOS, it takes a (too) long time before the  `didFocus` and stack `onTransitionEnd` lifecycle events are triggered. The visual animation is typically completed well within 500 msec, but it takes around 1000 msec before the previously mentioned events are emitted. This causes problems with for instance `react-navigation-shared-element`, which relies on these events to fire in a timely manner(https://github.com/IjzerenHein/react-navigation-shared-element/issues/24)

# How

This PR updates the resting threshold so that the underlying spring settles faster. No visual differences or differences in smoothness were witnessed during testing.

## Before

Time to settle `didFocus`: **941**
Time to settle `stack.onTransitionEnd`: **924**

```
15:59:55.743 [ListViewStack]startTransition, closing: false, nestingDepth: 1
15:59:55.744 [ListViewStack]willFocus, scene: "DetailScreen", depth: 1, closing: false
15:59:55.745 Transition start: "ListScreen" -> "DetailScreen"
15:59:56.667 [ListViewStack]endTransition, closing: false, nestingDepth: 1
15:59:56.668 Transition end: "DetailScreen"
15:59:56.685 [ListViewStack]didFocus, scene: "DetailScreen", depth: 1
```

## After

Time to settle `didFocus`: **529**
Time to settle `stack.onTransitionEnd`: **512**

```
15:55:00.686 [ListViewStack]startTransition, closing: false, nestingDepth: 1
15:55:00.687 [ListViewStack]willFocus, scene: "DetailScreen", depth: 1, closing: false
15:55:00.687 Transition start: "ListScreen" -> "DetailScreen"
15:55:01.198 [ListViewStack]endTransition, closing: false, nestingDepth: 1
15:55:01.199 Transition end: "DetailScreen"
15:55:01.216 [ListViewStack]didFocus, scene: "DetailScreen", depth: 1
2020-05-11 17:03:12 +02:00
Satyajit Sahoo
740c6b6706 chore: publish
- @react-navigation/bottom-tabs@5.4.2
 - @react-navigation/compat@5.1.18
 - @react-navigation/drawer@5.7.2
 - @react-navigation/material-bottom-tabs@5.2.2
 - @react-navigation/material-top-tabs@5.2.2
 - @react-navigation/native@5.3.0
 - @react-navigation/stack@5.3.2
2020-05-10 08:34:40 +02:00
Satyajit Sahoo
039017bc2a feat: initialState should take priority over deep link 2020-05-10 08:28:48 +02:00
Satyajit Sahoo
b85a1c3055 chore: publish
- @react-navigation/bottom-tabs@5.4.1
 - @react-navigation/compat@5.1.17
 - @react-navigation/core@5.5.2
 - @react-navigation/drawer@5.7.1
 - @react-navigation/material-bottom-tabs@5.2.1
 - @react-navigation/material-top-tabs@5.2.1
 - @react-navigation/native@5.2.6
 - @react-navigation/routers@5.4.4
 - @react-navigation/stack@5.3.1
2020-05-08 19:16:47 +02:00
Satyajit Sahoo
18f8188dc8 chore: add source key to package.json 2020-05-08 19:14:29 +02:00
Satyajit Sahoo
47a1229837 fix: fix building typescript definitions. closes #8216 2020-05-08 19:09:13 +02:00
Satyajit Sahoo
00b11e303e chore: publish
- @react-navigation/bottom-tabs@5.4.0
 - @react-navigation/compat@5.1.16
 - @react-navigation/core@5.5.1
 - @react-navigation/drawer@5.7.0
 - @react-navigation/material-bottom-tabs@5.2.0
 - @react-navigation/material-top-tabs@5.2.0
 - @react-navigation/native@5.2.5
 - @react-navigation/routers@5.4.3
 - @react-navigation/stack@5.3.0
2020-05-08 16:34:03 +02:00
Satyajit Sahoo
f384706741 feat: use links in bottom navigation tabs 2020-05-08 16:11:24 +02:00
Satyajit Sahoo
d1a6f3e30e chore: upgrade depenendecies 2020-05-08 16:06:28 +02:00
Satyajit Sahoo
fd6636a8cd chore: update circleci config 2020-05-08 03:19:47 +02:00
Satyajit Sahoo
eb24fea8b9 chore: upgrade depenendecies 2020-05-07 21:08:55 +02:00
Linus Unnebäck
85ae378d8c fix: return a promise-like from getInitialState (#8210) 2020-05-07 20:56:55 +02:00
Satyajit Sahoo
bea14aa26f feat: add generic type aliases for screen props
closes #7971
2020-05-06 19:00:04 +02:00
Satyajit Sahoo
4d1e102f8c fix: include safe are insets in title's margins 2020-05-06 16:49:02 +02:00
Satyajit Sahoo
f07cd13561 fix: add proper margins to the header title 2020-05-06 16:14:40 +02:00
Satyajit Sahoo
f6d06768d3 fix: avoid cleaning up state when a new navigator is mounted. fixes #8195 2020-05-06 15:49:59 +02:00
219 changed files with 14521 additions and 5715 deletions

View File

@@ -1,89 +1,97 @@
version: 2 version: 2.1
defaults: &defaults executors:
docker: default:
- image: circleci/node:10 docker:
working_directory: ~/project - image: circleci/node:10
working_directory: ~/project
environment:
YARN_CACHE_FOLDER: "~/.cache/yarn"
commands:
attach_project:
steps:
- attach_workspace:
at: ~/project
jobs: jobs:
install-dependencies: install-dependencies:
<<: *defaults executor: default
steps: steps:
- checkout - checkout
- attach_workspace: - attach_project
at: ~/project
- restore_cache: - restore_cache:
keys: keys:
- v1-dependencies-{{ checksum "yarn.lock" }} - yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
- v1-dependencies- - yarn-packages-v1-{{ .Branch }}-
- yarn-packages-v1-
- run: - run:
name: Install project dependencies name: Install project dependencies
command: yarn install --frozen-lockfile command: yarn install --frozen-lockfile
- save_cache: - save_cache:
key: v1-dependencies-{{ checksum "yarn.lock" }} key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
paths: node_modules paths: ~/.cache/yarn
- persist_to_workspace: - persist_to_workspace:
root: . root: .
paths: . paths: .
lint-and-typecheck: lint-and-typecheck:
<<: *defaults executor: default
steps: steps:
- attach_workspace: - attach_project
at: ~/project - run:
- run: name: Lint files
name: Lint files command: yarn lint
command: yarn lint - run:
- run: name: Typecheck files
name: Typecheck files command: yarn typescript
command: yarn typescript
unit-tests: unit-tests:
<<: *defaults executor: default
steps: steps:
- attach_workspace: - attach_project
at: ~/project - run:
- run: name: Run unit tests
name: Run unit tests command: yarn test --coverage
command: yarn test --coverage - run:
- run: name: Upload test coverage
name: Upload test coverage command: cat ./coverage/lcov.info | ./node_modules/.bin/codecov
command: cat ./coverage/lcov.info | ./node_modules/.bin/codecov - store_artifacts:
- store_artifacts: path: coverage
path: coverage destination: coverage
destination: coverage
integration-tests: integration-tests:
<<: *defaults executor: default
steps: steps:
- attach_workspace: - attach_project
at: ~/project - run:
- run: name: Install Headless Chrome dependencies
name: Install Headless Chrome dependencies command: |
command: | sudo apt-get install -yq \
sudo apt-get install -yq \ gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \ libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \ libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \ libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \ fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget - run:
- run: name: Build example for web
name: Build example for web command: yarn example expo build:web --no-pwa
command: yarn example expo build:web --no-pwa - run:
- run: name: Run integration tests
name: Run integration tests command: yarn example test --maxWorkers=2
command: yarn example test --maxWorkers=2
build-packages: build-packages:
<<: *defaults executor: default
steps: steps:
- attach_workspace: - attach_project
at: ~/project - run:
- run: name: Build packages in the monorepo
name: Build packages in the monorepo command: yarn lerna run prepare
command: yarn lerna run prepare - run:
- run: name: Verify paths for types
name: Verify paths for types command: node scripts/check-types-path.js
command: node scripts/check-types-path.js
workflows: workflows:
version: 2
build-and-test: build-and-test:
jobs: jobs:
- install-dependencies - install-dependencies

View File

@@ -11,7 +11,8 @@
"@react-navigation/drawer", "@react-navigation/drawer",
"@react-navigation/bottom-tabs", "@react-navigation/bottom-tabs",
"@react-navigation/material-top-tabs", "@react-navigation/material-top-tabs",
"@react-navigation/material-bottom-tabs" "@react-navigation/material-bottom-tabs",
"@react-navigation/devtools"
] ]
}, },
"env": { "browser": true, "node": true } "env": { "browser": true, "node": true }

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
github: react-navigation

View File

@@ -8,7 +8,7 @@ jobs:
if: github.event.pull_request.head.repo.owner.login == 'react-navigation' if: github.event.pull_request.head.repo.owner.login == 'react-navigation'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v1 uses: actions/setup-node@v1
@@ -23,20 +23,16 @@ jobs:
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }} expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
expo-cache: true expo-cache: true
- name: Get yarn cache - name: Restore yarn cache
id: yarn-cache id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)" uses: actions/cache@v2
- name: Check yarn cache
uses: actions/cache@v1
with: with:
path: ${{ steps.yarn-cache.outputs.dir }} path: '**/node_modules'
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies - name: Install dependencies
run: yarn if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile
- name: Publish Expo app - name: Publish Expo app
working-directory: ./example working-directory: ./example
@@ -47,8 +43,13 @@ jobs:
run: echo "::set-output name=path::@react-navigation/react-navigation-example?release-channel=pr-${{ github.event.number }}" run: echo "::set-output name=path::@react-navigation/react-navigation-example?release-channel=pr-${{ github.event.number }}"
- name: Comment on PR - name: Comment on PR
uses: unsplash/comment-on-pr@master uses: actions/github-script@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
msg: The Expo app for the example from this branch is ready!<br><br>[expo.io/${{ steps.expo.outputs.path }}](https://expo.io/${{ steps.expo.outputs.path }})<br><br><a href="https://exp.host/${{ steps.expo.outputs.path }}"><img src="https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=exp://exp.host/${{ steps.expo.outputs.path }}" height="200px" width="200px"></a>. github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'The Expo app for the example from this branch is ready!\n\n[expo.io/${{ steps.expo.outputs.path }}](https://expo.io/${{ steps.expo.outputs.path }})\n\n<a href="https://exp.host/${{ steps.expo.outputs.path }}"><img src="https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=exp://exp.host/${{ steps.expo.outputs.path }}" height="200px" width="200px"></a>'
})

View File

@@ -2,7 +2,7 @@ name: Expo Publish
on: on:
push: push:
branches: branches:
- master - main
jobs: jobs:
publish: publish:
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v1 uses: actions/checkout@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v1 uses: actions/setup-node@v1
@@ -25,19 +25,16 @@ jobs:
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }} expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
expo-cache: true expo-cache: true
- name: Get yarn cache - name: Restore yarn cache
id: yarn-cache id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)" uses: actions/cache@v2
- uses: actions/cache@v1
with: with:
path: ${{ steps.yarn-cache.outputs.dir }} path: '**/node_modules'
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install dependencies - name: Install dependencies
run: yarn if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile
- name: Publish Expo app - name: Publish Expo app
working-directory: ./example working-directory: ./example

View File

@@ -9,7 +9,8 @@ jobs:
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@master - name: Checkout
uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@@ -8,42 +8,58 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event.label.name == 'needs more info' if: github.event.label.name == 'needs more info'
steps: steps:
- uses: actions/checkout@master - uses: actions/github-script@v2
- uses: actions/github@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: comment "Hey! Thanks for opening the issue. Can you provide more information about the issue? Please fill the issue template when opening the issue without deleting any section. We need all the information we can to be able to help. Make sure to at least provide - Current behaviour, Expected behaviour, A way to [reproduce the issue with minimal code](https://stackoverflow.com/help/minimal-reproducible-example) (link to [snack.expo.io](https://snack.expo.io)) or a repo on GitHub, and the information about your environment (such as the platform of the device, exact versions of all the packages mentioned in the template etc.)." github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "Hey! Thanks for opening the issue. Can you provide more information about the issue? Please fill the issue template when opening the issue without deleting any section. We need all the information we can to be able to help.\n\nMake sure to at least provide - Current behaviour, Expected behaviour, A way to [reproduce the issue with minimal code](https://stackoverflow.com/help/minimal-reproducible-example) (link to [snack.expo.io](https://snack.expo.io)) or a repo on GitHub, and the information about your environment (such as the platform of the device, exact versions of all the packages mentioned in the template etc.)."
})
needs-repro: needs-repro:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event.label.name == 'needs repro' if: github.event.label.name == 'needs repro'
steps: steps:
- uses: actions/checkout@master - uses: actions/github-script@v2
- uses: actions/github@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: comment "Hey! Thanks for opening the issue. Can you provide a [minimal repro](https://stackoverflow.com/help/minimal-reproducible-example) which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible. The easiest way to provide a repro is on [snack.expo.io](https://snack.expo.io). If it's not possible to repro it on [snack.expo.io](https://snack.expo.io), then you can also provide the repro in a GitHub repository." github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "Hey! Thanks for opening the issue. Can you provide a [minimal repro](https://stackoverflow.com/help/minimal-reproducible-example) which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible.\n\nThe easiest way to provide a repro is on [snack.expo.io](https://snack.expo.io). If it's not possible to repro it on [snack.expo.io](https://snack.expo.io), then please provide the repro in a GitHub repository."
})
question: question:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event.label.name == 'question' if: github.event.label.name == 'question'
steps: steps:
- uses: actions/checkout@master - uses: actions/github-script@v2
- uses: actions/github@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: comment "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. This helps us prioritize fixing bugs in the library. Seems you have a usage question. Please ask the question on [StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation) instead using the `react-navigation` label. You can also chat with other community members on [Reactiflux Discord server](https://www.reactiflux.com/) in the `#react-navigation` channel." github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. This helps us prioritize fixing bugs in the library. Seems you have a usage question or an issue unrelated to this library. Please ask the question on [StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation) instead using the `react-navigation` label. You can also chat with other community members on [Reactiflux Discord server](https://www.reactiflux.com/) in the `#react-navigation` channel.\n\nIf you believe that this is actually a bug in the library, please open a new issue and fill the issue template with relevant information."
})
feature-request: feature-request:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event.label.name == 'feature-request' if: github.event.label.name == 'feature-request'
steps: steps:
- uses: actions/checkout@master - uses: actions/github-script@v2
- uses: actions/github@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: comment "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. Seems you have a feature request. Please post the feature request on [Canny](https://react-navigation.canny.io/feature-requests). This lets other users upvote your feature request and helps us prioritize the most requested features." github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. Seems you have a feature request. Please post the feature request on [Canny](https://react-navigation.canny.io/feature-requests). This lets other users upvote your feature request and helps us prioritize the most requested features.\n\nYou can also open a detailed proposal in our [RFC repo](https://github.com/react-navigation/rfcs) for discussion."
})

View File

@@ -7,19 +7,30 @@ jobs:
check-versions: check-versions:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: react-navigation/check-versions-action@master - uses: react-navigation/check-versions-action@v1.0.0
if: contains(github.event.issue.labels.*.name, 'version-4') != true
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
packages: | required-packages: |
@react-navigation/native
optional-packages: |
@react-navigation/bottom-tabs @react-navigation/bottom-tabs
@react-navigation/compat @react-navigation/compat
@react-navigation/core @react-navigation/core
@react-navigation/devtools
@react-navigation/drawer @react-navigation/drawer
@react-navigation/material-bottom-tabs @react-navigation/material-bottom-tabs
@react-navigation/material-top-tabs @react-navigation/material-top-tabs
@react-navigation/native
@react-navigation/routers @react-navigation/routers
@react-navigation/stack @react-navigation/stack
- uses: react-navigation/check-versions-action@v1.0.0
if: contains(github.event.issue.labels.*.name, 'version-4')
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
required-packages: |
react-navigation
optional-packages: |
react-navigation-animated-switch react-navigation-animated-switch
react-navigation-drawer react-navigation-drawer
react-navigation-material-bottom-tabs react-navigation-material-bottom-tabs

View File

@@ -10,9 +10,23 @@ Documentation can be found at [reactnavigation.org](https://reactnavigation.org/
If you are looking for version 4, the code can be found in the [4.x branch](https://github.com/react-navigation/react-navigation/tree/4.x). If you are looking for version 4, the code can be found in the [4.x branch](https://github.com/react-navigation/react-navigation/tree/4.x).
## Package Versions
| Name | Latest Version |
| ------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| [@react-navigation/core](/packages/core) | [![badge](https://img.shields.io/npm/v/@react-navigation/core.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/core) |
| [@react-navigation/native](/packages/native) | [![badge](https://img.shields.io/npm/v/@react-navigation/native.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/native) |
| [@react-navigation/routers](/packages/routers) | [![badge](https://img.shields.io/npm/v/@react-navigation/routers.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/routers) |
| [@react-navigation/stack](/packages/stack) | [![badge](https://img.shields.io/npm/v/@react-navigation/stack.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/stack) |
| [@react-navigation/drawer](/packages/drawer) | [![badge](https://img.shields.io/npm/v/@react-navigation/drawer.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/drawer) |
| [@react-navigation/material-top-tabs](/packages/material-top-tabs) | [![badge](https://img.shields.io/npm/v/@react-navigation/material-top-tabs.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/material-top-tabs) |
| [@react-navigation/material-bottom-tabs](/packages/material-bottom-tabs) | [![badge](https://img.shields.io/npm/v/@react-navigation/material-bottom-tabs.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/material-bottom-tabs) |
| [@react-navigation/bottom-tabs](/packages/bottom-tabs) | [![badge](https://img.shields.io/npm/v/@react-navigation/bottom-tabs.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/bottom-tabs) |
| [@react-navigation/devtools](/packages/devtools) | [![badge](https://img.shields.io/npm/v/@react-navigation/devtools.svg?style=flat-square)](https://www.npmjs.com/package/@react-navigation/devtools) |
## Contributing ## Contributing
Please read through our [contribution guide](CONTRIBUTING.md) a to get started! Please read through our [contribution guide](CONTRIBUTING.md) to get started!
## Installing from a fork on GitHub ## Installing from a fork on GitHub
@@ -49,7 +63,7 @@ Remember to replace `<user>`, `<repo>` and `<name>` with right values.
<!-- badges --> <!-- badges -->
[build-badge]: https://img.shields.io/circleci/project/github/react-navigation/react-navigation/master.svg?style=flat-square [build-badge]: https://img.shields.io/circleci/project/github/react-navigation/react-navigation/main.svg?style=flat-square
[build]: https://circleci.com/gh/react-navigation/react-navigation [build]: https://circleci.com/gh/react-navigation/react-navigation
[coverage-badge]: https://img.shields.io/codecov/c/github/react-navigation/react-navigation.svg?style=flat-square [coverage-badge]: https://img.shields.io/codecov/c/github/react-navigation/react-navigation.svg?style=flat-square
[coverage]: https://codecov.io/github/react-navigation/react-navigation [coverage]: https://codecov.io/github/react-navigation/react-navigation

View File

@@ -1,6 +1,10 @@
import 'react-native-gesture-handler'; import 'react-native-gesture-handler';
import { registerRootComponent } from 'expo'; import { registerRootComponent } from 'expo';
import { Asset } from 'expo-asset';
import { Assets as StackAssets } from '@react-navigation/stack';
import App from './src/index'; import App from './src/index';
Asset.loadAsync(StackAssets);
registerRootComponent(App); registerRootComponent(App);

41
example/CHANGELOG.md Normal file
View File

@@ -0,0 +1,41 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [5.1.0](https://github.com/react-navigation/react-navigation/compare/@react-navigation/example@5.0.0-alpha.23...@react-navigation/example@5.1.0) (2020-05-20)
### Bug Fixes
* add config to enable redux devtools integration ([c9c825b](https://github.com/react-navigation/react-navigation/commit/c9c825bee61426635a28ee149eeeff3d628171cd))
* clamp interpolated styles ([67798af](https://github.com/react-navigation/react-navigation/commit/67798af869dcbbf323629fc7e7cc9062d1e12c29))
* disable screens when mode is modal on older expo versions ([94d7b28](https://github.com/react-navigation/react-navigation/commit/94d7b28c0b2ce0d56c99b224610f305be6451626))
* dispatch pop early when screen is closed with gesture ([#336](https://github.com/react-navigation/react-navigation/issues/336)) ([3d937d1](https://github.com/react-navigation/react-navigation/commit/3d937d1e6571cd613e830d64f7b2e7426076d371)), closes [#267](https://github.com/react-navigation/react-navigation/issues/267)
* provide initial values for safe area to prevent blank screen ([#238](https://github.com/react-navigation/react-navigation/issues/238)) ([77b7570](https://github.com/react-navigation/react-navigation/commit/77b757091c0451e20bca01138629669c7da544a8))
* render fallback only if linking is enabled. closes [#8161](https://github.com/react-navigation/react-navigation/issues/8161) ([1c075ff](https://github.com/react-navigation/react-navigation/commit/1c075ffb169d233ed0515efea264a5a69b4de52e))
* return onPress instead of onClick for useLinkProps ([ae5442e](https://github.com/react-navigation/react-navigation/commit/ae5442ebe812b91fa1f12164f27d1aeed918ab0e))
* rtl in native app example ([50b366e](https://github.com/react-navigation/react-navigation/commit/50b366e7341f201d29a44f20b7771b3a832b0045))
* screens integration on Android ([#294](https://github.com/react-navigation/react-navigation/issues/294)) ([9bfb295](https://github.com/react-navigation/react-navigation/commit/9bfb29562020c61b4d5c9bee278bcb1c7bdb8b67))
* spread parent params to children in compat navigator ([24febf6](https://github.com/react-navigation/react-navigation/commit/24febf6ea99be2e5f22005fdd2a82136d647255c)), closes [#6785](https://github.com/react-navigation/react-navigation/issues/6785)
* update screens for native stack ([5411816](https://github.com/react-navigation/react-navigation/commit/54118161885738a6d20b062c7e6679f3bace8424))
* wrap navigators in gesture handler root ([41a5e1a](https://github.com/react-navigation/react-navigation/commit/41a5e1a385aa5180abc3992a4c67077c37b998b9))
### Features
* add `animationTypeForReplace` option ([#297](https://github.com/react-navigation/react-navigation/issues/297)) ([6262f72](https://github.com/react-navigation/react-navigation/commit/6262f7298bff843571fb4b1a677d3beabe29833e))
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/react-navigation/issues/308)) ([b931ae6](https://github.com/react-navigation/react-navigation/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
* add a useLinkProps hook ([f2291d1](https://github.com/react-navigation/react-navigation/commit/f2291d110faa2aa8e10c9133c1c0c28d54af7917))
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/commit/942d2be2c72720469475ce12ec8df23825994dbf))
* add custom theme support ([#211](https://github.com/react-navigation/react-navigation/issues/211)) ([00fc616](https://github.com/react-navigation/react-navigation/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
* add deeplinking to native example ([#309](https://github.com/react-navigation/react-navigation/issues/309)) ([e55e866](https://github.com/react-navigation/react-navigation/commit/e55e866af2f2163ee89bc527997cda13ffeb2abe))
* add headerStatusBarHeight option to stack ([b201fd2](https://github.com/react-navigation/react-navigation/commit/b201fd20716a2f03cb9373c72281f5d396a9356d))
* add Link component as useLinkTo hook for navigating to links ([2573b5b](https://github.com/react-navigation/react-navigation/commit/2573b5beaac1240434e52f3f57bb29da2f541c88))
* add openByDefault option to drawer ([36689e2](https://github.com/react-navigation/react-navigation/commit/36689e24c21b474692bb7ecd0b901c8afbbe9a20))
* add permanent drawer type ([#7818](https://github.com/react-navigation/react-navigation/issues/7818)) ([6a5d0a0](https://github.com/react-navigation/react-navigation/commit/6a5d0a035afae60d91aef78401ec8826295746fe))
* add preventDefault functionality in material bottom tabs ([3dede31](https://github.com/react-navigation/react-navigation/commit/3dede316ccab3b2403a475f60ce20b5c4e4cc068))
* emit appear and dismiss events for native stack ([f1df4a0](https://github.com/react-navigation/react-navigation/commit/f1df4a080877b3642e748a41a5ffc2da8c449a8c))
* initialState should take priority over deep link ([039017b](https://github.com/react-navigation/react-navigation/commit/039017bc2af69120d2d10e8f2c8a62919c37eb65))
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/react-navigation/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))

View File

@@ -7,12 +7,6 @@
"slug": "react-navigation-example", "slug": "react-navigation-example",
"description": "Demo app to showcase various functionality of React Navigation", "description": "Demo app to showcase various functionality of React Navigation",
"privacy": "public", "privacy": "public",
"sdkVersion": "37.0.0",
"platforms": [
"ios",
"android",
"web"
],
"version": "1.0.0", "version": "1.0.0",
"icon": "./assets/icon.png", "icon": "./assets/icon.png",
"splash": { "splash": {
@@ -20,15 +14,16 @@
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
}, },
"updates": { "sdkVersion": "37.0.0",
"fallbackToCacheTimeout": 0 "platforms": ["ios", "android", "web"],
},
"assetBundlePatterns": [
"**/*"
],
"ios": { "ios": {
"supportsTablet": true "supportsTablet": true
}, },
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": ["**/*"],
"scheme": "rne",
"entryPoint": "App.tsx" "entryPoint": "App.tsx"
} }
} }

View File

@@ -6,7 +6,7 @@ beforeEach(async () => {
it('loads the article page', async () => { it('loads the article page', async () => {
expect(await page.evaluate(() => location.pathname + location.search)).toBe( expect(await page.evaluate(() => location.pathname + location.search)).toBe(
'/link-component/Article?author=Gandalf' '/link-component/article/gandalf'
); );
expect( expect(
((await page.accessibility.snapshot()) as any)?.children?.find( ((await page.accessibility.snapshot()) as any)?.children?.find(
@@ -16,24 +16,24 @@ it('loads the article page', async () => {
}); });
it('goes to the album page and goes back', async () => { it('goes to the album page and goes back', async () => {
await page.click('[href="/link-component/Album"]'); await page.click('[href="/link-component/music"]');
expect(await page.evaluate(() => location.pathname + location.search)).toBe( expect(await page.evaluate(() => location.pathname + location.search)).toBe(
'/link-component/Album' '/link-component/music'
); );
expect( expect(
((await page.accessibility.snapshot()) as any)?.children?.find( ((await page.accessibility.snapshot()) as any)?.children?.find(
(it: any) => it.role === 'heading' (it: any) => it.role === 'heading'
)?.name )?.name
).toBe('Album'); ).toBe('Albums');
await page.click('[aria-label="Article by Gandalf, back"]'); await page.click('[aria-label="Article by Gandalf, back"]');
await page.waitForNavigation(); await page.waitForNavigation();
expect(await page.evaluate(() => location.pathname + location.search)).toBe( expect(await page.evaluate(() => location.pathname + location.search)).toBe(
'/link-component/Article?author=Gandalf' '/link-component/article/gandalf'
); );
expect( expect(

View File

@@ -3,10 +3,11 @@ import { page } from '../config/setup-playwright';
it('loads the example app', async () => { it('loads the example app', async () => {
const snapshot = await page.accessibility.snapshot(); const snapshot = await page.accessibility.snapshot();
// @ts-ignore expect(
expect(snapshot?.children?.find((it) => it.role === 'heading')?.name).toBe( (snapshot?.children as Record<string, unknown>[])?.find(
'Examples' (it) => it.role === 'heading'
); )?.name
).toBe('Examples');
const title = await page.$eval('[role=heading]', (el) => el.textContent); const title = await page.$eval('[role=heading]', (el) => el.textContent);
expect(title).toBe('Examples'); expect(title).toBe('Examples');

View File

@@ -0,0 +1,13 @@
import fetch from 'node-fetch';
import cheerio from 'cheerio';
const server = 'http://localhost:3275';
it('renders the home page', async () => {
const res = await fetch(server);
const html = await res.text();
const $ = cheerio.load(html);
expect($('title').text()).toBe('Examples');
});

View File

@@ -1,8 +1,16 @@
import { setup } from 'jest-dev-server'; import { setup } from 'jest-dev-server';
export default async function () { export default async function () {
await setup({ await setup([
command: 'yarn serve -l 3579 web-build', {
port: 3579, command: 'yarn serve -l 3579 web-build',
}); launchTimeout: 50000,
port: 3579,
},
{
command: 'yarn server',
launchTimeout: 50000,
port: 3275,
},
]);
} }

View File

@@ -1,35 +1,38 @@
PODS: PODS:
- boost-for-react-native (1.63.0) - boost-for-react-native (1.63.0)
- DoubleConversion (1.1.6) - DoubleConversion (1.1.6)
- EXAppLoaderProvider (8.0.0) - EXBlur (8.1.0):
- EXBlur (8.0.0):
- UMCore - UMCore
- EXConstants (8.0.0): - EXConstants (9.0.0):
- UMConstantsInterface - UMConstantsInterface
- UMCore - UMCore
- EXErrorRecovery (1.0.0): - EXErrorRecovery (1.1.0):
- UMCore - UMCore
- EXFileSystem (8.0.0): - EXFileSystem (8.1.0):
- UMCore - UMCore
- UMFileSystemInterface - UMFileSystemInterface
- EXFont (8.0.0): - EXFont (8.1.0):
- UMCore - UMCore
- UMFontInterface - UMFontInterface
- EXKeepAwake (8.0.0): - EXImageLoader (1.0.1):
- React-Core
- UMCore - UMCore
- EXLinearGradient (8.0.0): - UMImageLoaderInterface
- EXKeepAwake (8.1.0):
- UMCore - UMCore
- EXLocation (8.0.0): - EXLinearGradient (8.1.0):
- UMCore
- EXLocation (8.1.0):
- UMCore - UMCore
- UMPermissionsInterface - UMPermissionsInterface
- UMTaskManagerInterface - UMTaskManagerInterface
- EXPermissions (8.0.0): - EXPermissions (8.1.0):
- UMCore - UMCore
- UMPermissionsInterface - UMPermissionsInterface
- EXSQLite (8.0.0): - EXSQLite (8.1.0):
- UMCore - UMCore
- UMFileSystemInterface - UMFileSystemInterface
- EXWebBrowser (8.0.0): - EXWebBrowser (8.2.1):
- UMCore - UMCore
- FBLazyVector (0.61.5) - FBLazyVector (0.61.5)
- FBReactNativeSpec (0.61.5): - FBReactNativeSpec (0.61.5):
@@ -50,8 +53,6 @@ PODS:
- glog - glog
- glog (0.3.5) - glog (0.3.5)
- RCTRequired (0.61.5) - RCTRequired (0.61.5)
- RCTRestart (0.0.13):
- React
- RCTTypeSafety (0.61.5): - RCTTypeSafety (0.61.5):
- FBLazyVector (= 0.61.5) - FBLazyVector (= 0.61.5)
- Folly (= 2018.10.22.00) - Folly (= 2018.10.22.00)
@@ -214,7 +215,9 @@ PODS:
- React-cxxreact (= 0.61.5) - React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5) - React-jsi (= 0.61.5)
- React-jsinspector (0.61.5) - React-jsinspector (0.61.5)
- react-native-safe-area-context (0.6.2): - react-native-restart (0.0.15):
- React
- react-native-safe-area-context (1.0.0):
- React - React
- React-RCTActionSheet (0.61.5): - React-RCTActionSheet (0.61.5):
- React-Core/RCTActionSheetHeaders (= 0.61.5) - React-Core/RCTActionSheetHeaders (= 0.61.5)
@@ -251,39 +254,41 @@ PODS:
- React-cxxreact (= 0.61.5) - React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5) - React-jsi (= 0.61.5)
- ReactCommon/jscallinvoker (= 0.61.5) - ReactCommon/jscallinvoker (= 0.61.5)
- RNCMaskedView (0.1.5): - RNCMaskedView (0.1.10):
- React - React
- RNGestureHandler (1.5.5): - RNGestureHandler (1.6.1):
- React - React
- RNReanimated (1.4.0): - RNReanimated (1.8.0):
- React - React
- RNScreens (2.0.0-alpha.33): - RNScreens (2.7.0):
- React - React
- UMBarCodeScannerInterface (5.0.0) - UMAppLoader (1.0.2)
- UMCameraInterface (5.0.0) - UMBarCodeScannerInterface (5.1.0)
- UMConstantsInterface (5.0.0) - UMCameraInterface (5.1.0)
- UMCore (5.0.0) - UMConstantsInterface (5.1.0)
- UMFaceDetectorInterface (5.0.0) - UMCore (5.1.2)
- UMFileSystemInterface (5.0.0) - UMFaceDetectorInterface (5.1.0)
- UMFontInterface (5.0.0) - UMFileSystemInterface (5.1.0)
- UMImageLoaderInterface (5.0.0) - UMFontInterface (5.1.0)
- UMPermissionsInterface (5.0.0) - UMImageLoaderInterface (5.1.0)
- UMReactNativeAdapter (5.0.0): - UMPermissionsInterface (5.1.0):
- UMCore
- UMReactNativeAdapter (5.2.0):
- React-Core - React-Core
- UMCore - UMCore
- UMFontInterface - UMFontInterface
- UMSensorsInterface (5.0.0) - UMSensorsInterface (5.1.0)
- UMTaskManagerInterface (5.0.0) - UMTaskManagerInterface (5.1.0)
- Yoga (1.14.0) - Yoga (1.14.0)
DEPENDENCIES: DEPENDENCIES:
- DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- EXAppLoaderProvider (from `../../node_modules/expo-app-loader-provider/ios`)
- EXBlur (from `../../node_modules/expo-blur/ios`) - EXBlur (from `../../node_modules/expo-blur/ios`)
- EXConstants (from `../../node_modules/expo-constants/ios`) - EXConstants (from `../../node_modules/expo-constants/ios`)
- EXErrorRecovery (from `../../node_modules/expo-error-recovery/ios`) - EXErrorRecovery (from `../../node_modules/expo-error-recovery/ios`)
- EXFileSystem (from `../../node_modules/expo-file-system/ios`) - EXFileSystem (from `../../node_modules/expo-file-system/ios`)
- EXFont (from `../../node_modules/expo-font/ios`) - EXFont (from `../../node_modules/expo-font/ios`)
- EXImageLoader (from `../../node_modules/expo-image-loader/ios`)
- EXKeepAwake (from `../../node_modules/expo-keep-awake/ios`) - EXKeepAwake (from `../../node_modules/expo-keep-awake/ios`)
- EXLinearGradient (from `../../node_modules/expo-linear-gradient/ios`) - EXLinearGradient (from `../../node_modules/expo-linear-gradient/ios`)
- EXLocation (from `../../node_modules/expo-location/ios`) - EXLocation (from `../../node_modules/expo-location/ios`)
@@ -295,7 +300,6 @@ DEPENDENCIES:
- Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`) - Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`) - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
- RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`) - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
- RCTRestart (from `../../node_modules/react-native-restart/ios`)
- RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`) - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../../node_modules/react-native/`) - React (from `../../node_modules/react-native/`)
- React-Core (from `../../node_modules/react-native/`) - React-Core (from `../../node_modules/react-native/`)
@@ -306,6 +310,7 @@ DEPENDENCIES:
- React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`) - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`) - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-restart (from `../../node_modules/react-native-restart`)
- react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`) - react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
- React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`) - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
- React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`) - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
@@ -322,10 +327,11 @@ DEPENDENCIES:
- RNGestureHandler (from `../../node_modules/react-native-gesture-handler`) - RNGestureHandler (from `../../node_modules/react-native-gesture-handler`)
- RNReanimated (from `../../node_modules/react-native-reanimated`) - RNReanimated (from `../../node_modules/react-native-reanimated`)
- RNScreens (from `../../node_modules/react-native-screens`) - RNScreens (from `../../node_modules/react-native-screens`)
- UMAppLoader (from `../../node_modules/unimodules-app-loader/ios`)
- UMBarCodeScannerInterface (from `../../node_modules/unimodules-barcode-scanner-interface/ios`) - UMBarCodeScannerInterface (from `../../node_modules/unimodules-barcode-scanner-interface/ios`)
- UMCameraInterface (from `../../node_modules/unimodules-camera-interface/ios`) - UMCameraInterface (from `../../node_modules/unimodules-camera-interface/ios`)
- UMConstantsInterface (from `../../node_modules/unimodules-constants-interface/ios`) - UMConstantsInterface (from `../../node_modules/unimodules-constants-interface/ios`)
- "UMCore (from `../../node_modules/@unimodules/core/ios`)" - "UMCore (from `../../node_modules/react-native-unimodules/node_modules/@unimodules/core/ios`)"
- UMFaceDetectorInterface (from `../../node_modules/unimodules-face-detector-interface/ios`) - UMFaceDetectorInterface (from `../../node_modules/unimodules-face-detector-interface/ios`)
- UMFileSystemInterface (from `../../node_modules/unimodules-file-system-interface/ios`) - UMFileSystemInterface (from `../../node_modules/unimodules-file-system-interface/ios`)
- UMFontInterface (from `../../node_modules/unimodules-font-interface/ios`) - UMFontInterface (from `../../node_modules/unimodules-font-interface/ios`)
@@ -343,42 +349,30 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
DoubleConversion: DoubleConversion:
:podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" :podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
EXAppLoaderProvider:
:path: !ruby/object:Pathname
path: "../../node_modules/expo-app-loader-provider/ios"
EXBlur: EXBlur:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-blur/ios"
path: "../../node_modules/expo-blur/ios"
EXConstants: EXConstants:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-constants/ios"
path: "../../node_modules/expo-constants/ios"
EXErrorRecovery: EXErrorRecovery:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-error-recovery/ios"
path: "../../node_modules/expo-error-recovery/ios"
EXFileSystem: EXFileSystem:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-file-system/ios"
path: "../../node_modules/expo-file-system/ios"
EXFont: EXFont:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-font/ios"
path: "../../node_modules/expo-font/ios" EXImageLoader:
:path: "../../node_modules/expo-image-loader/ios"
EXKeepAwake: EXKeepAwake:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-keep-awake/ios"
path: "../../node_modules/expo-keep-awake/ios"
EXLinearGradient: EXLinearGradient:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-linear-gradient/ios"
path: "../../node_modules/expo-linear-gradient/ios"
EXLocation: EXLocation:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-location/ios"
path: "../../node_modules/expo-location/ios"
EXPermissions: EXPermissions:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-permissions/ios"
path: "../../node_modules/expo-permissions/ios"
EXSQLite: EXSQLite:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-sqlite/ios"
path: "../../node_modules/expo-sqlite/ios"
EXWebBrowser: EXWebBrowser:
:path: !ruby/object:Pathname :path: "../../node_modules/expo-web-browser/ios"
path: "../../node_modules/expo-web-browser/ios"
FBLazyVector: FBLazyVector:
:path: "../../node_modules/react-native/Libraries/FBLazyVector" :path: "../../node_modules/react-native/Libraries/FBLazyVector"
FBReactNativeSpec: FBReactNativeSpec:
@@ -389,8 +383,6 @@ EXTERNAL SOURCES:
:podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec" :podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
RCTRequired: RCTRequired:
:path: "../../node_modules/react-native/Libraries/RCTRequired" :path: "../../node_modules/react-native/Libraries/RCTRequired"
RCTRestart:
:path: "../../node_modules/react-native-restart/ios"
RCTTypeSafety: RCTTypeSafety:
:path: "../../node_modules/react-native/Libraries/TypeSafety" :path: "../../node_modules/react-native/Libraries/TypeSafety"
React: React:
@@ -407,6 +399,8 @@ EXTERNAL SOURCES:
:path: "../../node_modules/react-native/ReactCommon/jsiexecutor" :path: "../../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector: React-jsinspector:
:path: "../../node_modules/react-native/ReactCommon/jsinspector" :path: "../../node_modules/react-native/ReactCommon/jsinspector"
react-native-restart:
:path: "../../node_modules/react-native-restart"
react-native-safe-area-context: react-native-safe-area-context:
:path: "../../node_modules/react-native-safe-area-context" :path: "../../node_modules/react-native-safe-area-context"
React-RCTActionSheet: React-RCTActionSheet:
@@ -437,66 +431,55 @@ EXTERNAL SOURCES:
:path: "../../node_modules/react-native-reanimated" :path: "../../node_modules/react-native-reanimated"
RNScreens: RNScreens:
:path: "../../node_modules/react-native-screens" :path: "../../node_modules/react-native-screens"
UMAppLoader:
:path: "../../node_modules/unimodules-app-loader/ios"
UMBarCodeScannerInterface: UMBarCodeScannerInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-barcode-scanner-interface/ios"
path: "../../node_modules/unimodules-barcode-scanner-interface/ios"
UMCameraInterface: UMCameraInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-camera-interface/ios"
path: "../../node_modules/unimodules-camera-interface/ios"
UMConstantsInterface: UMConstantsInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-constants-interface/ios"
path: "../../node_modules/unimodules-constants-interface/ios"
UMCore: UMCore:
:path: !ruby/object:Pathname :path: "../../node_modules/react-native-unimodules/node_modules/@unimodules/core/ios"
path: "../../node_modules/@unimodules/core/ios"
UMFaceDetectorInterface: UMFaceDetectorInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-face-detector-interface/ios"
path: "../../node_modules/unimodules-face-detector-interface/ios"
UMFileSystemInterface: UMFileSystemInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-file-system-interface/ios"
path: "../../node_modules/unimodules-file-system-interface/ios"
UMFontInterface: UMFontInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-font-interface/ios"
path: "../../node_modules/unimodules-font-interface/ios"
UMImageLoaderInterface: UMImageLoaderInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-image-loader-interface/ios"
path: "../../node_modules/unimodules-image-loader-interface/ios"
UMPermissionsInterface: UMPermissionsInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-permissions-interface/ios"
path: "../../node_modules/unimodules-permissions-interface/ios"
UMReactNativeAdapter: UMReactNativeAdapter:
:path: !ruby/object:Pathname :path: "../../node_modules/@unimodules/react-native-adapter/ios"
path: "../../node_modules/@unimodules/react-native-adapter/ios"
UMSensorsInterface: UMSensorsInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-sensors-interface/ios"
path: "../../node_modules/unimodules-sensors-interface/ios"
UMTaskManagerInterface: UMTaskManagerInterface:
:path: !ruby/object:Pathname :path: "../../node_modules/unimodules-task-manager-interface/ios"
path: "../../node_modules/unimodules-task-manager-interface/ios"
Yoga: Yoga:
:path: "../../node_modules/react-native/ReactCommon/yoga" :path: "../../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS: SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2 DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
EXAppLoaderProvider: ebdb6bc2632c1ccadbe49f5e4104d8d690969c49 EXBlur: aa14d84bff6e9c2232fbcaf54ad809eee1cc41dc
EXBlur: d1604f66f89a9414f5ee65dfb23874437c1bb147 EXConstants: 5304709b1bea70a4828f48ba4c7fc3ec3b2d9b17
EXConstants: 4051b16c17ef3defa03c541d42811dc92b249146 EXErrorRecovery: 8f4c21ab2f51bf75defe4536f841a37de59b0661
EXErrorRecovery: d36db99ec6a3808f313f01b0890eb443796dd1c2 EXFileSystem: cf4232ba7c62dc49b78c2d36005f97b6fddf0b01
EXFileSystem: 6e0d9bb6cc4ea404dbb8f583c1a8a2dcdf4b83b6 EXFont: 8326ecf966be559f7ced7c8e221a32fc4d9ed8b0
EXFont: 6187b5ab46ee578d5f8e7f2ea092752e78772235 EXImageLoader: 5ad6896fa1ef2ee814b551873cbf7a7baccc694a
EXKeepAwake: 66e9f80b6d129633725a0e42f8d285c229876811 EXKeepAwake: d045bc2cf1ad5a04f0323cc7c894b95b414042e0
EXLinearGradient: 75f302f9d6484267a3f6d3252df2e7a5f00e716a EXLinearGradient: 97d8095d1e4ad96f7893e010e564796ed8aeea42
EXLocation: 3c75d012ca92eed94d4338778d79c49d1252393a EXLocation: bbd487fd96a18a3ad9725389bbb94c4a5f78edf3
EXPermissions: 9bc08859a675d291e89be9a0870155c27c16ac35 EXPermissions: 24b97f734ce9172d245a5be38ad9ccfcb6135964
EXSQLite: 220226a354912b100dfe913f5fe6f31762c8927e EXSQLite: 877ad6c8eb169353a2f94d5ad26510ffadd46a1f
EXWebBrowser: db32607359fb7b55b7b7b91df32dd3d8355bb3b7 EXWebBrowser: 5902f99ac5ac551e5c82ff46f13a337b323aa9ea
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75 FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51 Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28 glog: 1f3da668190260b06b429bb211bfbee5cd790c28
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1 RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
RCTRestart: dd19aab87fc1118e05b6b5b91b959105647f56b4
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320 RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78 React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04 React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
@@ -505,7 +488,8 @@ SPEC CHECKSUMS:
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7 React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386 React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0 React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
react-native-safe-area-context: 25260c5d0b9c53fd7aa88e569e2edae72af1f6a3 react-native-restart: fff228304625f55de2ebd4de43938110f4c888ed
react-native-safe-area-context: a346c75f2288147527365ce27b59ca6d38c27805
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76 React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360 React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72 React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
@@ -516,24 +500,25 @@ SPEC CHECKSUMS:
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
RNCMaskedView: dd13f9f7b146a9ad82f9b7eb6c9b5548fcf6e990 RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
RNGestureHandler: d2270608171c868581b840cfc692f2962c05cd17 RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNReanimated: b2ab0b693dddd2339bd2f300e770f6302d2e960c RNReanimated: 955cf4068714003d2f1a6e2bae3fb1118f359aff
RNScreens: 1c7fd499b915c77c21e8e6c327890c5af9b4cf7e RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
UMBarCodeScannerInterface: 3802c8574ef119c150701d679ab386e2266d6a54 UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6
UMCameraInterface: 985d301f688ed392f815728f0dd906ca34b7ccb1 UMBarCodeScannerInterface: 9dc692b87e5f20fe277fa57aa47f45d418c3cc6c
UMConstantsInterface: bda5f8bd3403ad99e663eb3c4da685d063c5653c UMCameraInterface: 625878bbf2ba188a8548675e1d1d2e438a653e6d
UMCore: 7ab08669a8bb2e61f557c1fe9784521cb5aa28e3 UMConstantsInterface: 64060cf86587bcd90b1dbd804cceb6d377a308c1
UMFaceDetectorInterface: ce14e8e597f6a52aa66e4ab956cb5bff4fa8acf8 UMCore: eb200e882eadafcd31ead290770835fd648c0945
UMFileSystemInterface: 2ed004c9620f43f0b36b33c42ce668500850d6a4 UMFaceDetectorInterface: d6677d6ddc9ab95a0ca857aa7f8ba76656cc770f
UMFontInterface: 24fbc0a02ade6c60ad3ee3e2b5d597c8dcfc3208 UMFileSystemInterface: c70ea7147198b9807080f3597f26236be49b0165
UMImageLoaderInterface: 3976a14c588341228881ff75970fbabf122efca4 UMFontInterface: d9d3b27af698c5389ae9e20b99ef56a083f491fb
UMPermissionsInterface: 2abf9f7f4aa7110e27beaf634a7deda2d50ff3d7 UMImageLoaderInterface: 14dd2c46c67167491effc9e91250e9510f12709e
UMReactNativeAdapter: 230406e3335a8dbd4c9c0e654488a1cf3b44552f UMPermissionsInterface: 5e83a9167c177e4a0f0a3539345983cc749efb3e
UMSensorsInterface: d708a892ef1500bdd9fc3ff03f7836c66d1634d3 UMReactNativeAdapter: 126da3486c1a1f11945b649d557d6c2ebb9407b2
UMTaskManagerInterface: a98e37a576a5220bf43b8faf33cfdc129d2f441d UMSensorsInterface: 48941f70175e2975af1a9386c6d6cb16d8126805
UMTaskManagerInterface: cb890c79c63885504ddc0efd7a7d01481760aca2
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
PODFILE CHECKSUM: c48a21ff513d3eadafa50f8797207ef2be75e234 PODFILE CHECKSUM: c48a21ff513d3eadafa50f8797207ef2be75e234
COCOAPODS: 1.8.4 COCOAPODS: 1.9.1

View File

@@ -8,26 +8,25 @@ const blacklist = require('metro-config/src/defaults/blacklist');
const root = path.resolve(__dirname, '..'); const root = path.resolve(__dirname, '..');
const packages = path.resolve(root, 'packages'); const packages = path.resolve(root, 'packages');
const workspaces = fs
// List all packages under `packages/`
.readdirSync(packages)
// Ignore hidden files such as .DS_Store
.filter((p) => !p.startsWith('.'))
.map((p) => path.join(packages, p));
// Get the list of dependencies for all packages in the monorepo // Get the list of dependencies for all packages in the monorepo
const modules = ['@expo/vector-icons'] const modules = ['@expo/vector-icons']
.concat( .concat(
...fs ...workspaces.map((it) => {
// List all packages under `packages/` const pak = JSON.parse(
.readdirSync(packages) fs.readFileSync(path.join(it, 'package.json'), 'utf8')
// Ignore hidden files such as .DS_Store );
.filter((p) => !p.startsWith('.'))
.map((p) => {
const pak = JSON.parse(
fs.readFileSync(path.join(packages, p, 'package.json'), 'utf8')
);
// We need to collect list of deps that this package imports // We need to make sure that only one version is loaded for peerDependencies
// Collecting both dependencies are peerDependencies should do it // So we blacklist them at the root, and alias them to the versions in example's node_modules
return Object.keys({ return pak.peerDependencies ? Object.keys(pak.peerDependencies) : [];
...pak.dependencies, })
...pak.peerDependencies,
});
})
) )
.sort() .sort()
.filter( .filter(
@@ -45,15 +44,16 @@ module.exports = {
watchFolders: [root], watchFolders: [root],
resolver: { resolver: {
// We need to blacklist `node_modules` of all our packages // We need to blacklist the peerDependencies we've collected in packages' node_modules
// This will avoid Metro throwing duplicate module errors
blacklistRE: blacklist( blacklistRE: blacklist(
fs [].concat(
.readdirSync(packages) ...workspaces.map((it) =>
.map((p) => path.join(packages, p)) modules.map(
.map( (m) =>
(it) => new RegExp(`^${escape(path.join(it, 'node_modules'))}\\/.*$`) new RegExp(`^${escape(path.join(it, 'node_modules', m))}\\/.*$`)
)
) )
)
), ),
// When we import a package from the monorepo, metro won't be able to find their deps // When we import a package from the monorepo, metro won't be able to find their deps

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/example", "name": "@react-navigation/example",
"description": "Demo app to showcase various functionality of React Navigation", "description": "Demo app to showcase various functionality of React Navigation",
"version": "5.0.0", "version": "5.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "expo start", "start": "expo start",
@@ -9,39 +9,52 @@
"native": "react-native start", "native": "react-native start",
"android": "react-native run-android", "android": "react-native run-android",
"ios": "react-native run-ios", "ios": "react-native run-ios",
"server": "nodemon -e '.js,.ts,.tsx' --exec \"babel-node -i '/node_modules[/\\](?react-native)/' -x '.web.tsx,.web.ts,.web.js,.tsx,.ts,.js' --config-file ./server/babel.config.js server\"",
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"@expo/vector-icons": "^10.0.0", "@expo/vector-icons": "^10.2.0",
"@react-native-community/masked-view": "^0.1.7", "@react-native-community/masked-view": "^0.1.10",
"color": "^3.1.2", "color": "^3.1.2",
"expo": "^37.0.0", "expo": "^37.0.12",
"expo-asset": "~8.1.3", "expo-asset": "~8.1.5",
"expo-blur": "~8.1.0", "expo-blur": "~8.1.0",
"koa": "^2.12.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-dom": "~16.9.0", "react-dom": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-gesture-handler": "^1.6.0", "react-native-gesture-handler": "^1.6.0",
"react-native-paper": "^3.7.0", "react-native-paper": "^3.10.1",
"react-native-reanimated": "^1.7.0", "react-native-reanimated": "^1.8.0",
"react-native-restart": "^0.0.14", "react-native-restart": "^0.0.15",
"react-native-safe-area-context": "^0.7.3", "react-native-safe-area-context": "^1.0.0",
"react-native-screens": "^2.3.0", "react-native-screens": "^2.7.0",
"react-native-tab-view": "2.14.0", "react-native-tab-view": "2.14.4",
"react-native-unimodules": "~0.8.1", "react-native-unimodules": "~0.9.1",
"react-native-vector-icons": "^6.6.0",
"react-native-web": "^0.11.7" "react-native-web": "^0.11.7"
}, },
"devDependencies": { "devDependencies": {
"@expo/webpack-config": "^0.11.19", "@babel/node": "^7.10.1",
"@expo/webpack-config": "^0.12.12",
"@types/cheerio": "^0.22.18",
"@types/jest-dev-server": "^4.2.0", "@types/jest-dev-server": "^4.2.0",
"@types/react": "^16.9.23", "@types/koa": "^2.11.3",
"@types/react-native": "^0.60.22", "@types/node-fetch": "^2.5.7",
"babel-preset-expo": "^8.1.0", "@types/react": "^16.9.36",
"expo-cli": "^3.17.18", "@types/react-dom": "^16.9.8",
"jest": "^25.2.7", "@types/react-native": "^0.62.7",
"babel-plugin-module-resolver": "^4.0.0",
"babel-preset-expo": "^8.2.1",
"cheerio": "^1.0.0-rc.3",
"expo-cli": "^3.21.5",
"jest": "^26.0.1",
"jest-dev-server": "^4.4.0", "jest-dev-server": "^4.4.0",
"mock-require-assets": "^0.0.1",
"node-fetch": "^2.6.0",
"nodemon": "^2.0.4",
"playwright": "^0.14.0", "playwright": "^0.14.0",
"serve": "^11.3.0", "serve": "^11.3.2",
"typescript": "^3.8.3" "typescript": "^3.9.5"
} }
} }

View File

@@ -0,0 +1,40 @@
const path = require('path');
const fs = require('fs');
const packages = path.resolve(__dirname, '..', '..', 'packages');
const alias = Object.fromEntries(
fs
.readdirSync(packages)
.filter((name) => !name.startsWith('.'))
.map((name) => [
`@react-navigation/${name}`,
path.resolve(
packages,
name,
require(`../../packages/${name}/package.json`).source
),
])
);
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-flow',
'@babel/preset-typescript',
'@babel/preset-react',
],
plugins: [
'@babel/plugin-proposal-class-properties',
[
'module-resolver',
{
root: ['..'],
alias: {
'react-native': 'react-native-web',
...alias,
},
},
],
],
};

54
example/server/index.tsx Normal file
View File

@@ -0,0 +1,54 @@
import './resolve-hooks';
import Koa from 'koa';
import * as React from 'react';
import ReactDOMServer from 'react-dom/server';
import { AppRegistry } from 'react-native-web';
import { ServerContainer, ServerContainerRef } from '@react-navigation/native';
import App from '../src/index';
AppRegistry.registerComponent('App', () => App);
const PORT = process.env.PORT || 3275;
const app = new Koa();
app.use(async (ctx) => {
const { element, getStyleElement } = AppRegistry.getApplication('App');
const ref = React.createRef<ServerContainerRef>();
const html = ReactDOMServer.renderToString(
<ServerContainer
ref={ref}
location={{ pathname: ctx.path, search: ctx.search }}
>
{element}
</ServerContainer>
);
const css = ReactDOMServer.renderToStaticMarkup(getStyleElement());
const document = `
<!DOCTYPE html>
<html style="height: 100%">
<meta charset="utf-8">
<meta httpEquiv="X-UA-Compatible" content="IE=edge">
<meta
name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover"
>
${css}
<title>${ref.current?.getCurrentOptions()?.title}</title>
<body style="min-height: 100%">
<div id="root" style="display: flex; min-height: 100vh">
${html}
</div>
`;
ctx.body = document;
});
app.listen(PORT, () => {
console.log(`Running at http://localhost:${PORT}`);
});

View File

@@ -0,0 +1,12 @@
import 'mock-require-assets';
import Module from 'module';
// We need to make sure that .web.xx extensions are resolved before .xx
// @ts-expect-error: _extensions doesn't exist in the type definitions
Module._extensions = Object.fromEntries(
// @ts-expect-error
Object.entries(Module._extensions).sort((a, b) => {
return b[0].split('.').length - a[0].split('.').length;
})
);

View File

@@ -0,0 +1,11 @@
import { Updates } from 'expo';
import RNRestart from 'react-native-restart';
export function restartApp() {
// @ts-expect-error: Expo doesn't exist in global definitions
if (global.Expo) {
Updates.reloadFromCache();
} else {
RNRestart.Restart();
}
}

1
example/src/Restart.tsx Normal file
View File

@@ -0,0 +1 @@
export function restartApp() {}

View File

@@ -1,7 +1,16 @@
import * as React from 'react'; import * as React from 'react';
import { Platform } from 'react-native'; import { View, ScrollView, StyleSheet, Platform } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons'; import { Button } from 'react-native-paper';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import {
getFocusedRouteNameFromRoute,
ParamListBase,
} from '@react-navigation/native';
import type { StackScreenProps } from '@react-navigation/stack';
import {
createBottomTabNavigator,
BottomTabNavigationProp,
} from '@react-navigation/bottom-tabs';
import TouchableBounce from '../Shared/TouchableBounce'; import TouchableBounce from '../Shared/TouchableBounce';
import Albums from '../Shared/Albums'; import Albums from '../Shared/Albums';
import Contacts from '../Shared/Contacts'; import Contacts from '../Shared/Contacts';
@@ -23,9 +32,50 @@ type BottomTabParams = {
Chat: undefined; Chat: undefined;
}; };
const scrollEnabled = Platform.select({ web: true, default: false });
const AlbumsScreen = ({
navigation,
}: {
navigation: BottomTabNavigationProp<BottomTabParams>;
}) => {
return (
<ScrollView>
<View style={styles.buttons}>
<Button
mode="outlined"
onPress={() => navigation.setOptions({ tabBarVisible: false })}
style={styles.button}
>
Hide tab bar
</Button>
<Button
mode="outlined"
onPress={() => navigation.setOptions({ tabBarVisible: true })}
style={styles.button}
>
Show tab bar
</Button>
</View>
<Albums scrollEnabled={scrollEnabled} />
</ScrollView>
);
};
const BottomTabs = createBottomTabNavigator<BottomTabParams>(); const BottomTabs = createBottomTabNavigator<BottomTabParams>();
export default function BottomTabsScreen() { export default function BottomTabsScreen({
navigation,
route,
}: StackScreenProps<ParamListBase, string>) {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Article';
React.useLayoutEffect(() => {
navigation.setOptions({
title: routeName,
});
}, [navigation, routeName]);
return ( return (
<BottomTabs.Navigator <BottomTabs.Navigator
screenOptions={{ screenOptions={{
@@ -37,13 +87,12 @@ export default function BottomTabsScreen() {
> >
<BottomTabs.Screen <BottomTabs.Screen
name="Article" name="Article"
component={SimpleStackScreen}
options={{ options={{
title: 'Article', title: 'Article',
tabBarIcon: getTabBarIcon('file-document-box'), tabBarIcon: getTabBarIcon('file-document-box'),
}} }}
> />
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
</BottomTabs.Screen>
<BottomTabs.Screen <BottomTabs.Screen
name="Chat" name="Chat"
component={Chat} component={Chat}
@@ -62,7 +111,7 @@ export default function BottomTabsScreen() {
/> />
<BottomTabs.Screen <BottomTabs.Screen
name="Albums" name="Albums"
component={Albums} component={AlbumsScreen}
options={{ options={{
title: 'Albums', title: 'Albums',
tabBarIcon: getTabBarIcon('image-album'), tabBarIcon: getTabBarIcon('image-album'),
@@ -71,3 +120,13 @@ export default function BottomTabsScreen() {
</BottomTabs.Navigator> </BottomTabs.Navigator>
); );
} }
const styles = StyleSheet.create({
buttons: {
flexDirection: 'row',
padding: 8,
},
button: {
margin: 8,
},
});

View File

@@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { View, StyleSheet } from 'react-native'; import { View, StyleSheet } from 'react-native';
import { Title, Button } from 'react-native-paper'; import { Title, Button } from 'react-native-paper';
import { Feather } from '@expo/vector-icons'; import Feather from 'react-native-vector-icons/Feather';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
type BottomTabParams = { type BottomTabParams = {

View File

@@ -17,7 +17,7 @@ import Albums from '../Shared/Albums';
type SimpleStackParams = { type SimpleStackParams = {
Article: { author: string }; Article: { author: string };
Album: undefined; Albums: undefined;
}; };
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>; type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
@@ -53,24 +53,24 @@ const ArticleScreen = ({
<ScrollView> <ScrollView>
<View style={styles.buttons}> <View style={styles.buttons}>
<Link <Link
to="/link-component/Album" to="/link-component/music"
style={[styles.button, { padding: 8 }]} style={[styles.button, { padding: 8 }]}
> >
Go to /link-component/Album Go to /link-component/music
</Link> </Link>
<Link <Link
to="/link-component/Album" to="/link-component/music"
action={StackActions.replace('Album')} action={StackActions.replace('Albums')}
style={[styles.button, { padding: 8 }]} style={[styles.button, { padding: 8 }]}
> >
Replace with /link-component/Album Replace with /link-component/music
</Link> </Link>
<LinkButton <LinkButton
to="/link-component/Album" to="/link-component/music"
mode="contained" mode="contained"
style={styles.button} style={styles.button}
> >
Go to /link-component/Album Go to /link-component/music
</LinkButton> </LinkButton>
<Button <Button
mode="outlined" mode="outlined"
@@ -97,17 +97,17 @@ const AlbumsScreen = ({
<ScrollView> <ScrollView>
<View style={styles.buttons}> <View style={styles.buttons}>
<Link <Link
to="/link-component/Article?author=Babel" to="/link-component/article/babel"
style={[styles.button, { padding: 8 }]} style={[styles.button, { padding: 8 }]}
> >
Go to /link-component/Article Go to /link-component/article
</Link> </Link>
<LinkButton <LinkButton
to="/link-component/Article?author=Babel" to="/link-component/article/babel"
mode="contained" mode="contained"
style={styles.button} style={styles.button}
> >
Go to /link-component/Article Go to /link-component/article
</LinkButton> </LinkButton>
<Button <Button
mode="outlined" mode="outlined"
@@ -144,9 +144,9 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
initialParams={{ author: 'Gandalf' }} initialParams={{ author: 'Gandalf' }}
/> />
<SimpleStack.Screen <SimpleStack.Screen
name="Album" name="Albums"
component={AlbumsScreen} component={AlbumsScreen}
options={{ title: 'Album' }} options={{ title: 'Albums' }}
/> />
</SimpleStack.Navigator> </SimpleStack.Navigator>
); );

View File

@@ -1,13 +1,19 @@
import * as React from 'react'; import * as React from 'react';
import { Dimensions, ScaledSize } from 'react-native'; import { Dimensions, ScaledSize } from 'react-native';
import { Appbar } from 'react-native-paper'; import { Appbar } from 'react-native-paper';
import { ParamListBase } from '@react-navigation/native'; import {
import { StackNavigationProp } from '@react-navigation/stack'; useTheme,
useNavigation,
ParamListBase,
} from '@react-navigation/native';
import { import {
createDrawerNavigator, createDrawerNavigator,
DrawerNavigationProp, DrawerNavigationProp,
DrawerContent, DrawerContent,
DrawerContentComponentProps,
DrawerContentOptions,
} from '@react-navigation/drawer'; } from '@react-navigation/drawer';
import type { StackNavigationProp } from '@react-navigation/stack';
import Article from '../Shared/Article'; import Article from '../Shared/Article';
import Albums from '../Shared/Albums'; import Albums from '../Shared/Albums';
import NewsFeed from '../Shared/NewsFeed'; import NewsFeed from '../Shared/NewsFeed';
@@ -15,7 +21,7 @@ import NewsFeed from '../Shared/NewsFeed';
type DrawerParams = { type DrawerParams = {
Article: undefined; Article: undefined;
NewsFeed: undefined; NewsFeed: undefined;
Album: undefined; Albums: undefined;
}; };
type DrawerNavigation = DrawerNavigationProp<DrawerParams>; type DrawerNavigation = DrawerNavigationProp<DrawerParams>;
@@ -43,10 +49,11 @@ const Header = ({
onGoBack: () => void; onGoBack: () => void;
title: string; title: string;
}) => { }) => {
const { colors } = useTheme();
const isLargeScreen = useIsLargeScreen(); const isLargeScreen = useIsLargeScreen();
return ( return (
<Appbar.Header> <Appbar.Header style={{ backgroundColor: colors.card, elevation: 1 }}>
{isLargeScreen ? null : <Appbar.BackAction onPress={onGoBack} />} {isLargeScreen ? null : <Appbar.BackAction onPress={onGoBack} />}
<Appbar.Content title={title} /> <Appbar.Content title={title} />
</Appbar.Header> </Appbar.Header>
@@ -80,6 +87,23 @@ const AlbumsScreen = ({ navigation }: { navigation: DrawerNavigation }) => {
); );
}; };
const CustomDrawerContent = (
props: DrawerContentComponentProps<DrawerContentOptions>
) => {
const { colors } = useTheme();
const navigation = useNavigation();
return (
<>
<Appbar.Header style={{ backgroundColor: colors.card, elevation: 1 }}>
<Appbar.Action icon="close" onPress={() => navigation.goBack()} />
<Appbar.Content title="Pages" />
</Appbar.Header>
<DrawerContent {...props} />
</>
);
};
const Drawer = createDrawerNavigator<DrawerParams>(); const Drawer = createDrawerNavigator<DrawerParams>();
type Props = Partial<React.ComponentProps<typeof Drawer.Navigator>> & { type Props = Partial<React.ComponentProps<typeof Drawer.Navigator>> & {
@@ -100,15 +124,7 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {
drawerType={isLargeScreen ? 'permanent' : 'back'} drawerType={isLargeScreen ? 'permanent' : 'back'}
drawerStyle={isLargeScreen ? null : { width: '100%' }} drawerStyle={isLargeScreen ? null : { width: '100%' }}
overlayColor="transparent" overlayColor="transparent"
drawerContent={(props) => ( drawerContent={(props) => <CustomDrawerContent {...props} />}
<>
<Appbar.Header>
<Appbar.Action icon="close" onPress={() => navigation.goBack()} />
<Appbar.Content title="Pages" />
</Appbar.Header>
<DrawerContent {...props} />
</>
)}
{...rest} {...rest}
> >
<Drawer.Screen name="Article" component={ArticleScreen} /> <Drawer.Screen name="Article" component={ArticleScreen} />
@@ -118,9 +134,9 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {
options={{ title: 'Feed' }} options={{ title: 'Feed' }}
/> />
<Drawer.Screen <Drawer.Screen
name="Album" name="Albums"
component={AlbumsScreen} component={AlbumsScreen}
options={{ title: 'Album' }} options={{ title: 'Albums' }}
/> />
</Drawer.Navigator> </Drawer.Navigator>
); );

View File

@@ -22,14 +22,13 @@ export default function MaterialBottomTabsScreen() {
<MaterialBottomTabs.Navigator barStyle={styles.tabBar}> <MaterialBottomTabs.Navigator barStyle={styles.tabBar}>
<MaterialBottomTabs.Screen <MaterialBottomTabs.Screen
name="Article" name="Article"
component={SimpleStackScreen}
options={{ options={{
tabBarLabel: 'Article', tabBarLabel: 'Article',
tabBarIcon: 'file-document-box', tabBarIcon: 'file-document-box',
tabBarColor: '#C9E7F8', tabBarColor: '#C9E7F8',
}} }}
> />
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
</MaterialBottomTabs.Screen>
<MaterialBottomTabs.Screen <MaterialBottomTabs.Screen
name="Chat" name="Chat"
component={Chat} component={Chat}

View File

@@ -1,4 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import type { ParamListBase } from '@react-navigation/native';
import type { StackNavigationProp } from '@react-navigation/stack';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'; import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import Albums from '../Shared/Albums'; import Albums from '../Shared/Albums';
import Contacts from '../Shared/Contacts'; import Contacts from '../Shared/Contacts';
@@ -12,7 +14,15 @@ type MaterialTopTabParams = {
const MaterialTopTabs = createMaterialTopTabNavigator<MaterialTopTabParams>(); const MaterialTopTabs = createMaterialTopTabNavigator<MaterialTopTabParams>();
export default function MaterialTopTabsScreen() { type Props = {
navigation: StackNavigationProp<ParamListBase>;
};
export default function MaterialTopTabsScreen({ navigation }: Props) {
navigation.setOptions({
cardStyle: { flex: 1 },
});
return ( return (
<MaterialTopTabs.Navigator> <MaterialTopTabs.Navigator>
<MaterialTopTabs.Screen <MaterialTopTabs.Screen

View File

@@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { View, StyleSheet, ScrollView, Platform } from 'react-native'; import { View, StyleSheet, ScrollView, Platform } from 'react-native';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { RouteProp, ParamListBase } from '@react-navigation/native'; import type { RouteProp, ParamListBase } from '@react-navigation/native';
import { import {
createStackNavigator, createStackNavigator,
StackNavigationProp, StackNavigationProp,
@@ -12,7 +12,7 @@ import Albums from '../Shared/Albums';
type ModalStackParams = { type ModalStackParams = {
Article: { author: string }; Article: { author: string };
Album: undefined; Albums: undefined;
}; };
type ModalStackNavigation = StackNavigationProp<ModalStackParams>; type ModalStackNavigation = StackNavigationProp<ModalStackParams>;
@@ -31,7 +31,7 @@ const ArticleScreen = ({
<View style={styles.buttons}> <View style={styles.buttons}>
<Button <Button
mode="contained" mode="contained"
onPress={() => navigation.push('Album')} onPress={() => navigation.push('Albums')}
style={styles.button} style={styles.button}
> >
Push album Push album
@@ -91,7 +91,6 @@ export default function SimpleStackScreen({ navigation, options }: Props) {
return ( return (
<ModalPresentationStack.Navigator <ModalPresentationStack.Navigator
mode="modal" mode="modal"
headerMode="screen"
screenOptions={({ route, navigation }) => ({ screenOptions={({ route, navigation }) => ({
...TransitionPresets.ModalPresentationIOS, ...TransitionPresets.ModalPresentationIOS,
cardOverlayEnabled: true, cardOverlayEnabled: true,
@@ -112,9 +111,9 @@ export default function SimpleStackScreen({ navigation, options }: Props) {
initialParams={{ author: 'Gandalf' }} initialParams={{ author: 'Gandalf' }}
/> />
<ModalPresentationStack.Screen <ModalPresentationStack.Screen
name="Album" name="Albums"
component={AlbumsScreen} component={AlbumsScreen}
options={{ title: 'Album' }} options={{ title: 'Albums' }}
/> />
</ModalPresentationStack.Navigator> </ModalPresentationStack.Navigator>
); );

View File

@@ -0,0 +1,40 @@
import * as React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Button } from 'react-native-paper';
import type { StackNavigationProp } from '@react-navigation/stack';
const NotFoundScreen = ({
navigation,
}: {
navigation: StackNavigationProp<{ Home: undefined }>;
}) => {
return (
<View style={styles.container}>
<Text style={styles.title}>404 Not Found</Text>
<Button
mode="contained"
onPress={() => navigation.navigate('Home')}
style={styles.button}
>
Go to home
</Button>
</View>
);
};
export default NotFoundScreen;
const styles = StyleSheet.create({
title: {
fontSize: 36,
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 8,
},
button: {
margin: 24,
},
});

View File

@@ -1,38 +1,33 @@
import * as React from 'react'; import * as React from 'react';
import { View, Platform, StyleSheet, ScrollView } from 'react-native'; import { View, Platform, StyleSheet, ScrollView } from 'react-native';
import { Button } from 'react-native-paper'; import { Button } from 'react-native-paper';
import { RouteProp, ParamListBase } from '@react-navigation/native'; import type { ParamListBase } from '@react-navigation/native';
import { import {
createStackNavigator, createStackNavigator,
StackNavigationProp, StackScreenProps,
} from '@react-navigation/stack'; } from '@react-navigation/stack';
import Article from '../Shared/Article'; import Article from '../Shared/Article';
import Albums from '../Shared/Albums'; import Albums from '../Shared/Albums';
import NewsFeed from '../Shared/NewsFeed'; import NewsFeed from '../Shared/NewsFeed';
type SimpleStackParams = { type SimpleStackParams = {
Article: { author: string }; Article: { author: string } | undefined;
NewsFeed: undefined; NewsFeed: { date: number };
Album: undefined; Albums: undefined;
}; };
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
const scrollEnabled = Platform.select({ web: true, default: false }); const scrollEnabled = Platform.select({ web: true, default: false });
const ArticleScreen = ({ const ArticleScreen = ({
navigation, navigation,
route, route,
}: { }: StackScreenProps<SimpleStackParams, 'Article'>) => {
navigation: SimpleStackNavigation;
route: RouteProp<SimpleStackParams, 'Article'>;
}) => {
return ( return (
<ScrollView> <ScrollView>
<View style={styles.buttons}> <View style={styles.buttons}>
<Button <Button
mode="contained" mode="contained"
onPress={() => navigation.replace('NewsFeed')} onPress={() => navigation.replace('NewsFeed', { date: Date.now() })}
style={styles.button} style={styles.button}
> >
Replace with feed Replace with feed
@@ -46,7 +41,7 @@ const ArticleScreen = ({
</Button> </Button>
</View> </View>
<Article <Article
author={{ name: route.params.author }} author={{ name: route.params?.author ?? 'Unknown' }}
scrollEnabled={scrollEnabled} scrollEnabled={scrollEnabled}
/> />
</ScrollView> </ScrollView>
@@ -54,16 +49,15 @@ const ArticleScreen = ({
}; };
const NewsFeedScreen = ({ const NewsFeedScreen = ({
route,
navigation, navigation,
}: { }: StackScreenProps<SimpleStackParams, 'NewsFeed'>) => {
navigation: SimpleStackNavigation;
}) => {
return ( return (
<ScrollView> <ScrollView>
<View style={styles.buttons}> <View style={styles.buttons}>
<Button <Button
mode="contained" mode="contained"
onPress={() => navigation.navigate('Album')} onPress={() => navigation.navigate('Albums')}
style={styles.button} style={styles.button}
> >
Navigate to album Navigate to album
@@ -76,16 +70,14 @@ const NewsFeedScreen = ({
Go back Go back
</Button> </Button>
</View> </View>
<NewsFeed scrollEnabled={scrollEnabled} /> <NewsFeed scrollEnabled={scrollEnabled} date={route.params.date} />
</ScrollView> </ScrollView>
); );
}; };
const AlbumsScreen = ({ const AlbumsScreen = ({
navigation, navigation,
}: { }: StackScreenProps<SimpleStackParams, 'Albums'>) => {
navigation: SimpleStackNavigation;
}) => {
return ( return (
<ScrollView> <ScrollView>
<View style={styles.buttons}> <View style={styles.buttons}>
@@ -111,22 +103,20 @@ const AlbumsScreen = ({
const SimpleStack = createStackNavigator<SimpleStackParams>(); const SimpleStack = createStackNavigator<SimpleStackParams>();
type Props = Partial<React.ComponentProps<typeof SimpleStack.Navigator>> & { export default function SimpleStackScreen({
navigation: StackNavigationProp<ParamListBase>; navigation,
}; }: StackScreenProps<ParamListBase>) {
export default function SimpleStackScreen({ navigation, ...rest }: Props) {
navigation.setOptions({ navigation.setOptions({
headerShown: false, headerShown: false,
}); });
return ( return (
<SimpleStack.Navigator {...rest}> <SimpleStack.Navigator>
<SimpleStack.Screen <SimpleStack.Screen
name="Article" name="Article"
component={ArticleScreen} component={ArticleScreen}
options={({ route }) => ({ options={({ route }) => ({
title: `Article by ${route.params.author}`, title: `Article by ${route.params?.author ?? 'Unknown'}`,
})} })}
initialParams={{ author: 'Gandalf' }} initialParams={{ author: 'Gandalf' }}
/> />
@@ -136,9 +126,9 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
options={{ title: 'Feed' }} options={{ title: 'Feed' }}
/> />
<SimpleStack.Screen <SimpleStack.Screen
name="Album" name="Albums"
component={AlbumsScreen} component={AlbumsScreen}
options={{ title: 'Album' }} options={{ title: 'Albums' }}
/> />
</SimpleStack.Navigator> </SimpleStack.Navigator>
); );

View File

@@ -1,21 +1,30 @@
import * as React from 'react'; import * as React from 'react';
import { View, StyleSheet, ScrollView, Alert, Platform } from 'react-native'; import {
Animated,
View,
StyleSheet,
ScrollView,
Alert,
Platform,
} from 'react-native';
import { Button, Appbar } from 'react-native-paper'; import { Button, Appbar } from 'react-native-paper';
import { BlurView } from 'expo-blur'; import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import { MaterialCommunityIcons } from '@expo/vector-icons'; import { useTheme, RouteProp, ParamListBase } from '@react-navigation/native';
import { RouteProp, ParamListBase } from '@react-navigation/native';
import { import {
createStackNavigator, createStackNavigator,
StackNavigationProp, StackNavigationProp,
HeaderBackground, HeaderBackground,
useHeaderHeight, useHeaderHeight,
Header,
StackHeaderProps,
} from '@react-navigation/stack'; } from '@react-navigation/stack';
import BlurView from '../Shared/BlurView';
import Article from '../Shared/Article'; import Article from '../Shared/Article';
import Albums from '../Shared/Albums'; import Albums from '../Shared/Albums';
type SimpleStackParams = { type SimpleStackParams = {
Article: { author: string }; Article: { author: string };
Album: undefined; Albums: undefined;
}; };
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>; type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
@@ -34,7 +43,7 @@ const ArticleScreen = ({
<View style={styles.buttons}> <View style={styles.buttons}>
<Button <Button
mode="contained" mode="contained"
onPress={() => navigation.push('Album')} onPress={() => navigation.push('Albums')}
style={styles.button} style={styles.button}
> >
Push album Push album
@@ -91,11 +100,32 @@ type Props = Partial<React.ComponentProps<typeof SimpleStack.Navigator>> & {
navigation: StackNavigationProp<ParamListBase>; navigation: StackNavigationProp<ParamListBase>;
}; };
function CustomHeader(props: StackHeaderProps) {
const { current, next } = props.scene.progress;
const progress = Animated.add(current, next || 0);
const opacity = progress.interpolate({
inputRange: [0, 1, 2],
outputRange: [0, 1, 0],
});
return (
<>
<Header {...props} />
<Animated.Text style={[styles.banner, { opacity }]}>
Why hello there, pardner!
</Animated.Text>
</>
);
}
export default function SimpleStackScreen({ navigation, ...rest }: Props) { export default function SimpleStackScreen({ navigation, ...rest }: Props) {
navigation.setOptions({ navigation.setOptions({
headerShown: false, headerShown: false,
}); });
const { colors, dark } = useTheme();
return ( return (
<SimpleStack.Navigator {...rest}> <SimpleStack.Navigator {...rest}>
<SimpleStack.Screen <SimpleStack.Screen
@@ -103,6 +133,7 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
component={ArticleScreen} component={ArticleScreen}
options={({ route }) => ({ options={({ route }) => ({
title: `Article by ${route.params?.author}`, title: `Article by ${route.params?.author}`,
header: CustomHeader,
headerTintColor: '#fff', headerTintColor: '#fff',
headerStyle: { backgroundColor: '#ff005d' }, headerStyle: { backgroundColor: '#ff005d' },
headerBackTitleVisible: false, headerBackTitleVisible: false,
@@ -131,16 +162,22 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
initialParams={{ author: 'Gandalf' }} initialParams={{ author: 'Gandalf' }}
/> />
<SimpleStack.Screen <SimpleStack.Screen
name="Album" name="Albums"
component={AlbumsScreen} component={AlbumsScreen}
options={{ options={{
title: 'Album', title: 'Albums',
headerBackTitle: 'Back', headerBackTitle: 'Back',
headerTransparent: true, headerTransparent: true,
headerBackground: () => ( headerBackground: () => (
<HeaderBackground style={{ backgroundColor: 'transparent' }}> <HeaderBackground
style={{
backgroundColor: 'transparent',
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: colors.border,
}}
>
<BlurView <BlurView
tint="light" tint={dark ? 'dark' : 'light'}
intensity={75} intensity={75}
style={StyleSheet.absoluteFill} style={StyleSheet.absoluteFill}
/> />
@@ -160,4 +197,10 @@ const styles = StyleSheet.create({
button: { button: {
margin: 8, margin: 8,
}, },
banner: {
textAlign: 'center',
color: 'tomato',
backgroundColor: 'papayawhip',
padding: 4,
},
}); });

View File

@@ -81,10 +81,6 @@ export default function Albums(props: Partial<ScrollViewProps>) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
content: {
flexDirection: 'row',
flexWrap: 'wrap',
},
...Platform.select({ ...Platform.select({
web: { web: {
content: { content: {

View File

@@ -0,0 +1,3 @@
import { BlurView } from 'expo-blur';
export default BlurView;

View File

@@ -0,0 +1,12 @@
import * as React from 'react';
import { View, ViewProps } from 'react-native';
type Props = ViewProps & {
tint: 'light' | 'dark';
intensity: number;
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function BlurView({ tint, intensity, ...rest }: Props) {
return <View {...rest} />;
}

View File

@@ -18,7 +18,9 @@ import {
} from 'react-native-paper'; } from 'react-native-paper';
import Color from 'color'; import Color from 'color';
type Props = Partial<ScrollViewProps>; type Props = Partial<ScrollViewProps> & {
date?: number;
};
const Author = () => { const Author = () => {
return ( return (

View File

@@ -1,4 +1,4 @@
// @ts-ignore // @ts-expect-error: there are no type definitions for deep imports
import TouchableBounce from 'react-native/Libraries/Components/Touchable/TouchableBounce'; import TouchableBounce from 'react-native/Libraries/Components/Touchable/TouchableBounce';
export default TouchableBounce; export default TouchableBounce;

View File

@@ -7,13 +7,11 @@ import {
I18nManager, I18nManager,
Dimensions, Dimensions,
ScaledSize, ScaledSize,
Linking,
} from 'react-native'; } from 'react-native';
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
import { enableScreens } from 'react-native-screens'; import { enableScreens } from 'react-native-screens';
import RNRestart from 'react-native-restart'; import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { Updates } from 'expo';
import { Asset } from 'expo-asset';
import { MaterialIcons } from '@expo/vector-icons';
import { import {
Provider as PaperProvider, Provider as PaperProvider,
DefaultTheme as PaperLightTheme, DefaultTheme as PaperLightTheme,
@@ -28,6 +26,8 @@ import {
NavigationContainer, NavigationContainer,
DefaultTheme, DefaultTheme,
DarkTheme, DarkTheme,
PathConfigMap,
NavigationContainerRef,
} from '@react-navigation/native'; } from '@react-navigation/native';
import { import {
createDrawerNavigator, createDrawerNavigator,
@@ -35,11 +35,12 @@ import {
} from '@react-navigation/drawer'; } from '@react-navigation/drawer';
import { import {
createStackNavigator, createStackNavigator,
Assets as StackAssets,
StackNavigationProp, StackNavigationProp,
HeaderStyleInterpolators, HeaderStyleInterpolators,
} from '@react-navigation/stack'; } from '@react-navigation/stack';
import { useReduxDevToolsExtension } from '@react-navigation/devtools';
import { restartApp } from './Restart';
import AsyncStorage from './AsyncStorage'; import AsyncStorage from './AsyncStorage';
import LinkingPrefixes from './LinkingPrefixes'; import LinkingPrefixes from './LinkingPrefixes';
import SettingsItem from './Shared/SettingsItem'; import SettingsItem from './Shared/SettingsItem';
@@ -50,6 +51,7 @@ import StackHeaderCustomization from './Screens/StackHeaderCustomization';
import BottomTabs from './Screens/BottomTabs'; import BottomTabs from './Screens/BottomTabs';
import MaterialTopTabsScreen from './Screens/MaterialTopTabs'; import MaterialTopTabsScreen from './Screens/MaterialTopTabs';
import MaterialBottomTabs from './Screens/MaterialBottomTabs'; import MaterialBottomTabs from './Screens/MaterialBottomTabs';
import NotFound from './Screens/NotFound';
import DynamicTabs from './Screens/DynamicTabs'; import DynamicTabs from './Screens/DynamicTabs';
import AuthFlow from './Screens/AuthFlow'; import AuthFlow from './Screens/AuthFlow';
import CompatAPI from './Screens/CompatAPI'; import CompatAPI from './Screens/CompatAPI';
@@ -60,9 +62,6 @@ YellowBox.ignoreWarnings(['Require cycle:', 'Warning: Async Storage']);
enableScreens(); enableScreens();
// @ts-ignore
global.REACT_NAVIGATION_REDUX_DEVTOOLS_EXTENSION_INTEGRATION_ENABLED = true;
type RootDrawerParamList = { type RootDrawerParamList = {
Root: undefined; Root: undefined;
Another: undefined; Another: undefined;
@@ -70,6 +69,7 @@ type RootDrawerParamList = {
type RootStackParamList = { type RootStackParamList = {
Home: undefined; Home: undefined;
NotFound: undefined;
} & { } & {
[P in keyof typeof SCREENS]: undefined; [P in keyof typeof SCREENS]: undefined;
}; };
@@ -125,12 +125,10 @@ const Stack = createStackNavigator<RootStackParamList>();
const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE'; const NAVIGATION_PERSISTENCE_KEY = 'NAVIGATION_STATE';
const THEME_PERSISTENCE_KEY = 'THEME_TYPE'; const THEME_PERSISTENCE_KEY = 'THEME_TYPE';
Asset.loadAsync(StackAssets);
export default function App() { export default function App() {
const [theme, setTheme] = React.useState(DefaultTheme); const [theme, setTheme] = React.useState(DefaultTheme);
const [isReady, setIsReady] = React.useState(false); const [isReady, setIsReady] = React.useState(Platform.OS === 'web');
const [initialState, setInitialState] = React.useState< const [initialState, setInitialState] = React.useState<
InitialState | undefined InitialState | undefined
>(); >();
@@ -138,18 +136,18 @@ export default function App() {
React.useEffect(() => { React.useEffect(() => {
const restoreState = async () => { const restoreState = async () => {
try { try {
let state; const initialUrl = await Linking.getInitialURL();
if (Platform.OS !== 'web' && state === undefined) { if (Platform.OS !== 'web' || initialUrl === null) {
const savedState = await AsyncStorage.getItem( const savedState = await AsyncStorage.getItem(
NAVIGATION_PERSISTENCE_KEY NAVIGATION_PERSISTENCE_KEY
); );
state = savedState ? JSON.parse(savedState) : undefined; const state = savedState ? JSON.parse(savedState) : undefined;
}
if (state !== undefined) { if (state !== undefined) {
setInitialState(state); setInitialState(state);
}
} }
} finally { } finally {
try { try {
@@ -193,6 +191,10 @@ export default function App() {
return () => Dimensions.removeEventListener('change', onDimensionsChange); return () => Dimensions.removeEventListener('change', onDimensionsChange);
}, []); }, []);
const navigationRef = React.useRef<NavigationContainerRef>(null);
useReduxDevToolsExtension(navigationRef);
if (!isReady) { if (!isReady) {
return null; return null;
} }
@@ -205,6 +207,7 @@ export default function App() {
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} /> <StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
)} )}
<NavigationContainer <NavigationContainer
ref={navigationRef}
initialState={initialState} initialState={initialState}
onStateChange={(state) => onStateChange={(state) =>
AsyncStorage.setItem( AsyncStorage.setItem(
@@ -222,21 +225,49 @@ export default function App() {
// The first segment of the link is the the scheme + host (returned by `Linking.makeUrl`) // The first segment of the link is the the scheme + host (returned by `Linking.makeUrl`)
prefixes: LinkingPrefixes, prefixes: LinkingPrefixes,
config: { config: {
Root: { screens: {
path: '', Root: {
initialRouteName: 'Home', path: '',
screens: Object.keys(SCREENS).reduce<{ [key: string]: string }>( initialRouteName: 'Home',
(acc, name) => { screens: Object.keys(SCREENS).reduce<PathConfigMap>(
// Convert screen names such as SimpleStack to kebab case (simple-stack) (acc, name) => {
acc[name] = name // Convert screen names such as SimpleStack to kebab case (simple-stack)
.replace(/([A-Z]+)/g, '-$1') const path = name
.replace(/^-/, '') .replace(/([A-Z]+)/g, '-$1')
.toLowerCase(); .replace(/^-/, '')
.toLowerCase();
return acc; acc[name] = {
}, path,
{ Home: '' } screens: {
), Article: {
path: 'article/:author?',
parse: {
author: (author) =>
author.charAt(0).toUpperCase() +
author.slice(1).replace(/-/g, ' '),
},
stringify: {
author: (author: string) =>
author.toLowerCase().replace(/\s/g, '-'),
},
},
Albums: 'music',
Chat: 'chat',
Contacts: 'people',
NewsFeed: 'feed',
Dialog: 'dialog',
},
};
return acc;
},
{
Home: '',
NotFound: '*',
}
),
},
}, },
}, },
}} }}
@@ -290,12 +321,7 @@ export default function App() {
value={I18nManager.isRTL} value={I18nManager.isRTL}
onValueChange={() => { onValueChange={() => {
I18nManager.forceRTL(!I18nManager.isRTL); I18nManager.forceRTL(!I18nManager.isRTL);
// @ts-ignore restartApp();
if (global.Expo) {
Updates.reloadFromCache();
} else {
RNRestart.Restart();
}
}} }}
/> />
<Divider /> <Divider />
@@ -325,6 +351,11 @@ export default function App() {
</ScrollView> </ScrollView>
)} )}
</Stack.Screen> </Stack.Screen>
<Stack.Screen
name="NotFound"
component={NotFound}
options={{ title: 'Oops!' }}
/>
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map( {(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
(name) => ( (name) => (
<Stack.Screen <Stack.Screen

16
example/types/react-native-web.d.ts vendored Normal file
View File

@@ -0,0 +1,16 @@
declare module 'react-native-web' {
export const AppRegistry: {
registerComponent(
name: string,
callback: () => React.ComponentType<any>
): void;
getApplication(
name: string,
options?: { initialProps: object }
): {
element: React.ReactElement;
getStyleElement(): React.ReactElement;
};
};
}

View File

@@ -24,19 +24,21 @@ module.exports = async function (env, argv) {
); );
Object.assign(config.resolve.alias, { Object.assign(config.resolve.alias, {
react: path.resolve(node_modules, 'react'), 'react': path.resolve(node_modules, 'react'),
'react-native': path.resolve(node_modules, 'react-native-web'), 'react-native': path.resolve(node_modules, 'react-native-web'),
'react-native-web': path.resolve(node_modules, 'react-native-web'), 'react-native-web': path.resolve(node_modules, 'react-native-web'),
'@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'), '@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'),
}); });
fs.readdirSync(packages).forEach((name) => { fs.readdirSync(packages)
config.resolve.alias[`@react-navigation/${name}`] = path.resolve( .filter((name) => !name.startsWith('.'))
packages, .forEach((name) => {
name, config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
'src' packages,
); name,
}); require(`../packages/${name}/package.json`).source
);
});
return config; return config;
}; };

View File

@@ -8,7 +8,7 @@
"version": "independent", "version": "independent",
"command": { "command": {
"publish": { "publish": {
"allowBranch": "master", "allowBranch": "main",
"conventionalCommits": true, "conventionalCommits": true,
"createRelease": "github", "createRelease": "github",
"message": "chore: publish", "message": "chore: publish",

View File

@@ -13,7 +13,7 @@
"license": "MIT", "license": "MIT",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/satya164/react-navigation.git" "url": "git+https://github.com/react-navigation/react-navigation.git"
}, },
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)", "author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)",
"scripts": { "scripts": {
@@ -25,26 +25,26 @@
"example": "yarn --cwd example" "example": "yarn --cwd example"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.10.1",
"@babel/plugin-proposal-optional-chaining": "^7.9.0", "@babel/plugin-proposal-optional-chaining": "^7.10.1",
"@babel/preset-env": "^7.9.0", "@babel/preset-env": "^7.10.2",
"@babel/preset-flow": "^7.9.0", "@babel/preset-flow": "^7.10.1",
"@babel/preset-react": "^7.9.4", "@babel/preset-react": "^7.10.1",
"@babel/preset-typescript": "^7.9.0", "@babel/preset-typescript": "^7.10.1",
"@babel/runtime": "^7.9.2", "@babel/runtime": "^7.10.2",
"@commitlint/config-conventional": "^8.3.4", "@commitlint/config-conventional": "^8.3.4",
"@types/jest": "^25.2.1", "@types/jest": "^26.0.0",
"babel-jest": "^25.2.6", "babel-jest": "^26.0.1",
"codecov": "^3.6.5", "codecov": "^3.7.0",
"commitlint": "^8.3.5", "commitlint": "^8.3.5",
"core-js": "^3.6.4", "core-js": "^3.6.5",
"eslint": "^6.8.0", "eslint": "^7.2.0",
"eslint-config-satya164": "^3.1.6", "eslint-config-satya164": "^3.1.7",
"husky": "^4.2.3", "husky": "^4.2.5",
"jest": "^25.2.7", "jest": "^26.0.1",
"lerna": "^3.20.2", "lerna": "^3.22.1",
"prettier": "^2.0.4", "prettier": "^2.0.5",
"typescript": "^3.8.3" "typescript": "^3.9.5"
}, },
"resolutions": { "resolutions": {
"react": "~16.9.0", "react": "~16.9.0",

View File

@@ -3,7 +3,7 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.3...@react-navigation/bottom-tabs@5.3.4) (2020-05-05) ## [5.6.1](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@5.6.0...@react-navigation/bottom-tabs@5.6.1) (2020-06-25)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -11,43 +11,24 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.2...@react-navigation/bottom-tabs@5.3.3) (2020-05-01) # [5.6.0](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@5.5.2...@react-navigation/bottom-tabs@5.6.0) (2020-06-24)
**Note:** Version bump only for package @react-navigation/bottom-tabs
### Bug Fixes
* make sure we don't miss dimensions updates ([c65f9ef](https://github.com/react-navigation/react-navigation/commit/c65f9ef1a9be93b399e724a9731605e408aca80e))
* remove broken showIcon option from bottom-tabs ([1612819](https://github.com/react-navigation/react-navigation/commit/16128199edd4de37f9c7353bdf803de8e2f201a2))
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.1...@react-navigation/bottom-tabs@5.3.2) (2020-05-01)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.0...@react-navigation/bottom-tabs@5.3.1) (2020-04-30)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.8...@react-navigation/bottom-tabs@5.3.0) (2020-04-30)
### Features ### Features
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/2792f438fe45428fe193e3708fee7ad61966cbf4)) * add iconStyle prop to bottom tab bar options ([#8188](https://github.com/react-navigation/react-navigation/issues/8188)) ([4480d2f](https://github.com/react-navigation/react-navigation/commit/4480d2fe04c8da11b444ebe75ee618d380682312))
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/942d2be2c72720469475ce12ec8df23825994dbf))
## [5.2.8](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.7...@react-navigation/bottom-tabs@5.2.8) (2020-04-27) ## [5.5.2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.5.1...@react-navigation/bottom-tabs@5.5.2) (2020-06-06)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -55,81 +36,30 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.2.7](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.6...@react-navigation/bottom-tabs@5.2.7) (2020-04-17) ## [5.5.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.5.0...@react-navigation/bottom-tabs@5.5.1) (2020-05-27)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.5...@react-navigation/bottom-tabs@5.2.6) (2020-04-08)
### Bug Fixes ### Bug Fixes
* mark type exports for all packages ([b71de6c](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/b71de6cc799143f1d0e8a0cfcc34f0a2381f9840)) * fix type of style for various options ([9d822b9](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/9d822b95a6df797e2e63e481573e64ea7d0f9386))
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.4...@react-navigation/bottom-tabs@5.2.5) (2020-03-30) # [5.5.0](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.7...@react-navigation/bottom-tabs@5.5.0) (2020-05-23)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.3...@react-navigation/bottom-tabs@5.2.4) (2020-03-23)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.2...@react-navigation/bottom-tabs@5.2.3) (2020-03-22)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.1...@react-navigation/bottom-tabs@5.2.2) (2020-03-19)
### Bug Fixes
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/7485)
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6789)
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.0...@react-navigation/bottom-tabs@5.2.1) (2020-03-17)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.1...@react-navigation/bottom-tabs@5.2.0) (2020-03-16)
### Features ### Features
* add safeAreaInsets to bottom tabs ([82af7be](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/82af7bed7135e42e24693b48cf7f1c6f9f5a6981)) * animate changes to tabBarVisible in BottomTabBar ([#8286](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/8286)) ([c1e46f8](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/c1e46f8e331e0054995aa476455af204d02d4170))
* update react-native-safe-area-context to 1.0.0 ([#8182](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/8182)) ([d62fbfe](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/d62fbfe255140f16b182e8b54b276a7c96f2aec6))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.0...@react-navigation/bottom-tabs@5.1.1) (2020-03-03) ## [5.4.7](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.6...@react-navigation/bottom-tabs@5.4.7) (2020-05-20)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -137,18 +67,69 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.7...@react-navigation/bottom-tabs@5.1.0) (2020-02-26) ## [5.4.6](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.5...@react-navigation/bottom-tabs@5.4.6) (2020-05-20)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.4.5](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.4...@react-navigation/bottom-tabs@5.4.5) (2020-05-16)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.4.4](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.3...@react-navigation/bottom-tabs@5.4.4) (2020-05-14)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.4.3](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.2...@react-navigation/bottom-tabs@5.4.3) (2020-05-14)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.1...@react-navigation/bottom-tabs@5.4.2) (2020-05-10)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.0...@react-navigation/bottom-tabs@5.4.1) (2020-05-08)
### Bug Fixes
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.4...@react-navigation/bottom-tabs@5.4.0) (2020-05-08)
### Features ### Features
* add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6756) * add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/7971)
## [5.0.7](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.6...@react-navigation/bottom-tabs@5.0.7) (2020-02-21) ## [5.3.4](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.3...@react-navigation/bottom-tabs@5.3.4) (2020-05-05)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -156,7 +137,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.6](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.5...@react-navigation/bottom-tabs@5.0.6) (2020-02-19) ## [5.3.3](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.2...@react-navigation/bottom-tabs@5.3.3) (2020-05-01)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -164,7 +145,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.5](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.4...@react-navigation/bottom-tabs@5.0.5) (2020-02-14) ## [5.3.2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.1...@react-navigation/bottom-tabs@5.3.2) (2020-05-01)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -172,7 +153,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.3...@react-navigation/bottom-tabs@5.0.4) (2020-02-14) ## [5.3.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.0...@react-navigation/bottom-tabs@5.3.1) (2020-04-30)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -180,108 +161,19 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.2...@react-navigation/bottom-tabs@5.0.3) (2020-02-12) # [5.3.0](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.8...@react-navigation/bottom-tabs@5.3.0) (2020-04-30)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.1...@react-navigation/bottom-tabs@5.0.2) (2020-02-11)
### Bug Fixes
* initialize keyboard-hiding tabBar to visible=true ([#6740](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6740), [#6799](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6799)) ([0c59ef7](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/0c59ef7328c63108a2a2c04e927794d73cead63a))
* provide route context to header and bottom tabs ([b6e7e08](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/b6e7e08b9a05be6c04ed21e938b9580876239116))
## [5.0.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.45...@react-navigation/bottom-tabs@5.0.1) (2020-02-10)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.45](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.44...@react-navigation/bottom-tabs@5.0.0-alpha.45) (2020-02-04)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.44](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.43...@react-navigation/bottom-tabs@5.0.0-alpha.44) (2020-02-04)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.43](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.42...@react-navigation/bottom-tabs@5.0.0-alpha.43) (2020-02-03)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.42) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.40) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
# [5.0.0-alpha.39](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.38...@react-navigation/bottom-tabs@5.0.0-alpha.39) (2020-01-24)
### Bug Fixes
* use layout instead of dimensions for determining tab bar layout ([f1fe951](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/f1fe951cf9d602e1b6d4932e3c6c77bbeaaec5c0))
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.37...@react-navigation/bottom-tabs@5.0.0-alpha.38) (2020-01-23)
### Bug Fixes
* don't use native driver on web ([0a982ee](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/0a982ee6984b24c0ba053a30223e255f3835e050))
### Features ### Features
* let the navigator specify if default can be prevented ([da67e13](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/da67e134d2157201360427d3c10da24f24cae7aa)) * add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/942d2be2c72720469475ce12ec8df23825994dbf))
# [5.0.0-alpha.37](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.36...@react-navigation/bottom-tabs@5.0.0-alpha.37) (2020-01-14) ## [5.2.8](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.7...@react-navigation/bottom-tabs@5.2.8) (2020-04-27)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -289,18 +181,26 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.35...@react-navigation/bottom-tabs@5.0.0-alpha.36) (2020-01-13) ## [5.2.7](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.6...@react-navigation/bottom-tabs@5.2.7) (2020-04-17)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.5...@react-navigation/bottom-tabs@5.2.6) (2020-04-08)
### Bug Fixes ### Bug Fixes
* make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/issues/265) * mark type exports for all packages ([b71de6c](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/b71de6cc799143f1d0e8a0cfcc34f0a2381f9840))
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.34...@react-navigation/bottom-tabs@5.0.0-alpha.35) (2020-01-13) ## [5.2.5](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.4...@react-navigation/bottom-tabs@5.2.5) (2020-03-30)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -308,7 +208,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.32...@react-navigation/bottom-tabs@5.0.0-alpha.34) (2020-01-09) ## [5.2.4](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.3...@react-navigation/bottom-tabs@5.2.4) (2020-03-23)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs
@@ -316,7 +216,233 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.32...@react-navigation/bottom-tabs@5.0.0-alpha.33) (2020-01-09) ## [5.2.3](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.2...@react-navigation/bottom-tabs@5.2.3) (2020-03-22)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.1...@react-navigation/bottom-tabs@5.2.2) (2020-03-19)
### Bug Fixes
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/7485)
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/6789)
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.0...@react-navigation/bottom-tabs@5.2.1) (2020-03-17)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.1...@react-navigation/bottom-tabs@5.2.0) (2020-03-16)
### Features
* add safeAreaInsets to bottom tabs ([82af7be](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/82af7bed7135e42e24693b48cf7f1c6f9f5a6981))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.0...@react-navigation/bottom-tabs@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.7...@react-navigation/bottom-tabs@5.1.0) (2020-02-26)
### Features
* add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/6756)
## [5.0.7](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.6...@react-navigation/bottom-tabs@5.0.7) (2020-02-21)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.6](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.5...@react-navigation/bottom-tabs@5.0.6) (2020-02-19)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.5](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.4...@react-navigation/bottom-tabs@5.0.5) (2020-02-14)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.4](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.3...@react-navigation/bottom-tabs@5.0.4) (2020-02-14)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.3](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.2...@react-navigation/bottom-tabs@5.0.3) (2020-02-12)
**Note:** Version bump only for package @react-navigation/bottom-tabs
## [5.0.2](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.1...@react-navigation/bottom-tabs@5.0.2) (2020-02-11)
### Bug Fixes
* initialize keyboard-hiding tabBar to visible=true ([#6740](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/6740), [#6799](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/6799)) ([0c59ef7](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/0c59ef7328c63108a2a2c04e927794d73cead63a))
* provide route context to header and bottom tabs ([b6e7e08](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/b6e7e08b9a05be6c04ed21e938b9580876239116))
## [5.0.1](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.45...@react-navigation/bottom-tabs@5.0.1) (2020-02-10)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.45](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.44...@react-navigation/bottom-tabs@5.0.0-alpha.45) (2020-02-04)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.44](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.43...@react-navigation/bottom-tabs@5.0.0-alpha.44) (2020-02-04)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.43](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.42...@react-navigation/bottom-tabs@5.0.0-alpha.43) (2020-02-03)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.42](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.42) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
# [5.0.0-alpha.40](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.40) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
# [5.0.0-alpha.39](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.38...@react-navigation/bottom-tabs@5.0.0-alpha.39) (2020-01-24)
### Bug Fixes
* use layout instead of dimensions for determining tab bar layout ([f1fe951](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/f1fe951cf9d602e1b6d4932e3c6c77bbeaaec5c0))
# [5.0.0-alpha.38](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.37...@react-navigation/bottom-tabs@5.0.0-alpha.38) (2020-01-23)
### Bug Fixes
* don't use native driver on web ([0a982ee](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/0a982ee6984b24c0ba053a30223e255f3835e050))
### Features
* let the navigator specify if default can be prevented ([da67e13](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/da67e134d2157201360427d3c10da24f24cae7aa))
# [5.0.0-alpha.37](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.36...@react-navigation/bottom-tabs@5.0.0-alpha.37) (2020-01-14)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.36](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.35...@react-navigation/bottom-tabs@5.0.0-alpha.36) (2020-01-13)
### Bug Fixes
* make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/issues/265)
# [5.0.0-alpha.35](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.34...@react-navigation/bottom-tabs@5.0.0-alpha.35) (2020-01-13)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.34](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.32...@react-navigation/bottom-tabs@5.0.0-alpha.34) (2020-01-09)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.33](https://github.com/react-navigation/react-navigation/tree/main/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.32...@react-navigation/bottom-tabs@5.0.0-alpha.33) (2020-01-09)
**Note:** Version bump only for package @react-navigation/bottom-tabs **Note:** Version bump only for package @react-navigation/bottom-tabs

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/bottom-tabs", "name": "@react-navigation/bottom-tabs",
"description": "Bottom tab navigator following iOS design guidelines", "description": "Bottom tab navigator following iOS design guidelines",
"version": "5.3.4", "version": "5.6.1",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -12,14 +12,20 @@
"tab" "tab"
], ],
"license": "MIT", "license": "MIT",
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs", "repository": {
"type": "git",
"url": "https://github.com/react-navigation/react-navigation.git",
"directory": "packages/bottom-tabs"
},
"main": "lib/commonjs/index.js", "main": "lib/commonjs/index.js",
"react-native": "src/index.tsx", "react-native": "src/index.tsx",
"source": "src/index.tsx",
"module": "lib/module/index.js", "module": "lib/module/index.js",
"types": "lib/typescript/src/index.d.ts", "types": "lib/typescript/src/index.d.ts",
"files": [ "files": [
"src", "src",
"lib" "lib",
"!**/__tests__"
], ],
"sideEffects": false, "sideEffects": false,
"publishConfig": { "publishConfig": {
@@ -34,17 +40,17 @@
"react-native-iphone-x-helper": "^1.2.1" "react-native-iphone-x-helper": "^1.2.1"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.10.0", "@react-native-community/bob": "^0.15.1",
"@react-navigation/native": "^5.2.4", "@react-navigation/native": "^5.6.1",
"@types/color": "^3.0.1", "@types/color": "^3.0.1",
"@types/react": "^16.9.23", "@types/react": "^16.9.36",
"@types/react-native": "^0.61.22", "@types/react-native": "^0.62.7",
"del-cli": "^3.0.0", "del-cli": "^3.0.1",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-safe-area-context": "^0.7.3", "react-native-safe-area-context": "^1.0.0",
"react-native-screens": "^2.3.0", "react-native-screens": "^2.7.0",
"typescript": "^3.8.3" "typescript": "^3.9.5"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^5.0.5", "@react-navigation/native": "^5.0.5",

View File

@@ -15,6 +15,7 @@ export { default as BottomTabBar } from './views/BottomTabBar';
export type { export type {
BottomTabNavigationOptions, BottomTabNavigationOptions,
BottomTabNavigationProp, BottomTabNavigationProp,
BottomTabScreenProps,
BottomTabBarProps, BottomTabBarProps,
BottomTabBarOptions, BottomTabBarOptions,
} from './types'; } from './types';

View File

@@ -8,7 +8,7 @@ import {
TabNavigationState, TabNavigationState,
} from '@react-navigation/native'; } from '@react-navigation/native';
import BottomTabView from '../views/BottomTabView'; import BottomTabView from '../views/BottomTabView';
import { import type {
BottomTabNavigationConfig, BottomTabNavigationConfig,
BottomTabNavigationOptions, BottomTabNavigationOptions,
BottomTabNavigationEventMap, BottomTabNavigationEventMap,

View File

@@ -1,18 +1,20 @@
import * as React from 'react'; import type * as React from 'react';
import { import type {
Animated,
TouchableWithoutFeedbackProps, TouchableWithoutFeedbackProps,
StyleProp, StyleProp,
TextStyle, TextStyle,
ViewStyle, ViewStyle,
GestureResponderEvent, GestureResponderEvent,
} from 'react-native'; } from 'react-native';
import { import type {
NavigationHelpers, NavigationHelpers,
NavigationProp, NavigationProp,
ParamListBase, ParamListBase,
Descriptor, Descriptor,
TabNavigationState, TabNavigationState,
TabActionHelpers, TabActionHelpers,
RouteProp,
} from '@react-navigation/native'; } from '@react-navigation/native';
export type BottomTabNavigationEventMap = { export type BottomTabNavigationEventMap = {
@@ -45,6 +47,14 @@ export type BottomTabNavigationProp<
> & > &
TabActionHelpers<ParamList>; TabActionHelpers<ParamList>;
export type BottomTabScreenProps<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string
> = {
navigation: BottomTabNavigationProp<ParamList, RouteName>;
route: RouteProp<ParamList, RouteName>;
};
export type BottomTabNavigationOptions = { export type BottomTabNavigationOptions = {
/** /**
* Title text for the screen. * Title text for the screen.
@@ -109,7 +119,7 @@ export type BottomTabDescriptorMap = {
[key: string]: BottomTabDescriptor; [key: string]: BottomTabDescriptor;
}; };
export type BottomTabNavigationConfig = { export type BottomTabNavigationConfig<T = BottomTabBarOptions> = {
/** /**
* Whether the screens should render the first time they are accessed. Defaults to `true`. * Whether the screens should render the first time they are accessed. Defaults to `true`.
* Set it to `false` if you want to render all screens on initial render. * Set it to `false` if you want to render all screens on initial render.
@@ -118,11 +128,11 @@ export type BottomTabNavigationConfig = {
/** /**
* Function that returns a React element to display as the tab bar. * Function that returns a React element to display as the tab bar.
*/ */
tabBar?: (props: BottomTabBarProps) => React.ReactNode; tabBar?: (props: BottomTabBarProps<T>) => React.ReactNode;
/** /**
* Options for the tab bar which will be passed as props to the tab bar component. * Options for the tab bar which will be passed as props to the tab bar component.
*/ */
tabBarOptions?: BottomTabBarOptions; tabBarOptions?: T;
}; };
export type BottomTabBarOptions = { export type BottomTabBarOptions = {
@@ -154,21 +164,21 @@ export type BottomTabBarOptions = {
* Whether the tab label should be visible. Defaults to `true`. * Whether the tab label should be visible. Defaults to `true`.
*/ */
showLabel?: boolean; showLabel?: boolean;
/**
* Whether the tab icon should be visible. Defaults to `true`.
*/
showIcon?: boolean;
/** /**
* Style object for the tab label. * Style object for the tab label.
*/ */
labelStyle?: StyleProp<TextStyle>; labelStyle?: StyleProp<TextStyle>;
/**
* Style object for the tab icon.
*/
iconStyle?: StyleProp<TextStyle>;
/** /**
* Style object for the tab container. * Style object for the tab container.
*/ */
tabStyle?: StyleProp<ViewStyle>; tabStyle?: StyleProp<ViewStyle>;
/** /**
* Whether the label is rendered below the icon or beside the icon. * Whether the label is rendered below the icon or beside the icon.
* By default, in `vertical` orinetation, label is rendered below and in `horizontal` orientation, it's rendered beside. * By default, in `vertical` orientation, label is rendered below and in `horizontal` orientation, it's rendered beside.
*/ */
labelPosition?: LabelPosition; labelPosition?: LabelPosition;
/** /**
@@ -188,10 +198,10 @@ export type BottomTabBarOptions = {
/** /**
* Style object for the tab bar container. * Style object for the tab bar container.
*/ */
style?: StyleProp<ViewStyle>; style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
}; };
export type BottomTabBarProps = BottomTabBarOptions & { export type BottomTabBarProps<T = BottomTabBarOptions> = T & {
state: TabNavigationState; state: TabNavigationState;
descriptors: BottomTabDescriptorMap; descriptors: BottomTabDescriptorMap;
navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>; navigation: NavigationHelpers<ParamListBase, BottomTabNavigationEventMap>;

View File

@@ -0,0 +1,31 @@
import * as React from 'react';
import { Keyboard, Platform } from 'react-native';
export default function useIsKeyboardShown() {
const [isKeyboardShown, setIsKeyboardShown] = React.useState(false);
React.useEffect(() => {
const handleKeyboardShow = () => setIsKeyboardShown(true);
const handleKeyboardHide = () => setIsKeyboardShown(false);
if (Platform.OS === 'ios') {
Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
} else {
Keyboard.addListener('keyboardDidShow', handleKeyboardShow);
Keyboard.addListener('keyboardDidHide', handleKeyboardHide);
}
return () => {
if (Platform.OS === 'ios') {
Keyboard.removeListener('keyboardWillShow', handleKeyboardShow);
Keyboard.removeListener('keyboardWillHide', handleKeyboardHide);
} else {
Keyboard.removeListener('keyboardDidShow', handleKeyboardShow);
Keyboard.removeListener('keyboardDidHide', handleKeyboardHide);
}
};
}, []);
return isKeyboardShown;
}

View File

@@ -0,0 +1,37 @@
import * as React from 'react';
import { ScaledSize, Dimensions } from 'react-native';
// This is similar to the new useWindowDimensions hook in react-native
// However, we have a custom implementation to support older RN versions
export default function useWindowDimensions() {
const [dimensions, setDimensions] = React.useState(() => {
// `height` and `width` maybe undefined during SSR, so we initialize them
const { height = 0, width = 0 } = Dimensions.get('window');
return { height, width };
});
React.useEffect(() => {
const onChange = ({ window }: { window: ScaledSize }) => {
const { width, height } = window;
setDimensions((d) => {
if (width === d.width && height === d.height) {
return d;
}
return { width, height };
});
};
// We might have missed an update before the listener was added
// So make sure to update the dimensions
onChange({ window: Dimensions.get('window') });
Dimensions.addEventListener('change', onChange);
return () => Dimensions.addEventListener('change', onChange);
}, []);
return dimensions;
}

View File

@@ -3,11 +3,8 @@ import {
View, View,
Animated, Animated,
StyleSheet, StyleSheet,
Keyboard,
Platform, Platform,
LayoutChangeEvent, LayoutChangeEvent,
ScaledSize,
Dimensions,
} from 'react-native'; } from 'react-native';
import { import {
NavigationContext, NavigationContext,
@@ -19,7 +16,9 @@ import {
import { useSafeArea } from 'react-native-safe-area-context'; import { useSafeArea } from 'react-native-safe-area-context';
import BottomTabItem from './BottomTabItem'; import BottomTabItem from './BottomTabItem';
import { BottomTabBarProps } from '../types'; import useWindowDimensions from '../utils/useWindowDimensions';
import useIsKeyboardShown from '../utils/useIsKeyboardShown';
import type { BottomTabBarProps } from '../types';
type Props = BottomTabBarProps & { type Props = BottomTabBarProps & {
activeTintColor?: string; activeTintColor?: string;
@@ -44,8 +43,8 @@ export default function BottomTabBar({
keyboardHidesTabBar = false, keyboardHidesTabBar = false,
labelPosition, labelPosition,
labelStyle, labelStyle,
iconStyle,
safeAreaInsets, safeAreaInsets,
showIcon,
showLabel, showLabel,
style, style,
tabStyle, tabStyle,
@@ -53,72 +52,49 @@ export default function BottomTabBar({
const { colors } = useTheme(); const { colors } = useTheme();
const buildLink = useLinkBuilder(); const buildLink = useLinkBuilder();
const [dimensions, setDimensions] = React.useState(() => { const focusedRoute = state.routes[state.index];
const { height = 0, width = 0 } = Dimensions.get('window'); const focusedDescriptor = descriptors[focusedRoute.key];
const focusedOptions = focusedDescriptor.options;
return { height, width }; const dimensions = useWindowDimensions();
}); const isKeyboardShown = useIsKeyboardShown();
const [layout, setLayout] = React.useState({ const shouldShowTabBar =
height: 0, focusedOptions.tabBarVisible !== false &&
width: dimensions.width, !(keyboardHidesTabBar && isKeyboardShown);
});
const [keyboardShown, setKeyboardShown] = React.useState(false);
const [visible] = React.useState(() => new Animated.Value(1)); const [isTabBarHidden, setIsTabBarHidden] = React.useState(!shouldShowTabBar);
const { routes } = state; const [visible] = React.useState(
() => new Animated.Value(shouldShowTabBar ? 1 : 0)
);
React.useEffect(() => { React.useEffect(() => {
if (keyboardShown) { if (shouldShowTabBar) {
Animated.timing(visible, {
toValue: 0,
duration: 200,
useNativeDriver,
}).start();
}
}, [keyboardShown, visible]);
React.useEffect(() => {
const handleOrientationChange = ({ window }: { window: ScaledSize }) => {
setDimensions(window);
};
const handleKeyboardShow = () => setKeyboardShown(true);
const handleKeyboardHide = () =>
Animated.timing(visible, { Animated.timing(visible, {
toValue: 1, toValue: 1,
duration: 250, duration: 250,
useNativeDriver, useNativeDriver,
}).start(({ finished }) => { }).start(({ finished }) => {
if (finished) { if (finished) {
setKeyboardShown(false); setIsTabBarHidden(false);
} }
}); });
Dimensions.addEventListener('change', handleOrientationChange);
if (Platform.OS === 'ios') {
Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
} else { } else {
Keyboard.addListener('keyboardDidShow', handleKeyboardShow); setIsTabBarHidden(true);
Keyboard.addListener('keyboardDidHide', handleKeyboardHide);
Animated.timing(visible, {
toValue: 0,
duration: 200,
useNativeDriver,
}).start();
} }
}, [shouldShowTabBar, visible]);
return () => { const [layout, setLayout] = React.useState({
Dimensions.removeEventListener('change', handleOrientationChange); height: 0,
width: dimensions.width,
if (Platform.OS === 'ios') { });
Keyboard.removeListener('keyboardWillShow', handleKeyboardShow);
Keyboard.removeListener('keyboardWillHide', handleKeyboardHide);
} else {
Keyboard.removeListener('keyboardDidShow', handleKeyboardShow);
Keyboard.removeListener('keyboardDidHide', handleKeyboardHide);
}
};
}, [visible]);
const handleLayout = (e: LayoutChangeEvent) => { const handleLayout = (e: LayoutChangeEvent) => {
const { height, width } = e.nativeEvent.layout; const { height, width } = e.nativeEvent.layout;
@@ -135,6 +111,7 @@ export default function BottomTabBar({
}); });
}; };
const { routes } = state;
const shouldUseHorizontalLabels = () => { const shouldUseHorizontalLabels = () => {
if (labelPosition) { if (labelPosition) {
return labelPosition === 'beside-icon'; return labelPosition === 'beside-icon';
@@ -183,22 +160,19 @@ export default function BottomTabBar({
backgroundColor: colors.card, backgroundColor: colors.card,
borderTopColor: colors.border, borderTopColor: colors.border,
}, },
keyboardHidesTabBar {
? { transform: [
// When the keyboard is shown, slide down the tab bar {
transform: [ translateY: visible.interpolate({
{ inputRange: [0, 1],
translateY: visible.interpolate({ outputRange: [layout.height + insets.bottom, 0],
inputRange: [0, 1], }),
outputRange: [layout.height, 0], },
}), ],
}, // Absolutely position the tab bar so that the content is below it
], // This is needed to avoid gap at bottom when the tab bar is hidden
// Absolutely position the tab bar so that the content is below it position: isTabBarHidden ? 'absolute' : null,
// This is needed to avoid gap at bottom when the tab bar is hidden },
position: keyboardShown ? 'absolute' : null,
}
: null,
{ {
height: DEFAULT_TABBAR_HEIGHT + insets.bottom, height: DEFAULT_TABBAR_HEIGHT + insets.bottom,
paddingBottom: insets.bottom, paddingBottom: insets.bottom,
@@ -206,7 +180,7 @@ export default function BottomTabBar({
}, },
style, style,
]} ]}
pointerEvents={keyboardHidesTabBar && keyboardShown ? 'none' : 'auto'} pointerEvents={isTabBarHidden ? 'none' : 'auto'}
> >
<View style={styles.content} onLayout={handleLayout}> <View style={styles.content} onLayout={handleLayout}>
{routes.map((route, index) => { {routes.map((route, index) => {
@@ -272,9 +246,9 @@ export default function BottomTabBar({
button={options.tabBarButton} button={options.tabBarButton}
icon={options.tabBarIcon} icon={options.tabBarIcon}
label={label} label={label}
showIcon={showIcon}
showLabel={showLabel} showLabel={showLabel}
labelStyle={labelStyle} labelStyle={labelStyle}
iconStyle={iconStyle}
style={tabStyle} style={tabStyle}
/> />
</NavigationRouteContext.Provider> </NavigationRouteContext.Provider>

View File

@@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import { import {
View, View,
Text,
TouchableWithoutFeedback, TouchableWithoutFeedback,
Animated,
StyleSheet, StyleSheet,
Platform, Platform,
StyleProp, StyleProp,
@@ -14,7 +14,7 @@ import { Link, Route, useTheme } from '@react-navigation/native';
import Color from 'color'; import Color from 'color';
import TabBarIcon from './TabBarIcon'; import TabBarIcon from './TabBarIcon';
import { BottomTabBarButtonProps } from '../types'; import type { BottomTabBarButtonProps } from '../types';
type Props = { type Props = {
/** /**
@@ -90,10 +90,6 @@ type Props = {
* Whether to show the label text for the tab. * Whether to show the label text for the tab.
*/ */
showLabel?: boolean; showLabel?: boolean;
/**
* Whether to show the icon for the tab.
*/
showIcon?: boolean;
/** /**
* Whether to allow scaling the font for the label for accessibility purposes. * Whether to allow scaling the font for the label for accessibility purposes.
*/ */
@@ -102,6 +98,10 @@ type Props = {
* Style object for the label element. * Style object for the label element.
*/ */
labelStyle?: StyleProp<TextStyle>; labelStyle?: StyleProp<TextStyle>;
/**
* Style object for the icon element.
*/
iconStyle?: StyleProp<ViewStyle>;
/** /**
* Style object for the wrapper element. * Style object for the wrapper element.
*/ */
@@ -165,9 +165,9 @@ export default function BottomTabBarItem({
activeBackgroundColor = 'transparent', activeBackgroundColor = 'transparent',
inactiveBackgroundColor = 'transparent', inactiveBackgroundColor = 'transparent',
showLabel = true, showLabel = true,
showIcon = true,
allowFontScaling, allowFontScaling,
labelStyle, labelStyle,
iconStyle,
style, style,
}: Props) { }: Props) {
const { colors } = useTheme(); const { colors } = useTheme();
@@ -191,30 +191,26 @@ export default function BottomTabBarItem({
if (typeof label === 'string') { if (typeof label === 'string') {
return ( return (
<Animated.Text <Text
numberOfLines={1} numberOfLines={1}
style={[ style={[
styles.label, styles.label,
{ color }, { color },
showIcon && horizontal ? styles.labelBeside : styles.labelBeneath, horizontal ? styles.labelBeside : styles.labelBeneath,
labelStyle, labelStyle,
]} ]}
allowFontScaling={allowFontScaling} allowFontScaling={allowFontScaling}
> >
{label} {label}
</Animated.Text> </Text>
); );
} }
if (typeof label === 'string') {
return label;
}
return label({ focused, color }); return label({ focused, color });
}; };
const renderIcon = ({ focused }: { focused: boolean }) => { const renderIcon = ({ focused }: { focused: boolean }) => {
if (showIcon === false || icon === undefined) { if (icon === undefined) {
return null; return null;
} }
@@ -230,7 +226,10 @@ export default function BottomTabBarItem({
activeTintColor={activeTintColor} activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor} inactiveTintColor={inactiveTintColor}
renderIcon={icon} renderIcon={icon}
style={horizontal ? styles.iconHorizontal : styles.iconVertical} style={[
horizontal ? styles.iconHorizontal : styles.iconVertical,
iconStyle,
]}
/> />
); );
}; };

View File

@@ -12,7 +12,7 @@ import { ScreenContainer } from 'react-native-screens';
import SafeAreaProviderCompat from './SafeAreaProviderCompat'; import SafeAreaProviderCompat from './SafeAreaProviderCompat';
import ResourceSavingScene from './ResourceSavingScene'; import ResourceSavingScene from './ResourceSavingScene';
import BottomTabBar from './BottomTabBar'; import BottomTabBar from './BottomTabBar';
import { import type {
BottomTabNavigationConfig, BottomTabNavigationConfig,
BottomTabDescriptorMap, BottomTabDescriptorMap,
BottomTabNavigationHelpers, BottomTabNavigationHelpers,
@@ -75,17 +75,8 @@ export default class BottomTabView extends React.Component<Props, State> {
tabBarOptions, tabBarOptions,
state, state,
navigation, navigation,
descriptors,
} = this.props; } = this.props;
const { descriptors } = this.props;
const route = state.routes[state.index];
const descriptor = descriptors[route.key];
const options = descriptor.options;
if (options.tabBarVisible === false) {
return null;
}
return tabBar({ return tabBar({
...tabBarOptions, ...tabBarOptions,
state: state, state: state,

View File

@@ -17,7 +17,7 @@ export default class ResourceSavingScene extends React.Component<Props> {
if (screensEnabled?.() && Platform.OS !== 'web') { if (screensEnabled?.() && Platform.OS !== 'web') {
const { isVisible, ...rest } = this.props; const { isVisible, ...rest } = this.props;
// @ts-ignore // @ts-expect-error: stackPresentation is incorrectly marked as required
return <Screen active={isVisible ? 1 : 0} {...rest} />; return <Screen active={isVisible ? 1 : 0} {...rest} />;
} }

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native'; import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
import { Route } from '@react-navigation/native'; import type { Route } from '@react-navigation/native';
type Props = { type Props = {
route: Route<string>; route: Route<string>;

View File

@@ -3,7 +3,7 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.14...@react-navigation/compat@5.1.15) (2020-05-05) ## [5.1.28](https://github.com/react-navigation/react-navigation/compare/@react-navigation/compat@5.1.27...@react-navigation/compat@5.1.28) (2020-06-25)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -11,51 +11,18 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.13...@react-navigation/compat@5.1.14) (2020-05-01) ## [5.1.27](https://github.com/react-navigation/react-navigation/compare/@react-navigation/compat@5.1.26...@react-navigation/compat@5.1.27) (2020-06-24)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.13](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.12...@react-navigation/compat@5.1.13) (2020-05-01)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.12](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.11...@react-navigation/compat@5.1.12) (2020-04-30)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.11](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.10...@react-navigation/compat@5.1.11) (2020-04-30)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.9...@react-navigation/compat@5.1.10) (2020-04-27)
### Bug Fixes ### Bug Fixes
* fix typo in navigationOptions ([8cbb201](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/8cbb201f1a7fb90e45a078df6bc42ce4771cc6a6)) * more improvements to types ([d244488](https://github.com/react-navigation/react-navigation/commit/d2444887be227bbbdcfcb13a7f26a8ebb344043e))
* spread parent params to children in compat navigator ([24febf6](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/24febf6ea99be2e5f22005fdd2a82136d647255c)), closes [#6785](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/issues/6785)
## [5.1.9](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.8...@react-navigation/compat@5.1.9) (2020-04-17) ## [5.1.26](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.25...@react-navigation/compat@5.1.26) (2020-06-06)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -63,18 +30,82 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.8](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.7...@react-navigation/compat@5.1.8) (2020-04-08) ## [5.1.25](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.24...@react-navigation/compat@5.1.25) (2020-05-27)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.24](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.23...@react-navigation/compat@5.1.24) (2020-05-23)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.23](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.22...@react-navigation/compat@5.1.23) (2020-05-20)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.22](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.21...@react-navigation/compat@5.1.22) (2020-05-20)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.21](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.20...@react-navigation/compat@5.1.21) (2020-05-16)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.20](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.19...@react-navigation/compat@5.1.20) (2020-05-14)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.19](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.18...@react-navigation/compat@5.1.19) (2020-05-14)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.18](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.17...@react-navigation/compat@5.1.18) (2020-05-10)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.17](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.16...@react-navigation/compat@5.1.17) (2020-05-08)
### Bug Fixes ### Bug Fixes
* use 1 as default in compatibility pop action ([4408117](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/44081172d440c713ad3543a2d5e1e18ebc8f72a4)) * fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.6...@react-navigation/compat@5.1.7) (2020-03-30) ## [5.1.16](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.15...@react-navigation/compat@5.1.16) (2020-05-08)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -82,7 +113,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.5...@react-navigation/compat@5.1.6) (2020-03-23) ## [5.1.15](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.14...@react-navigation/compat@5.1.15) (2020-05-05)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -90,7 +121,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.4...@react-navigation/compat@5.1.5) (2020-03-22) ## [5.1.14](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.13...@react-navigation/compat@5.1.14) (2020-05-01)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -98,7 +129,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.3...@react-navigation/compat@5.1.4) (2020-03-19) ## [5.1.13](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.12...@react-navigation/compat@5.1.13) (2020-05-01)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -106,7 +137,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.2...@react-navigation/compat@5.1.3) (2020-03-17) ## [5.1.12](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.11...@react-navigation/compat@5.1.12) (2020-04-30)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -114,7 +145,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.1...@react-navigation/compat@5.1.2) (2020-03-16) ## [5.1.11](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.10...@react-navigation/compat@5.1.11) (2020-04-30)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -122,7 +153,19 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.0...@react-navigation/compat@5.1.1) (2020-03-03) ## [5.1.10](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.9...@react-navigation/compat@5.1.10) (2020-04-27)
### Bug Fixes
* fix typo in navigationOptions ([8cbb201](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/8cbb201f1a7fb90e45a078df6bc42ce4771cc6a6))
* spread parent params to children in compat navigator ([24febf6](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/24febf6ea99be2e5f22005fdd2a82136d647255c)), closes [#6785](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/issues/6785)
## [5.1.9](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.8...@react-navigation/compat@5.1.9) (2020-04-17)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -130,18 +173,85 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.7...@react-navigation/compat@5.1.0) (2020-02-26) ## [5.1.8](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.7...@react-navigation/compat@5.1.8) (2020-04-08)
### Bug Fixes
* use 1 as default in compatibility pop action ([4408117](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/44081172d440c713ad3543a2d5e1e18ebc8f72a4))
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.6...@react-navigation/compat@5.1.7) (2020-03-30)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.5...@react-navigation/compat@5.1.6) (2020-03-23)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.4...@react-navigation/compat@5.1.5) (2020-03-22)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.3...@react-navigation/compat@5.1.4) (2020-03-19)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.2...@react-navigation/compat@5.1.3) (2020-03-17)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.1...@react-navigation/compat@5.1.2) (2020-03-16)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.1.0...@react-navigation/compat@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/compat
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.7...@react-navigation/compat@5.1.0) (2020-02-26)
### Features ### Features
* add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/issues/6756) * add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/issues/6756)
## [5.0.7](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.6...@react-navigation/compat@5.0.7) (2020-02-21) ## [5.0.7](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.6...@react-navigation/compat@5.0.7) (2020-02-21)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -149,18 +259,18 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.6](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.5...@react-navigation/compat@5.0.6) (2020-02-19) ## [5.0.6](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.5...@react-navigation/compat@5.0.6) (2020-02-19)
### Bug Fixes ### Bug Fixes
* add NavigationEvents ([d69b0db](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/d69b0db60455b8789276822ba73f5349db8842d7)), closes [/github.com/react-navigation/react-navigation/issues/6821#issuecomment-588268512](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/issues/issuecomment-588268512) * add NavigationEvents ([d69b0db](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/d69b0db60455b8789276822ba73f5349db8842d7)), closes [/github.com/react-navigation/react-navigation/issues/6821#issuecomment-588268512](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/issues/issuecomment-588268512)
## [5.0.5](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.4...@react-navigation/compat@5.0.5) (2020-02-14) ## [5.0.5](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.4...@react-navigation/compat@5.0.5) (2020-02-14)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -168,7 +278,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.4](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.3...@react-navigation/compat@5.0.4) (2020-02-14) ## [5.0.4](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.3...@react-navigation/compat@5.0.4) (2020-02-14)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -176,7 +286,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.3](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.2...@react-navigation/compat@5.0.3) (2020-02-12) ## [5.0.3](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.2...@react-navigation/compat@5.0.3) (2020-02-12)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -184,7 +294,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.2](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.1...@react-navigation/compat@5.0.2) (2020-02-11) ## [5.0.2](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.1...@react-navigation/compat@5.0.2) (2020-02-11)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -192,7 +302,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.0.1](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.34...@react-navigation/compat@5.0.1) (2020-02-10) ## [5.0.1](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.34...@react-navigation/compat@5.0.1) (2020-02-10)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -200,7 +310,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.33...@react-navigation/compat@5.0.0-alpha.34) (2020-02-04) # [5.0.0-alpha.34](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.33...@react-navigation/compat@5.0.0-alpha.34) (2020-02-04)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -208,7 +318,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.32...@react-navigation/compat@5.0.0-alpha.33) (2020-02-04) # [5.0.0-alpha.33](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.32...@react-navigation/compat@5.0.0-alpha.33) (2020-02-04)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -216,7 +326,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.32](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.31...@react-navigation/compat@5.0.0-alpha.32) (2020-02-03) # [5.0.0-alpha.32](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.31...@react-navigation/compat@5.0.0-alpha.32) (2020-02-03)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -224,31 +334,31 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.31](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.31) (2020-02-02) # [5.0.0-alpha.31](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.31) (2020-02-02)
### Bug Fixes ### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f)) * add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf)) * throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf))
# [5.0.0-alpha.29](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.29) (2020-02-02) # [5.0.0-alpha.29](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.29) (2020-02-02)
### Bug Fixes ### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f)) * add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf)) * throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf))
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.27...@react-navigation/compat@5.0.0-alpha.28) (2020-01-24) # [5.0.0-alpha.28](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.27...@react-navigation/compat@5.0.0-alpha.28) (2020-01-24)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -256,19 +366,19 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.26...@react-navigation/compat@5.0.0-alpha.27) (2020-01-23) # [5.0.0-alpha.27](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.26...@react-navigation/compat@5.0.0-alpha.27) (2020-01-23)
### Bug Fixes ### Bug Fixes
* ensure re-render on isFirstRouteInParent change in compat layer ([14ae373](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/14ae3738cf46088e082bd1c60b9dcc6dacacd1bf)) * ensure re-render on isFirstRouteInParent change in compat layer ([14ae373](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/14ae3738cf46088e082bd1c60b9dcc6dacacd1bf))
* improvements to the compat layer ([2a76dc4](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/2a76dc4d3c4cc0365a3afcff6ac321145efed026)) * improvements to the compat layer ([2a76dc4](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/2a76dc4d3c4cc0365a3afcff6ac321145efed026))
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.25...@react-navigation/compat@5.0.0-alpha.26) (2020-01-14) # [5.0.0-alpha.26](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.25...@react-navigation/compat@5.0.0-alpha.26) (2020-01-14)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -276,18 +386,18 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.25](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.24...@react-navigation/compat@5.0.0-alpha.25) (2020-01-13) # [5.0.0-alpha.25](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.24...@react-navigation/compat@5.0.0-alpha.25) (2020-01-13)
### Bug Fixes ### Bug Fixes
* make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/issues/265) * make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/issues/265)
# [5.0.0-alpha.24](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.23...@react-navigation/compat@5.0.0-alpha.24) (2020-01-13) # [5.0.0-alpha.24](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.23...@react-navigation/compat@5.0.0-alpha.24) (2020-01-13)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -295,7 +405,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.23](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.21...@react-navigation/compat@5.0.0-alpha.23) (2020-01-09) # [5.0.0-alpha.23](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.21...@react-navigation/compat@5.0.0-alpha.23) (2020-01-09)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat
@@ -303,7 +413,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.22](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.21...@react-navigation/compat@5.0.0-alpha.22) (2020-01-09) # [5.0.0-alpha.22](https://github.com/react-navigation/react-navigation/tree/main/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.21...@react-navigation/compat@5.0.0-alpha.22) (2020-01-09)
**Note:** Version bump only for package @react-navigation/compat **Note:** Version bump only for package @react-navigation/compat

View File

@@ -1,20 +1,26 @@
{ {
"name": "@react-navigation/compat", "name": "@react-navigation/compat",
"description": "Compatibility layer to write navigator definitions in static configuration format", "description": "Compatibility layer to write navigator definitions in static configuration format",
"version": "5.1.15", "version": "5.1.28",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat", "repository": {
"type": "git",
"url": "https://github.com/react-navigation/react-navigation.git",
"directory": "packages/compat"
},
"bugs": { "bugs": {
"url": "https://github.com/react-navigation/react-navigation/issues" "url": "https://github.com/react-navigation/react-navigation/issues"
}, },
"homepage": "https://reactnavigation.org/docs/compatibility.html", "homepage": "https://reactnavigation.org/docs/compatibility.html",
"main": "lib/commonjs/index.js", "main": "lib/commonjs/index.js",
"react-native": "src/index.tsx", "react-native": "src/index.tsx",
"source": "src/index.tsx",
"module": "lib/module/index.js", "module": "lib/module/index.js",
"types": "lib/typescript/src/index.d.ts", "types": "lib/typescript/src/index.d.ts",
"files": [ "files": [
"src", "src",
"lib" "lib",
"!**/__tests__"
], ],
"sideEffects": false, "sideEffects": false,
"publishConfig": { "publishConfig": {
@@ -25,11 +31,11 @@
"clean": "del lib" "clean": "del lib"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.10.0", "@react-native-community/bob": "^0.15.1",
"@react-navigation/native": "^5.2.4", "@react-navigation/native": "^5.6.1",
"@types/react": "^16.9.23", "@types/react": "^16.9.36",
"react": "~16.9.0", "react": "~16.9.0",
"typescript": "^3.8.3" "typescript": "^3.9.5"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^5.0.5", "@react-navigation/native": "^5.0.5",

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { import type {
NavigationProp, NavigationProp,
ParamListBase, ParamListBase,
RouteProp, RouteProp,

View File

@@ -25,7 +25,7 @@ export default function NavigationEvents(props: Props) {
propsRef.current.onWillBlur?.(); propsRef.current.onWillBlur?.();
}); });
// @ts-ignore // @ts-expect-error: transitionEnd may not exist on this navigator
const unsubTransitionEnd = navigation.addListener('transitionEnd', () => { const unsubTransitionEnd = navigation.addListener('transitionEnd', () => {
if (navigation.isFocused()) { if (navigation.isFocused()) {
propsRef.current.onDidFocus?.(); propsRef.current.onDidFocus?.();

View File

@@ -1,4 +1,4 @@
import { import type {
NavigationState, NavigationState,
PartialState, PartialState,
ParamListBase, ParamListBase,
@@ -6,7 +6,7 @@ import {
RouteProp, RouteProp,
} from '@react-navigation/native'; } from '@react-navigation/native';
import * as helpers from './helpers'; import * as helpers from './helpers';
import { CompatNavigationProp } from './types'; import type { CompatNavigationProp } from './types';
type EventName = type EventName =
| 'action' | 'action'
@@ -16,10 +16,6 @@ type EventName =
| 'didBlur' | 'didBlur'
| 'refocus'; | 'refocus';
// const focusSubscriptions = new WeakMap<() => void, () => void>();
// const blurSubscriptions = new WeakMap<() => void, () => void>();
// const refocusSubscriptions = new WeakMap<() => void, () => void>();
export default function createCompatNavigationProp< export default function createCompatNavigationProp<
NavigationPropType extends NavigationProp<ParamListBase>, NavigationPropType extends NavigationProp<ParamListBase>,
ParamList extends ParamListBase = NavigationPropType extends NavigationProp< ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
@@ -74,7 +70,7 @@ export default function createCompatNavigationProp<
} }
}; };
// @ts-ignore // @ts-expect-error: this event may not exist in this navigator
unsubscribe = navigation.addListener('transitionEnd', listener); unsubscribe = navigation.addListener('transitionEnd', listener);
context.subscriptions.didFocus.set(callback, unsubscribe); context.subscriptions.didFocus.set(callback, unsubscribe);
break; break;
@@ -86,7 +82,7 @@ export default function createCompatNavigationProp<
} }
}; };
// @ts-ignore // @ts-expect-error: this event may not exist in this navigator
unsubscribe = navigation.addListener('transitionEnd', listener); unsubscribe = navigation.addListener('transitionEnd', listener);
context.subscriptions.didBlur.set(callback, unsubscribe); context.subscriptions.didBlur.set(callback, unsubscribe);
break; break;
@@ -98,7 +94,7 @@ export default function createCompatNavigationProp<
} }
}; };
// @ts-ignore // @ts-expect-error: this event may not exist in this navigator
unsubscribe = navigation.addListener('tabPress', listener); unsubscribe = navigation.addListener('tabPress', listener);
context.subscriptions.refocus.set(callback, unsubscribe); context.subscriptions.refocus.set(callback, unsubscribe);
break; break;
@@ -106,7 +102,6 @@ export default function createCompatNavigationProp<
case 'action': case 'action':
throw new Error("Listening to 'action' events is not supported."); throw new Error("Listening to 'action' events is not supported.");
default: default:
// @ts-ignore
unsubscribe = navigation.addListener(type, callback); unsubscribe = navigation.addListener(type, callback);
} }
@@ -144,18 +139,17 @@ export default function createCompatNavigationProp<
case 'action': case 'action':
throw new Error("Listening to 'action' events is not supported."); throw new Error("Listening to 'action' events is not supported.");
default: default:
// @ts-ignore
navigation.removeListener(type, callback); navigation.removeListener(type, callback);
} }
}, },
state: { state: {
...state, ...state,
// @ts-ignore // @ts-expect-error
routeName: state.name, routeName: state.name,
get index() { get index() {
// @ts-ignore // @ts-expect-error
if (state.index !== undefined) { if (state.index !== undefined) {
// @ts-ignore // @ts-expect-error
return state.index; return state.index;
} }
@@ -163,13 +157,13 @@ export default function createCompatNavigationProp<
"Accessing child navigation state for a route is not safe and won't work correctly." "Accessing child navigation state for a route is not safe and won't work correctly."
); );
// @ts-ignore // @ts-expect-error
return state.state ? state.state.index : undefined; return state.state ? state.state.index : undefined;
}, },
get routes() { get routes() {
// @ts-ignore // @ts-expect-error
if (state.routes !== undefined) { if (state.routes !== undefined) {
// @ts-ignore // @ts-expect-error
return state.routes; return state.routes;
} }
@@ -177,7 +171,7 @@ export default function createCompatNavigationProp<
"Accessing child navigation state for a route is not safe and won't work correctly." "Accessing child navigation state for a route is not safe and won't work correctly."
); );
// @ts-ignore // @ts-expect-error
return state.state ? state.state.routes : undefined; return state.state ? state.state.routes : undefined;
}, },
}, },
@@ -185,7 +179,7 @@ export default function createCompatNavigationProp<
paramName: T, paramName: T,
defaultValue: ParamList[T] defaultValue: ParamList[T]
): ParamList[T] { ): ParamList[T] {
// @ts-ignore // @ts-expect-error
const params = state.params; const params = state.params;
if (params && paramName in params) { if (params && paramName in params) {
@@ -201,7 +195,7 @@ export default function createCompatNavigationProp<
const { routes } = navigation.dangerouslyGetState(); const { routes } = navigation.dangerouslyGetState();
// @ts-ignore // @ts-expect-error
return routes[0].key === state.key; return routes[0].key === state.key;
}, },
dangerouslyGetParent() { dangerouslyGetParent() {

View File

@@ -6,24 +6,23 @@ import {
TypedNavigator, TypedNavigator,
NavigationProp, NavigationProp,
RouteProp, RouteProp,
EventMapBase,
NavigationRouteContext, NavigationRouteContext,
} from '@react-navigation/native'; } from '@react-navigation/native';
import CompatScreen from './CompatScreen'; import CompatScreen from './CompatScreen';
import ScreenPropsContext from './ScreenPropsContext'; import ScreenPropsContext from './ScreenPropsContext';
import createCompatNavigationProp from './createCompatNavigationProp'; import createCompatNavigationProp from './createCompatNavigationProp';
import { CompatScreenType, CompatRouteConfig } from './types'; import type { CompatScreenType, CompatRouteConfig } from './types';
export default function createCompatNavigatorFactory< export default function createCompatNavigatorFactory<
CreateNavigator extends () => TypedNavigator< CreateNavigator extends () => TypedNavigator<
ParamListBase, ParamListBase,
NavigationState, NavigationState,
{}, {},
EventMapBase, any,
React.ComponentType<any> React.ComponentType<any>
> >
>(createNavigator: CreateNavigator) { >(createNavigator: CreateNavigator) {
// @ts-ignore // @ts-expect-error: isCompat may or may not exist
if (createNavigator.isCompat) { if (createNavigator.isCompat) {
throw new Error( throw new Error(
`The navigator is already in compat mode. You don't need to wrap it in 'createCompatNavigatorFactory'.` `The navigator is already in compat mode. You don't need to wrap it in 'createCompatNavigatorFactory'.`
@@ -99,7 +98,7 @@ export default function createCompatNavigatorFactory<
state?: NavigationState | PartialState<NavigationState>; state?: NavigationState | PartialState<NavigationState>;
}; };
}) => { }) => {
// @ts-ignore // @ts-expect-error: navigationOptions may exists on the component, but TS is dumb
const routeNavigationOptions = routeConfigItem.navigationOptions; const routeNavigationOptions = routeConfigItem.navigationOptions;
const screenNavigationOptions = getScreenComponent() const screenNavigationOptions = getScreenComponent()
.navigationOptions; .navigationOptions;
@@ -116,7 +115,8 @@ export default function createCompatNavigatorFactory<
typeof screenNavigationOptions === 'function' typeof screenNavigationOptions === 'function'
? { ? {
navigation: createCompatNavigationProp< navigation: createCompatNavigationProp<
NavigationPropType NavigationPropType,
ParamList
>(navigation, route, {}), >(navigation, route, {}),
navigationOptions: defaultNavigationOptions || {}, navigationOptions: defaultNavigationOptions || {},
screenProps, screenProps,

View File

@@ -1,5 +1,9 @@
import { ParamListBase, NavigationProp, Route } from '@react-navigation/native'; import type {
import * as helpers from './helpers'; ParamListBase,
NavigationProp,
Route,
} from '@react-navigation/native';
import type * as helpers from './helpers';
export type CompatNavigationProp< export type CompatNavigationProp<
NavigationPropType extends NavigationProp<ParamListBase>, NavigationPropType extends NavigationProp<ParamListBase>,

View File

@@ -7,7 +7,7 @@ import {
useNavigationState, useNavigationState,
} from '@react-navigation/native'; } from '@react-navigation/native';
import createCompatNavigationProp from './createCompatNavigationProp'; import createCompatNavigationProp from './createCompatNavigationProp';
import { CompatNavigationProp } from './types'; import type { CompatNavigationProp } from './types';
export default function useCompatNavigation< export default function useCompatNavigation<
T extends NavigationProp<ParamListBase> T extends NavigationProp<ParamListBase>

View File

@@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { NavigationProp, ParamListBase } from '@react-navigation/native'; import type { NavigationProp, ParamListBase } from '@react-navigation/native';
import useCompatNavigation from './useCompatNavigation'; import useCompatNavigation from './useCompatNavigation';
import { CompatNavigationProp } from './types'; import type { CompatNavigationProp } from './types';
type InjectedProps<T extends NavigationProp<ParamListBase>> = { type InjectedProps<T extends NavigationProp<ParamListBase>> = {
navigation: CompatNavigationProp<T>; navigation: CompatNavigationProp<T>;
@@ -22,7 +22,7 @@ export default function withNavigation<
}): React.ReactElement => { }): React.ReactElement => {
const navigation = useCompatNavigation<T>(); const navigation = useCompatNavigation<T>();
// @ts-ignore // @ts-expect-error: type checking HOC is hard
return <Comp ref={onRef} navigation={navigation} {...rest} />; return <Comp ref={onRef} navigation={navigation} {...rest} />;
}; };

View File

@@ -19,7 +19,7 @@ export default function withNavigationFocus<
}): React.ReactElement => { }): React.ReactElement => {
const isFocused = useIsFocused(); const isFocused = useIsFocused();
// @ts-ignore // @ts-expect-error: type checking HOC is hard
return <Comp ref={onRef} isFocused={isFocused} {...rest} />; return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
}; };

View File

@@ -3,111 +3,69 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [5.5.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.4.0...@react-navigation/core@5.5.0) (2020-05-05) ## [5.11.1](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@5.11.0...@react-navigation/core@5.11.1) (2020-06-25)
### Bug Fixes
* fix error with type definitions. closes [#8511](https://github.com/react-navigation/react-navigation/issues/8511) ([d1210a8](https://github.com/react-navigation/react-navigation/commit/d1210a861b37201827c333a5c012c4f0ebd9bb6a))
# [5.11.0](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@5.10.0...@react-navigation/core@5.11.0) (2020-06-24)
### Bug Fixes
* fix getCurrentOptions for nested screens ([6730690](https://github.com/react-navigation/react-navigation/commit/67306905299314bda053e553ded228374e3e23c9))
* fix getCurrentOptions for nested screens ([afc83ee](https://github.com/react-navigation/react-navigation/commit/afc83eedf8c308c958a08900e069948e3d8a6aa1))
* more improvements to types ([d244488](https://github.com/react-navigation/react-navigation/commit/d2444887be227bbbdcfcb13a7f26a8ebb344043e))
### Features ### Features
* add support for optional params to linking ([#8196](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8196)) ([fcd1cc6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/fcd1cc64c151e4941f3f544a54b5048d853821f6)) * add devtools package ([#8436](https://github.com/react-navigation/react-navigation/issues/8436)) ([95b044e](https://github.com/react-navigation/react-navigation/commit/95b044ecf95939f40ced4da740a365140b3952b7))
* support params anywhere in path segement ([#8184](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8184)) ([3999fc2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3999fc28365c3a06a17d963c7be7fb7e897f99e0)) * add event for options on container ([#8334](https://github.com/react-navigation/react-navigation/issues/8334)) ([fe3f98e](https://github.com/react-navigation/react-navigation/commit/fe3f98eb9cdd986c32460b78520b4d3d2435c279))
* add helper to get focused route name from nested state ([#8435](https://github.com/react-navigation/react-navigation/issues/8435)) ([f51f9c8](https://github.com/react-navigation/react-navigation/commit/f51f9c8493e079f73688adaf9dc43a2171c3e44a))
* rework linking configuration to be more strict ([#8502](https://github.com/react-navigation/react-navigation/issues/8502)) ([a021cfb](https://github.com/react-navigation/react-navigation/commit/a021cfb8af4afd50f785f6ee9b51d361e25704ca))
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.5...@react-navigation/core@5.4.0) (2020-04-30) # [5.10.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.9.0...@react-navigation/core@5.10.0) (2020-06-06)
### Bug Fixes ### Bug Fixes
* handle empty paths when parsing ([c3fa83e](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/c3fa83efe0d73db76365f8be3d6a8ca1d1289b71)) * catch missing params when they are required in navigate ([#8389](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8389)) ([8774ca9](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/8774ca97e1da91e97677ecd816c85f66af296b93))
* parsing url ([bd35b4f](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/bd35b4fc202c3868fb75c3675b62de67557089e1)) * make sure the wildcard pattern catches nested unmatched routes ([c3bd349](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/c3bd349d77688011c9c55027edd66c6f39de2ade))
* only use the query params for focused route in path ([2d66ef9](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2d66ef93ec9923a452415c482c40e7c6b769917c))
* prevent state change being emitted unnecessarily ([ab1f79c](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ab1f79c096e94475a4da1acf1c850d04fb1bc4cf))
### Features ### Features
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/2792f438fe45428fe193e3708fee7ad61966cbf4)) * add wildcard patterns for paths ([4fe72e3](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/4fe72e3ce7bae9120d04e490401f3bad58ebdf5c)), closes [#8019](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8019)
## [5.3.5](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.4...@react-navigation/core@5.3.5) (2020-04-27) # [5.9.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.8.2...@react-navigation/core@5.9.0) (2020-05-27)
### Bug Fixes
* add config to enable redux devtools integration ([c9c825b](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/c9c825bee61426635a28ee149eeeff3d628171cd))
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.3...@react-navigation/core@5.3.4) (2020-04-17)
### Bug Fixes
* add initial option for navigating to nested navigators ([004c7d7](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/004c7d7ab1f80faf04b2a1836ec6b79a5419e45f))
* add initial param for actions from deep link ([a3f7a5f](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/a3f7a5feba2e6aa2158aeaea6cde73ae1603173e))
* handle initial: false for nested route after first initialization ([187aefe](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/187aefe9c400b499f920c212bf856414e25c5aaf))
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.2...@react-navigation/core@5.3.3) (2020-04-08)
### Bug Fixes
* switch order of focus and blur events. closes [#7963](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/7963) ([ce3994c](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/ce3994c82c28669d5742017eb7627e9adf996933))
* workaround warning about setState in another component in render ([d4fd906](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/d4fd906915cc20d6fb21508384c05a540d8644d8))
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.1...@react-navigation/core@5.3.2) (2020-03-30)
### Bug Fixes
* handle no path property and undefined query params ([#7911](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/7911)) ([cd47915](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/cd47915861a56cd7eaa9ac79f5139cde56ca95a7))
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.0...@react-navigation/core@5.3.1) (2020-03-23)
### Bug Fixes
* don't emit events for screens that don't exist anymore ([1c00142](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/1c001424b595b40f9db9343096c833f75353b099))
* only call listeners for focused screen for global events ([3096de6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3096de62868a7ed9ed65e529c8ddfa001b9be486))
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.3...@react-navigation/core@5.3.0) (2020-03-22)
### Bug Fixes
* return correct value for isFocused after changing screens ([5b15c71](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/5b15c7164f5503f2f0d51006a3f23bd0c58fd9b7)), closes [#7843](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/7843)
### Features ### Features
* support function in listeners prop ([3709e65](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3709e652f41a16c2c2b05d5dbbe1da2017ba2c3f)) * add ref to get current options in `ServerContainer` ([#8333](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8333)) ([0b1a718](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/0b1a718756e208d84b20e45ca56004332308ad54))
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.2...@react-navigation/core@5.2.3) (2020-03-19) ## [5.8.2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.8.1...@react-navigation/core@5.8.2) (2020-05-23)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core
@@ -115,7 +73,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.1...@react-navigation/core@5.2.2) (2020-03-16) ## [5.8.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.8.0...@react-navigation/core@5.8.1) (2020-05-20)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core
@@ -123,133 +81,189 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.0...@react-navigation/core@5.2.1) (2020-03-03) # [5.8.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.7.0...@react-navigation/core@5.8.0) (2020-05-20)
### Bug Fixes
* fix links for documentation ([5bb0f40](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/5bb0f405ceb5755d39a0b5b1f2e4ecee0da051bc))
* move updating state to useEffect ([2dfa4f3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/2dfa4f36293a2acb718814f6b2fa79d7c7ddf09c))
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.6...@react-navigation/core@5.2.0) (2020-02-26)
### Features ### Features
* add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/6756) * add getCurrentOptions ([#8277](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8277)) ([d024ec6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/d024ec6d74dffe481ce6fde732c729e20c1668f4))
* add getCurrentRoute ([#8254](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8254)) ([7b25c8e](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/7b25c8eb2e6f96128fd86b92615346ce55bedeca))
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.5...@react-navigation/core@5.1.6) (2020-02-21) # [5.7.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.6.1...@react-navigation/core@5.7.0) (2020-05-16)
### Bug Fixes ### Bug Fixes
* avoid emitting focus events twice ([f167008](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/f16700812f3757713b04ca3a860209795b4a6c44)), closes [#6749](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/6749) * don't use Object.fromEntries ([51f4d11](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/51f4d11fdf4bd2bb06f8cd4094f051816590e62c))
* preserve screen order with numeric names ([125bd70](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/125bd70e49b708d936a2eee72ba5cb92eacf26a9)), closes [#6900](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/6900)
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.4...@react-navigation/core@5.1.5) (2020-02-19)
### Bug Fixes
* show descriptive error for invalid return for useFocusEffect ([1a28c29](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/1a28c299b5e3f0805eb6e9ea3cf5e9cc90c7a280))
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.3...@react-navigation/core@5.1.4) (2020-02-14)
### Bug Fixes
* link to migration guide on invalid usage ([c5fcfbd](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/c5fcfbd4277541e131acbaa7602a5d7e636afebb))
* return '/' for empty paths ([aaf01e0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/aaf01e01e7b47b375f68aebe6d0effe82878d060))
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.2...@react-navigation/core@5.1.3) (2020-02-14)
### Bug Fixes
* return false for canGoBack if navigator hasn't finished mounting ([c8ac5fa](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/c8ac5fab61cf127985431075a3c59c1f3dfa42da))
* throw a descriptive error if navigation object hasn't initialized ([b6accd0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/b6accd03f69dd438e595094d8bf8599cc12e71ac))
* update links in error messages ([f964200](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/f964200b0dcbc19d5f88ad2dd1eb8e5576973497))
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.1...@react-navigation/core@5.1.2) (2020-02-12)
### Bug Fixes
* fix false positives for circular object check ([030c63c](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/030c63c89fe447aa484b767831c8f8e26e90431c)), closes [#6827](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/6827)
* static container memo check ([#6825](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/6825)) ([2bf0958](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/2bf09585021470f500d967e9242836840efe970f))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.0...@react-navigation/core@5.1.1) (2020-02-11)
### Bug Fixes
* don't cleanup state on switching navigator ([359ae1b](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/359ae1bfacec5ef880b3944f465c881aedb16767))
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.43...@react-navigation/core@5.1.0) (2020-02-10)
### Bug Fixes
* add some links in the error messages ([13b4e07](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/13b4e07348496f7cb516d625b44a6a7d310ef9af))
### Features ### Features
* support ignoring empty path strings ([#349](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/349)) ([61b1134](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/61b1134f90310390fe819622c1f33273fca0bd42)) * add a PathConfig type ([60cb3c9](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/60cb3c9ba76d7ef166c9fe8b55f23728975b5b6e))
# [5.0.0-alpha.43](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.42...@react-navigation/core@5.0.0-alpha.43) (2020-02-04) ## [5.6.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.6.0...@react-navigation/core@5.6.1) (2020-05-14)
### Bug Fixes ### Bug Fixes
* improve error message for unhandled action ([ca4a360](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ca4a36070a21c4fe86cb1cc55a4452dca293f215)) * don't use flat since it's not supported in node ([21b397f](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/21b397f0d6b96ec4875d3172f47533130bb08009))
# [5.6.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.5.2...@react-navigation/core@5.6.0) (2020-05-14)
### Bug Fixes
* ignore extra slashes in the pattern ([3c47716](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/3c47716826d0dfa69dfa6112141c116723372ea1))
* ignore state updates when we're not mounted ([0149e85](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/0149e85a95b90c6a9d487fa753ddbf5d01c03e3d)), closes [#8226](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8226)
### Features ### Features
* add initialRouteName property to config ([#322](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/322)) ([4ca5cc6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/4ca5cc632992187f12870281e4cf4c7d1f799967)) * merge path patterns for nested screens ([#8253](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8253)) ([acc9646](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/acc9646426fee53558d686dfbe5fd0e35361d8c0))
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.41...@react-navigation/core@5.0.0-alpha.42) (2020-02-04) ## [5.5.2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.5.1...@react-navigation/core@5.5.2) (2020-05-08)
### Bug Fixes
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
## [5.5.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.5.0...@react-navigation/core@5.5.1) (2020-05-08)
### Bug Fixes
* avoid cleaning up state when a new navigator is mounted. fixes [#8195](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8195) ([f6d0676](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/f6d06768d3c36d1f5beaffcb660f3c259209f2e7))
# [5.5.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.4.0...@react-navigation/core@5.5.0) (2020-05-05)
### Features
* add support for optional params to linking ([#8196](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8196)) ([fcd1cc6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/fcd1cc64c151e4941f3f544a54b5048d853821f6))
* support params anywhere in path segement ([#8184](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/8184)) ([3999fc2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/3999fc28365c3a06a17d963c7be7fb7e897f99e0))
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.5...@react-navigation/core@5.4.0) (2020-04-30)
### Bug Fixes
* handle empty paths when parsing ([c3fa83e](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/c3fa83efe0d73db76365f8be3d6a8ca1d1289b71))
* parsing url ([bd35b4f](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/bd35b4fc202c3868fb75c3675b62de67557089e1))
### Features
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
## [5.3.5](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.4...@react-navigation/core@5.3.5) (2020-04-27)
### Bug Fixes
* add config to enable redux devtools integration ([c9c825b](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/c9c825bee61426635a28ee149eeeff3d628171cd))
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.3...@react-navigation/core@5.3.4) (2020-04-17)
### Bug Fixes
* add initial option for navigating to nested navigators ([004c7d7](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/004c7d7ab1f80faf04b2a1836ec6b79a5419e45f))
* add initial param for actions from deep link ([a3f7a5f](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/a3f7a5feba2e6aa2158aeaea6cde73ae1603173e))
* handle initial: false for nested route after first initialization ([187aefe](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/187aefe9c400b499f920c212bf856414e25c5aaf))
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.2...@react-navigation/core@5.3.3) (2020-04-08)
### Bug Fixes
* switch order of focus and blur events. closes [#7963](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/7963) ([ce3994c](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ce3994c82c28669d5742017eb7627e9adf996933))
* workaround warning about setState in another component in render ([d4fd906](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/d4fd906915cc20d6fb21508384c05a540d8644d8))
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.1...@react-navigation/core@5.3.2) (2020-03-30)
### Bug Fixes
* handle no path property and undefined query params ([#7911](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/7911)) ([cd47915](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/cd47915861a56cd7eaa9ac79f5139cde56ca95a7))
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.3.0...@react-navigation/core@5.3.1) (2020-03-23)
### Bug Fixes
* don't emit events for screens that don't exist anymore ([1c00142](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/1c001424b595b40f9db9343096c833f75353b099))
* only call listeners for focused screen for global events ([3096de6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/3096de62868a7ed9ed65e529c8ddfa001b9be486))
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.2.3...@react-navigation/core@5.3.0) (2020-03-22)
### Bug Fixes
* return correct value for isFocused after changing screens ([5b15c71](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/5b15c7164f5503f2f0d51006a3f23bd0c58fd9b7)), closes [#7843](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/7843)
### Features
* support function in listeners prop ([3709e65](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/3709e652f41a16c2c2b05d5dbbe1da2017ba2c3f))
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.2.2...@react-navigation/core@5.2.3) (2020-03-19)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core
@@ -257,115 +271,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.40...@react-navigation/core@5.0.0-alpha.41) (2020-02-03) ## [5.2.2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.2.1...@react-navigation/core@5.2.2) (2020-03-16)
### Bug Fixes
* ignore circular references when checking serializable ([e5063b9](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/e5063b93398350511f3fd2ef48425559f871781f))
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.40) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
### Features
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.38) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
### Features
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
# [5.0.0-alpha.37](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.36...@react-navigation/core@5.0.0-alpha.37) (2020-01-24)
### Bug Fixes
* add error message when trying to use v4 API with v5 ([179e807](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/179e807a64a7d031d671c2c4b12edaee3c3440c5))
* validate screen configs ([2f1f0af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2f1f0af862ef8625da4c2aaf463d45fe17a4ac88))
* warn if non-serializable values found in state ([5751e7f](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5751e7f97a1731a5c71862174dfd931b6ffe13e2))
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.35...@react-navigation/core@5.0.0-alpha.36) (2020-01-23)
### Bug Fixes
* disallow canPreventDefault option if not present in types ([d9059b5](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/d9059b56d8a89b39fec43d38a7b0514d41c0b550))
* don't add ?if query params is empty ([3bf5ddd](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/3bf5ddde2ac1ba45f1123752d37532175f18a3d9))
* fix types for useFocusEffect ([23ab45a](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/23ab45aceb72cc27ebfacdedfbf60d0c540fecfb)), closes [#270](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/270)
* make sure that we return correct value if selector changes ([6c2acbb](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/6c2acbb304a9f11789b45a410b6c41911eca3947)), closes [/github.com/react-navigation/navigation-ex/pull/273#issuecomment-576581225](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/issuecomment-576581225)
* use protected for private value store ([ad4eaff](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ad4eaff1e99e4f9fca3a193764fd0f26efa41341))
### Features
* add useNavigationState hook ([32a2206](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/32a2206513bc084d8da07187385d11db498f1e2a))
* let the navigator specify if default can be prevented ([da67e13](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/da67e134d2157201360427d3c10da24f24cae7aa))
* support nested config in getPathFromState ([#266](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/266)) ([1e53821](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/1e53821d52be182369add07a86c72221c5dba53e))
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.34...@react-navigation/core@5.0.0-alpha.35) (2020-01-14)
### Bug Fixes
* fix intellisense for CompositeNavigationProp ([a912323](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/a912323c1dfa0c3564ca82c448a86f85d1658f7f))
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.33...@react-navigation/core@5.0.0-alpha.34) (2020-01-13)
### Bug Fixes
* make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/265)
# [5.0.0-alpha.33](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.32...@react-navigation/core@5.0.0-alpha.33) (2020-01-13)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core
@@ -373,7 +279,133 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.32](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.30...@react-navigation/core@5.0.0-alpha.32) (2020-01-09) ## [5.2.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.2.0...@react-navigation/core@5.2.1) (2020-03-03)
### Bug Fixes
* fix links for documentation ([5bb0f40](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/5bb0f405ceb5755d39a0b5b1f2e4ecee0da051bc))
* move updating state to useEffect ([2dfa4f3](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2dfa4f36293a2acb718814f6b2fa79d7c7ddf09c))
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.6...@react-navigation/core@5.2.0) (2020-02-26)
### Features
* add ability add listeners with listeners prop ([1624108](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/162410843c4f175ae107756de1c3af04d1d47aa7)), closes [#6756](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/6756)
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.5...@react-navigation/core@5.1.6) (2020-02-21)
### Bug Fixes
* avoid emitting focus events twice ([f167008](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/f16700812f3757713b04ca3a860209795b4a6c44)), closes [#6749](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/6749)
* preserve screen order with numeric names ([125bd70](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/125bd70e49b708d936a2eee72ba5cb92eacf26a9)), closes [#6900](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/6900)
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.4...@react-navigation/core@5.1.5) (2020-02-19)
### Bug Fixes
* show descriptive error for invalid return for useFocusEffect ([1a28c29](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/1a28c299b5e3f0805eb6e9ea3cf5e9cc90c7a280))
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.3...@react-navigation/core@5.1.4) (2020-02-14)
### Bug Fixes
* link to migration guide on invalid usage ([c5fcfbd](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/c5fcfbd4277541e131acbaa7602a5d7e636afebb))
* return '/' for empty paths ([aaf01e0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/aaf01e01e7b47b375f68aebe6d0effe82878d060))
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.2...@react-navigation/core@5.1.3) (2020-02-14)
### Bug Fixes
* return false for canGoBack if navigator hasn't finished mounting ([c8ac5fa](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/c8ac5fab61cf127985431075a3c59c1f3dfa42da))
* throw a descriptive error if navigation object hasn't initialized ([b6accd0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/b6accd03f69dd438e595094d8bf8599cc12e71ac))
* update links in error messages ([f964200](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/f964200b0dcbc19d5f88ad2dd1eb8e5576973497))
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.1...@react-navigation/core@5.1.2) (2020-02-12)
### Bug Fixes
* fix false positives for circular object check ([030c63c](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/030c63c89fe447aa484b767831c8f8e26e90431c)), closes [#6827](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/6827)
* static container memo check ([#6825](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/6825)) ([2bf0958](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2bf09585021470f500d967e9242836840efe970f))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.1.0...@react-navigation/core@5.1.1) (2020-02-11)
### Bug Fixes
* don't cleanup state on switching navigator ([359ae1b](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/359ae1bfacec5ef880b3944f465c881aedb16767))
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.43...@react-navigation/core@5.1.0) (2020-02-10)
### Bug Fixes
* add some links in the error messages ([13b4e07](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/13b4e07348496f7cb516d625b44a6a7d310ef9af))
### Features
* support ignoring empty path strings ([#349](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/349)) ([61b1134](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/61b1134f90310390fe819622c1f33273fca0bd42))
# [5.0.0-alpha.43](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.42...@react-navigation/core@5.0.0-alpha.43) (2020-02-04)
### Bug Fixes
* improve error message for unhandled action ([ca4a360](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ca4a36070a21c4fe86cb1cc55a4452dca293f215))
### Features
* add initialRouteName property to config ([#322](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/322)) ([4ca5cc6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/4ca5cc632992187f12870281e4cf4c7d1f799967))
# [5.0.0-alpha.42](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.41...@react-navigation/core@5.0.0-alpha.42) (2020-02-04)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core
@@ -381,7 +413,131 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
# [5.0.0-alpha.31](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.30...@react-navigation/core@5.0.0-alpha.31) (2020-01-09) # [5.0.0-alpha.41](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.40...@react-navigation/core@5.0.0-alpha.41) (2020-02-03)
### Bug Fixes
* ignore circular references when checking serializable ([e5063b9](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/e5063b93398350511f3fd2ef48425559f871781f))
# [5.0.0-alpha.40](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.40) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
### Features
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
# [5.0.0-alpha.38](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.38) (2020-02-02)
### Bug Fixes
* add licenses ([0c159db](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
### Features
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
# [5.0.0-alpha.37](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.36...@react-navigation/core@5.0.0-alpha.37) (2020-01-24)
### Bug Fixes
* add error message when trying to use v4 API with v5 ([179e807](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/179e807a64a7d031d671c2c4b12edaee3c3440c5))
* validate screen configs ([2f1f0af](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/2f1f0af862ef8625da4c2aaf463d45fe17a4ac88))
* warn if non-serializable values found in state ([5751e7f](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/5751e7f97a1731a5c71862174dfd931b6ffe13e2))
# [5.0.0-alpha.36](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.35...@react-navigation/core@5.0.0-alpha.36) (2020-01-23)
### Bug Fixes
* disallow canPreventDefault option if not present in types ([d9059b5](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/d9059b56d8a89b39fec43d38a7b0514d41c0b550))
* don't add ?if query params is empty ([3bf5ddd](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/3bf5ddde2ac1ba45f1123752d37532175f18a3d9))
* fix types for useFocusEffect ([23ab45a](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/23ab45aceb72cc27ebfacdedfbf60d0c540fecfb)), closes [#270](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/270)
* make sure that we return correct value if selector changes ([6c2acbb](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/6c2acbb304a9f11789b45a410b6c41911eca3947)), closes [/github.com/react-navigation/navigation-ex/pull/273#issuecomment-576581225](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/issuecomment-576581225)
* use protected for private value store ([ad4eaff](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/ad4eaff1e99e4f9fca3a193764fd0f26efa41341))
### Features
* add useNavigationState hook ([32a2206](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/32a2206513bc084d8da07187385d11db498f1e2a))
* let the navigator specify if default can be prevented ([da67e13](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/da67e134d2157201360427d3c10da24f24cae7aa))
* support nested config in getPathFromState ([#266](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/266)) ([1e53821](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/1e53821d52be182369add07a86c72221c5dba53e))
# [5.0.0-alpha.35](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.34...@react-navigation/core@5.0.0-alpha.35) (2020-01-14)
### Bug Fixes
* fix intellisense for CompositeNavigationProp ([a912323](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/a912323c1dfa0c3564ca82c448a86f85d1658f7f))
# [5.0.0-alpha.34](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.33...@react-navigation/core@5.0.0-alpha.34) (2020-01-13)
### Bug Fixes
* make sure paths aren't aliased when building definitions ([65a5dac](https://github.com/react-navigation/react-navigation/tree/main/packages/core/commit/65a5dac2bf887f4ba081ab15bd4c9870bb15697f)), closes [#265](https://github.com/react-navigation/react-navigation/tree/main/packages/core/issues/265)
# [5.0.0-alpha.33](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.32...@react-navigation/core@5.0.0-alpha.33) (2020-01-13)
**Note:** Version bump only for package @react-navigation/core
# [5.0.0-alpha.32](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.30...@react-navigation/core@5.0.0-alpha.32) (2020-01-09)
**Note:** Version bump only for package @react-navigation/core
# [5.0.0-alpha.31](https://github.com/react-navigation/react-navigation/tree/main/packages/core/compare/@react-navigation/core@5.0.0-alpha.30...@react-navigation/core@5.0.0-alpha.31) (2020-01-09)
**Note:** Version bump only for package @react-navigation/core **Note:** Version bump only for package @react-navigation/core

View File

@@ -1,25 +1,31 @@
{ {
"name": "@react-navigation/core", "name": "@react-navigation/core",
"description": "Core utilities for building navigators", "description": "Core utilities for building navigators",
"version": "5.5.0", "version": "5.11.1",
"keywords": [ "keywords": [
"react", "react",
"react-native", "react-native",
"react-navigation" "react-navigation"
], ],
"license": "MIT", "license": "MIT",
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/core", "repository": {
"type": "git",
"url": "https://github.com/react-navigation/react-navigation.git",
"directory": "packages/core"
},
"bugs": { "bugs": {
"url": "https://github.com/react-navigation/react-navigation/issues" "url": "https://github.com/react-navigation/react-navigation/issues"
}, },
"homepage": "https://reactnavigation.org", "homepage": "https://reactnavigation.org",
"main": "lib/commonjs/index.js", "main": "lib/commonjs/index.js",
"react-native": "src/index.tsx", "react-native": "src/index.tsx",
"source": "src/index.tsx",
"module": "lib/module/index.js", "module": "lib/module/index.js",
"types": "lib/typescript/src/index.d.ts", "types": "lib/typescript/src/index.d.ts",
"files": [ "files": [
"src", "src",
"lib" "lib",
"!**/__tests__"
], ],
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
@@ -29,23 +35,23 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/routers": "^5.4.2", "@react-navigation/routers": "^5.4.8",
"escape-string-regexp": "^2.0.0", "escape-string-regexp": "^4.0.0",
"nanoid": "^3.0.2", "nanoid": "^3.1.9",
"query-string": "^6.12.0", "query-string": "^6.13.1",
"react-is": "^16.13.0", "react-is": "^16.13.0",
"use-subscription": "^1.4.0" "use-subscription": "^1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.10.0", "@react-native-community/bob": "^0.15.1",
"@types/react": "^16.9.23", "@types/react": "^16.9.36",
"@types/react-is": "^16.7.1", "@types/react-is": "^16.7.1",
"@types/use-subscription": "^1.0.0", "@types/use-subscription": "^1.0.0",
"del-cli": "^3.0.0", "del-cli": "^3.0.1",
"react": "~16.9.0", "react": "~16.9.0",
"react-native-testing-library": "^1.12.0", "react-native-testing-library": "^2.1.0",
"react-test-renderer": "~16.13.1", "react-test-renderer": "~16.13.1",
"typescript": "^3.8.3" "typescript": "^3.9.5"
}, },
"peerDependencies": { "peerDependencies": {
"react": "*" "react": "*"

View File

@@ -9,55 +9,43 @@ import {
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import EnsureSingleNavigator from './EnsureSingleNavigator'; import EnsureSingleNavigator from './EnsureSingleNavigator';
import NavigationBuilderContext from './NavigationBuilderContext'; import NavigationBuilderContext from './NavigationBuilderContext';
import NavigationStateContext from './NavigationStateContext';
import UnhandledActionContext from './UnhandledActionContext';
import { ScheduleUpdateContext } from './useScheduleUpdate'; import { ScheduleUpdateContext } from './useScheduleUpdate';
import useFocusedListeners from './useFocusedListeners'; import useFocusedListeners from './useFocusedListeners';
import useDevTools from './useDevTools';
import useStateGetters from './useStateGetters'; import useStateGetters from './useStateGetters';
import useOptionsGetters from './useOptionsGetters';
import useEventEmitter from './useEventEmitter'; import useEventEmitter from './useEventEmitter';
import useSyncState from './useSyncState'; import useSyncState from './useSyncState';
import isSerializable from './isSerializable'; import isSerializable from './isSerializable';
import type {
import { NavigationContainerRef, NavigationContainerProps } from './types'; NavigationContainerEventMap,
NavigationContainerRef,
NavigationContainerProps,
} from './types';
type State = NavigationState | PartialState<NavigationState> | undefined; type State = NavigationState | PartialState<NavigationState> | undefined;
const DEVTOOLS_CONFIG_KEY =
'REACT_NAVIGATION_REDUX_DEVTOOLS_EXTENSION_INTEGRATION_ENABLED';
const MISSING_CONTEXT_ERROR =
"Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.";
const NOT_INITIALIZED_ERROR = const NOT_INITIALIZED_ERROR =
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details."; "The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
export const NavigationStateContext = React.createContext<{
isDefault?: true;
state?: NavigationState | PartialState<NavigationState>;
getKey: () => string | undefined;
setKey: (key: string) => void;
getState: () => NavigationState | PartialState<NavigationState> | undefined;
setState: (
state: NavigationState | PartialState<NavigationState> | undefined
) => void;
}>({
isDefault: true,
get getKey(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get setKey(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get getState(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get setState(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
});
let hasWarnedForSerialization = false; let hasWarnedForSerialization = false;
/**
* Migration instructions for removal of devtools from core
*/
Object.defineProperty(
global,
'REACT_NAVIGATION_REDUX_DEVTOOLS_EXTENSION_INTEGRATION_ENABLED',
{
set(_) {
console.warn(
"Redux devtools extension integration can be enabled with the '@react-navigation/devtools' package. For more details, see https://reactnavigation.org/docs/devtools"
);
},
}
);
/** /**
* Remove `key` and `routeNames` from the state objects recursively to get partial state. * Remove `key` and `routeNames` from the state objects recursively to get partial state.
* *
@@ -73,7 +61,6 @@ const getPartialState = (
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { key, routeNames, ...partialState } = state; const { key, routeNames, ...partialState } = state;
// @ts-ignore
return { return {
...partialState, ...partialState,
stale: true, stale: true,
@@ -127,7 +114,6 @@ const BaseNavigationContainer = React.forwardRef(
); );
const isFirstMountRef = React.useRef<boolean>(true); const isFirstMountRef = React.useRef<boolean>(true);
const skipTrackingRef = React.useRef<boolean>(false);
const navigatorKeyRef = React.useRef<string | undefined>(); const navigatorKeyRef = React.useRef<string | undefined>();
@@ -137,23 +123,6 @@ const BaseNavigationContainer = React.forwardRef(
navigatorKeyRef.current = key; navigatorKeyRef.current = key;
}, []); }, []);
const reset = React.useCallback(
(state: NavigationState) => {
skipTrackingRef.current = true;
setState(state);
},
[setState]
);
const { trackState, trackAction } = useDevTools({
enabled:
// @ts-ignore
DEVTOOLS_CONFIG_KEY in global ? global[DEVTOOLS_CONFIG_KEY] : false,
name: '@react-navigation',
reset,
state,
});
const { const {
listeners, listeners,
addListener: addFocusedListener, addListener: addFocusedListener,
@@ -189,17 +158,29 @@ const BaseNavigationContainer = React.forwardRef(
const resetRoot = React.useCallback( const resetRoot = React.useCallback(
(state?: PartialState<NavigationState> | NavigationState) => { (state?: PartialState<NavigationState> | NavigationState) => {
trackAction('@@RESET_ROOT');
setState(state); setState(state);
}, },
[setState, trackAction] [setState]
); );
const getRootState = React.useCallback(() => { const getRootState = React.useCallback(() => {
return getStateForRoute('root'); return getStateForRoute('root');
}, [getStateForRoute]); }, [getStateForRoute]);
const emitter = useEventEmitter(); const getCurrentRoute = React.useCallback(() => {
let state = getRootState();
if (state === undefined) {
return undefined;
}
while (state.routes[state.index].state !== undefined) {
state = state.routes[state.index].state as NavigationState;
}
return state.routes[state.index];
}, [getRootState]);
const emitter = useEventEmitter<NavigationContainerEventMap>();
const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
React.useImperativeHandle(ref, () => ({ React.useImperativeHandle(ref, () => ({
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce< ...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
@@ -208,7 +189,7 @@ const BaseNavigationContainer = React.forwardRef(
acc[name] = (...args: any[]) => acc[name] = (...args: any[]) =>
dispatch( dispatch(
CommonActions[name]( CommonActions[name](
// @ts-ignore // @ts-expect-error: we can't know the type statically
...args ...args
) )
); );
@@ -221,15 +202,35 @@ const BaseNavigationContainer = React.forwardRef(
getRootState, getRootState,
dangerouslyGetState: () => state, dangerouslyGetState: () => state,
dangerouslyGetParent: () => undefined, dangerouslyGetParent: () => undefined,
getCurrentRoute,
getCurrentOptions,
})); }));
const onDispatchAction = React.useCallback(
(action: NavigationAction, noop: boolean) => {
emitter.emit({ type: '__unsafe_action__', data: { action, noop } });
},
[emitter]
);
const onOptionsChange = React.useCallback(
(options) => {
emitter.emit({
type: 'options',
data: { options },
});
},
[emitter]
);
const builderContext = React.useMemo( const builderContext = React.useMemo(
() => ({ () => ({
addFocusedListener, addFocusedListener,
addStateGetter, addStateGetter,
trackAction, onDispatchAction,
onOptionsChange,
}), }),
[addFocusedListener, trackAction, addStateGetter] [addFocusedListener, addStateGetter, onDispatchAction, onOptionsChange]
); );
const scheduleContext = React.useMemo( const scheduleContext = React.useMemo(
@@ -244,10 +245,17 @@ const BaseNavigationContainer = React.forwardRef(
setState, setState,
getKey, getKey,
setKey, setKey,
addOptionsGetter,
}), }),
[getKey, getState, setKey, setState, state] [getKey, getState, setKey, setState, state, addOptionsGetter]
); );
const onStateChangeRef = React.useRef(onStateChange);
React.useEffect(() => {
onStateChangeRef.current = onStateChange;
});
React.useEffect(() => { React.useEffect(() => {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
if ( if (
@@ -263,29 +271,62 @@ const BaseNavigationContainer = React.forwardRef(
} }
} }
emitter.emit({ emitter.emit({ type: 'state', data: { state } });
type: 'state',
data: { state },
});
if (skipTrackingRef.current) { if (!isFirstMountRef.current && onStateChangeRef.current) {
skipTrackingRef.current = false; onStateChangeRef.current(getRootState());
} else {
trackState(getRootState);
}
if (!isFirstMountRef.current && onStateChange) {
onStateChange(getRootState());
} }
isFirstMountRef.current = false; isFirstMountRef.current = false;
}, [onStateChange, trackState, getRootState, emitter, state]); }, [getRootState, emitter, state]);
const onUnhandledAction = React.useCallback((action: NavigationAction) => {
if (process.env.NODE_ENV === 'production') {
return;
}
const payload: Record<string, any> | undefined = action.payload;
let message = `The action '${action.type}'${
payload ? ` with payload ${JSON.stringify(action.payload)}` : ''
} was not handled by any navigator.`;
switch (action.type) {
case 'NAVIGATE':
case 'PUSH':
case 'REPLACE':
case 'JUMP_TO':
if (payload?.name) {
message += `\n\nDo you have a screen named '${payload.name}'?\n\nIf you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.`;
} else {
message += `\n\nYou need to pass the name of the screen to navigate to.\n\nSee https://reactnavigation.org/docs/navigation-actions for usage.`;
}
break;
case 'GO_BACK':
case 'POP':
case 'POP_TO_TOP':
message += `\n\nIs there any screen to go back to?`;
break;
case 'OPEN_DRAWER':
case 'CLOSE_DRAWER':
case 'TOGGLE_DRAWER':
message += `\n\nIs your screen inside a Drawer navigator?`;
break;
}
message += `\n\nThis is a development-only warning and won't be shown in production.`;
console.error(message);
}, []);
return ( return (
<ScheduleUpdateContext.Provider value={scheduleContext}> <ScheduleUpdateContext.Provider value={scheduleContext}>
<NavigationBuilderContext.Provider value={builderContext}> <NavigationBuilderContext.Provider value={builderContext}>
<NavigationStateContext.Provider value={context}> <NavigationStateContext.Provider value={context}>
<EnsureSingleNavigator>{children}</EnsureSingleNavigator> <UnhandledActionContext.Provider value={onUnhandledAction}>
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
</UnhandledActionContext.Provider>
</NavigationStateContext.Provider> </NavigationStateContext.Provider>
</NavigationBuilderContext.Provider> </NavigationBuilderContext.Provider>
</ScheduleUpdateContext.Provider> </ScheduleUpdateContext.Provider>

View File

@@ -0,0 +1,11 @@
import * as React from 'react';
/**
* Context which holds the values for the current navigation tree.
* Intended for use in SSR. This is not safe to use on the client.
*/
const CurrentRenderContext = React.createContext<
{ options?: object } | undefined
>(undefined);
export default CurrentRenderContext;

View File

@@ -1,10 +1,10 @@
import * as React from 'react'; import * as React from 'react';
import { import type {
NavigationAction, NavigationAction,
NavigationState, NavigationState,
ParamListBase, ParamListBase,
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import { NavigationHelpers } from './types'; import type { NavigationHelpers } from './types';
export type ChildActionListener = ( export type ChildActionListener = (
action: NavigationAction, action: NavigationAction,
@@ -32,10 +32,12 @@ const NavigationBuilderContext = React.createContext<{
addActionListener?: (listener: ChildActionListener) => void; addActionListener?: (listener: ChildActionListener) => void;
addFocusedListener?: (listener: FocusedNavigationListener) => void; addFocusedListener?: (listener: FocusedNavigationListener) => void;
onRouteFocus?: (key: string) => void; onRouteFocus?: (key: string) => void;
onDispatchAction: (action: NavigationAction, noop: boolean) => void;
addStateGetter?: (key: string, getter: NavigatorStateGetter) => void; addStateGetter?: (key: string, getter: NavigatorStateGetter) => void;
trackAction: (action: NavigationAction) => void; onOptionsChange: (options: object) => void;
}>({ }>({
trackAction: () => undefined, onDispatchAction: () => undefined,
onOptionsChange: () => undefined,
}); });
export default NavigationBuilderContext; export default NavigationBuilderContext;

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { ParamListBase } from '@react-navigation/routers'; import type { ParamListBase } from '@react-navigation/routers';
import { NavigationProp } from './types'; import type { NavigationProp } from './types';
/** /**
* Context which holds the navigation prop for a screen. * Context which holds the navigation prop for a screen.

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { ParamListBase } from '@react-navigation/routers'; import type { ParamListBase } from '@react-navigation/routers';
import { NavigationHelpers } from './types'; import type { NavigationHelpers } from './types';
/** /**
* Context which holds the navigation helpers of the parent navigator. * Context which holds the navigation helpers of the parent navigator.

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { Route } from '@react-navigation/routers'; import type { Route } from '@react-navigation/routers';
/** /**
* Context which holds the route prop for a screen. * Context which holds the route prop for a screen.

View File

@@ -0,0 +1,35 @@
import * as React from 'react';
import type { NavigationState, PartialState } from '@react-navigation/routers';
const MISSING_CONTEXT_ERROR =
"Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.";
export default React.createContext<{
isDefault?: true;
state?: NavigationState | PartialState<NavigationState>;
getKey: () => string | undefined;
setKey: (key: string) => void;
getState: () => NavigationState | PartialState<NavigationState> | undefined;
setState: (
state: NavigationState | PartialState<NavigationState> | undefined
) => void;
addOptionsGetter?: (
key: string,
getter: () => object | undefined | null
) => void;
}>({
isDefault: true,
get getKey(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get setKey(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get getState(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
get setState(): any {
throw new Error(MISSING_CONTEXT_ERROR);
},
});

View File

@@ -1,20 +1,21 @@
import * as React from 'react'; import * as React from 'react';
import { import type {
Route, Route,
ParamListBase, ParamListBase,
NavigationState, NavigationState,
PartialState, PartialState,
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import { NavigationStateContext } from './BaseNavigationContainer'; import NavigationStateContext from './NavigationStateContext';
import NavigationContext from './NavigationContext';
import NavigationRouteContext from './NavigationRouteContext';
import StaticContainer from './StaticContainer'; import StaticContainer from './StaticContainer';
import EnsureSingleNavigator from './EnsureSingleNavigator'; import EnsureSingleNavigator from './EnsureSingleNavigator';
import { NavigationProp, RouteConfig, EventMapBase } from './types'; import useOptionsGetters from './useOptionsGetters';
import NavigationBuilderContext from './NavigationBuilderContext';
import useFocusEffect from './useFocusEffect';
import type { NavigationProp, RouteConfig, EventMapBase } from './types';
type Props< type Props<
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase EventMap extends EventMapBase
> = { > = {
screen: RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>; screen: RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>;
@@ -24,6 +25,7 @@ type Props<
}; };
getState: () => State; getState: () => State;
setState: (state: State) => void; setState: (state: State) => void;
options: object;
}; };
/** /**
@@ -32,7 +34,7 @@ type Props<
*/ */
export default function SceneView< export default function SceneView<
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase EventMap extends EventMapBase
>({ >({
screen, screen,
@@ -40,10 +42,28 @@ export default function SceneView<
navigation, navigation,
getState, getState,
setState, setState,
options,
}: Props<State, ScreenOptions, EventMap>) { }: Props<State, ScreenOptions, EventMap>) {
const navigatorKeyRef = React.useRef<string | undefined>(); const navigatorKeyRef = React.useRef<string | undefined>();
const { onOptionsChange } = React.useContext(NavigationBuilderContext);
const getKey = React.useCallback(() => navigatorKeyRef.current, []); const getKey = React.useCallback(() => navigatorKeyRef.current, []);
const optionsRef = React.useRef<object | undefined>(options);
const getOptions = React.useCallback(() => optionsRef.current, []);
const { addOptionsGetter, hasAnyChildListener } = useOptionsGetters({
key: route.key,
getState,
getOptions,
});
const optionsChange = React.useCallback(() => {
optionsRef.current = options;
if (!hasAnyChildListener) {
onOptionsChange(options);
}
}, [onOptionsChange, options, hasAnyChildListener]);
useFocusEffect(optionsChange);
const setKey = React.useCallback((key: string) => { const setKey = React.useCallback((key: string) => {
navigatorKeyRef.current = key; navigatorKeyRef.current = key;
@@ -77,33 +97,35 @@ export default function SceneView<
setState: setCurrentState, setState: setCurrentState,
getKey, getKey,
setKey, setKey,
addOptionsGetter,
}), }),
[getCurrentState, getKey, route.state, setCurrentState, setKey] [
getCurrentState,
getKey,
route.state,
setCurrentState,
setKey,
addOptionsGetter,
]
); );
return ( return (
<NavigationContext.Provider value={navigation}> <NavigationStateContext.Provider value={context}>
<NavigationRouteContext.Provider value={route}> <EnsureSingleNavigator>
<NavigationStateContext.Provider value={context}> <StaticContainer
<EnsureSingleNavigator> name={screen.name}
<StaticContainer // @ts-expect-error: these properties exist on screen, but TS is confused
name={screen.name} render={screen.component || screen.children}
// @ts-ignore navigation={navigation}
render={screen.component || screen.children} route={route}
navigation={navigation} >
route={route} {'component' in screen && screen.component !== undefined ? (
> <screen.component navigation={navigation} route={route} />
{'component' in screen && screen.component !== undefined ? ( ) : 'children' in screen && screen.children !== undefined ? (
// @ts-ignore screen.children({ navigation, route })
<screen.component navigation={navigation} route={route} /> ) : null}
) : 'children' in screen && screen.children !== undefined ? ( </StaticContainer>
// @ts-ignore </EnsureSingleNavigator>
screen.children({ navigation, route }) </NavigationStateContext.Provider>
) : null}
</StaticContainer>
</EnsureSingleNavigator>
</NavigationStateContext.Provider>
</NavigationRouteContext.Provider>
</NavigationContext.Provider>
); );
} }

View File

@@ -1,5 +1,5 @@
import { ParamListBase, NavigationState } from '@react-navigation/routers'; import type { ParamListBase, NavigationState } from '@react-navigation/routers';
import { RouteConfig, EventMapBase } from './types'; import type { RouteConfig, EventMapBase } from './types';
/** /**
* Empty component used for specifying route configuration. * Empty component used for specifying route configuration.
@@ -8,7 +8,7 @@ export default function Screen<
ParamList extends ParamListBase, ParamList extends ParamListBase,
RouteName extends keyof ParamList, RouteName extends keyof ParamList,
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase EventMap extends EventMapBase
>(_: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap>) { >(_: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap>) {
/* istanbul ignore next */ /* istanbul ignore next */

View File

@@ -0,0 +1,8 @@
import * as React from 'react';
import type { NavigationAction } from '@react-navigation/routers';
const UnhandledActionContext = React.createContext<
((action: NavigationAction) => void) | undefined
>(undefined);
export default UnhandledActionContext;

View File

@@ -1,17 +1,16 @@
import * as React from 'react'; import * as React from 'react';
import { act, render } from 'react-native-testing-library'; import { act, render } from 'react-native-testing-library';
import { import type {
DefaultRouterOptions, DefaultRouterOptions,
NavigationState, NavigationState,
Router, Router,
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import BaseNavigationContainer, { import BaseNavigationContainer from '../BaseNavigationContainer';
NavigationStateContext, import NavigationStateContext from '../NavigationStateContext';
} from '../BaseNavigationContainer';
import MockRouter, { MockActions } from './__fixtures__/MockRouter'; import MockRouter, { MockActions } from './__fixtures__/MockRouter';
import useNavigationBuilder from '../useNavigationBuilder'; import useNavigationBuilder from '../useNavigationBuilder';
import Screen from '../Screen'; import Screen from '../Screen';
import { NavigationContainerRef } from '../types'; import type { NavigationContainerRef } from '../types';
it('throws when getState is accessed without a container', () => { it('throws when getState is accessed without a container', () => {
expect.assertions(1); expect.assertions(1);
@@ -431,6 +430,65 @@ it('emits state events when the state changes', () => {
}); });
}); });
it('emits state events when options change', () => {
const TestNavigator = (props: any) => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
return (
<React.Fragment>
{state.routes.map((route) => descriptors[route.key].render())}
</React.Fragment>
);
};
const ref = React.createRef<NavigationContainerRef>();
const element = (
<BaseNavigationContainer ref={ref}>
<TestNavigator>
<Screen name="foo" options={{ x: 1 }}>
{() => null}
</Screen>
<Screen name="bar" options={{ y: 2 }}>
{() => null}
</Screen>
<Screen name="baz" options={{ v: 3 }}>
{() => (
<TestNavigator>
<Screen name="foo" options={{ g: 5 }}>
{() => null}
</Screen>
</TestNavigator>
)}
</Screen>
</TestNavigator>
</BaseNavigationContainer>
);
const listener = jest.fn();
render(element).update(element);
ref.current?.addListener('options', listener);
act(() => {
ref.current?.navigate('bar');
});
expect(listener.mock.calls[0][0].data.options).toEqual({
y: 2,
});
ref.current?.removeListener('options', listener);
const listener2 = jest.fn();
ref.current?.addListener('options', listener2);
act(() => {
ref.current?.navigate('baz');
});
expect(listener2.mock.calls[0][0].data.options).toEqual({ g: 5 });
});
it('throws if there is no navigator rendered', () => { it('throws if there is no navigator rendered', () => {
expect.assertions(1); expect.assertions(1);

View File

@@ -5,7 +5,7 @@ it('throws descriptive error if an argument is passed', () => {
expect(() => createDummyNavigator()).not.toThrowError(); expect(() => createDummyNavigator()).not.toThrowError();
// @ts-ignore // @ts-expect-error: we're explicitly passing invalid argument
expect(() => createDummyNavigator({})).toThrowError( expect(() => createDummyNavigator({})).toThrowError(
"Creating a navigator doesn't take an argument." "Creating a navigator doesn't take an argument."
); );

View File

@@ -0,0 +1,68 @@
import getFocusedRouteNameFromRoute from '../getFocusedRouteNameFromRoute';
it('gets undefined if there is no nested state', () => {
expect(getFocusedRouteNameFromRoute({ name: 'Home' })).toBe(undefined);
});
it('gets focused route name from nested state', () => {
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
state: {
routes: [{ name: 'Article' }],
},
})
).toBe('Article');
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
state: {
index: 1,
routes: [{ name: 'Article' }, { name: 'Chat' }, { name: 'Album' }],
},
})
).toBe('Chat');
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
state: {
routes: [{ name: 'Article' }, { name: 'Chat' }],
},
})
).toBe('Chat');
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
state: {
type: 'tab',
routes: [{ name: 'Article' }, { name: 'Chat' }],
},
})
).toBe('Article');
});
it('gets nested screen in params if present', () => {
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
params: { screen: 'Chat' },
})
).toBe('Chat');
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
params: { screen: 'Chat', initial: false },
})
).toBe('Chat');
expect(
getFocusedRouteNameFromRoute({
name: 'Home',
params: { screen: {} },
})
).toBe(undefined);
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,12 @@
import * as React from 'react'; import * as React from 'react';
import { render, act } from 'react-native-testing-library'; import { render, act } from 'react-native-testing-library';
import { NavigationState } from '@react-navigation/routers'; import type { NavigationState } from '@react-navigation/routers';
import Screen from '../Screen'; import Screen from '../Screen';
import BaseNavigationContainer from '../BaseNavigationContainer'; import BaseNavigationContainer from '../BaseNavigationContainer';
import useNavigationBuilder from '../useNavigationBuilder'; import useNavigationBuilder from '../useNavigationBuilder';
import useNavigation from '../useNavigation'; import useNavigation from '../useNavigation';
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter'; import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
import { NavigationContainerRef } from '../types'; import type { NavigationContainerRef } from '../types';
beforeEach(() => (MockRouterKey.current = 0)); beforeEach(() => (MockRouterKey.current = 0));
@@ -75,7 +75,7 @@ it("doesn't crash when initialState is null", () => {
const TestScreen = () => null; const TestScreen = () => null;
const element = ( const element = (
// @ts-ignore // @ts-expect-error: we're explicitly passing null for state
<BaseNavigationContainer initialState={null}> <BaseNavigationContainer initialState={null}>
<TestNavigator> <TestNavigator>
<Screen name="foo" component={TestScreen} /> <Screen name="foo" component={TestScreen} />
@@ -379,6 +379,8 @@ it("doesn't update state if action wasn't handled", () => {
}); });
it('cleans up state when the navigator unmounts', () => { it('cleans up state when the navigator unmounts', () => {
jest.useFakeTimers();
const TestNavigator = (props: any) => { const TestNavigator = (props: any) => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props); const { state, descriptors } = useNavigationBuilder(MockRouter, props);
@@ -426,6 +428,8 @@ it('cleans up state when the navigator unmounts', () => {
<BaseNavigationContainer onStateChange={onStateChange} children={null} /> <BaseNavigationContainer onStateChange={onStateChange} children={null} />
); );
act(() => jest.runAllTimers());
expect(onStateChange).toBeCalledTimes(2); expect(onStateChange).toBeCalledTimes(2);
expect(onStateChange).lastCalledWith(undefined); expect(onStateChange).lastCalledWith(undefined);
}); });
@@ -1486,3 +1490,194 @@ it("doesn't throw if children is null", () => {
expect(() => render(element).update(element)).not.toThrowError(); expect(() => render(element).update(element)).not.toThrowError();
}); });
it('returns currently focused route with getCurrentRoute', () => {
const TestNavigator = (props: any): any => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
return descriptors[state.routes[state.index].key].render();
};
const TestScreen = () => null;
const navigation = React.createRef<NavigationContainerRef>();
const container = (
<BaseNavigationContainer ref={navigation}>
<TestNavigator>
<Screen name="bar" options={{ a: 'b' }}>
{() => (
<TestNavigator initialRouteName="bar-a">
<Screen
name="bar-a"
component={TestScreen}
options={{ sample: 'data' }}
/>
</TestNavigator>
)}
</Screen>
<Screen name="xux" component={TestScreen} />
</TestNavigator>
</BaseNavigationContainer>
);
render(container).update(container);
expect(navigation.current?.getCurrentRoute()).toEqual({
key: 'bar-a',
name: 'bar-a',
});
});
it("returns focused screen's options with getCurrentOptions when focused screen is rendered", () => {
const TestNavigator = (props: any): any => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
return descriptors[state.routes[state.index].key].render();
};
const TestScreen = () => null;
const navigation = React.createRef<NavigationContainerRef>();
const container = (
<BaseNavigationContainer ref={navigation}>
<TestNavigator>
<Screen name="bar" options={{ a: 'b' }}>
{() => (
<TestNavigator
initialRouteName="bar-a"
screenOptions={() => ({ sample2: 'data' })}
>
<Screen
name="bar-a"
component={TestScreen}
options={{ sample: 'data' }}
/>
<Screen
name="bar-b"
component={TestScreen}
options={{ sample3: 'data' }}
/>
</TestNavigator>
)}
</Screen>
<Screen name="xux" component={TestScreen} />
</TestNavigator>
</BaseNavigationContainer>
);
render(container).update(container);
expect(navigation.current?.getCurrentOptions()).toEqual({
sample: 'data',
sample2: 'data',
});
act(() => navigation.current?.navigate('bar-b'));
expect(navigation.current?.getCurrentOptions()).toEqual({
sample2: 'data',
sample3: 'data',
});
});
it("returns focused screen's options with getCurrentOptions when all screens are rendered", () => {
const TestNavigator = (props: any): any => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
return <>{state.routes.map((route) => descriptors[route.key].render())}</>;
};
const TestScreen = () => null;
const navigation = React.createRef<NavigationContainerRef>();
const container = (
<BaseNavigationContainer ref={navigation}>
<TestNavigator>
<Screen name="bar" options={{ a: 'b' }}>
{() => (
<TestNavigator
initialRouteName="bar-a"
screenOptions={() => ({ sample2: 'data' })}
>
<Screen
name="bar-a"
component={TestScreen}
options={{ sample: 'data' }}
/>
<Screen
name="bar-b"
component={TestScreen}
options={{ sample3: 'data' }}
/>
</TestNavigator>
)}
</Screen>
<Screen name="xux" component={TestScreen} />
</TestNavigator>
</BaseNavigationContainer>
);
render(container).update(container);
expect(navigation.current?.getCurrentOptions()).toEqual({
sample: 'data',
sample2: 'data',
});
act(() => navigation.current?.navigate('bar-b'));
expect(navigation.current?.getCurrentOptions()).toEqual({
sample2: 'data',
sample3: 'data',
});
});
it('does not throw if while getting current options with no options defined', () => {
const TestNavigator = (props: any): any => {
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
return descriptors[state.routes[state.index].key].render();
};
const TestScreen = () => null;
const navigation = React.createRef<NavigationContainerRef>();
const container = (
<BaseNavigationContainer ref={navigation}>
<TestNavigator>
<Screen name="bar" options={{ a: 'b' }}>
{() => (
<TestNavigator initialRouteName="bar-a">
<Screen
name="bar-b"
component={TestScreen}
options={{ wrongKey: true }}
/>
<Screen name="bar-a" component={TestScreen} />
</TestNavigator>
)}
</Screen>
</TestNavigator>
</BaseNavigationContainer>
);
render(container).update(container);
expect(navigation.current?.getCurrentOptions()).toEqual({});
});
it('does not throw if while getting current options with empty container', () => {
const navigation = React.createRef<NavigationContainerRef>();
const container = (
<BaseNavigationContainer ref={navigation} children={null} />
);
render(container).update(container);
expect(navigation.current?.getCurrentOptions()).toEqual(undefined);
});

View File

@@ -51,19 +51,17 @@ it('returns false for non-serializable object', () => {
}); });
it('returns false for circular references', () => { it('returns false for circular references', () => {
const x = { const x: any = {
a: 1, a: 1,
b: { b1: 1 }, b: { b1: 1 },
}; };
// @ts-ignore
x.b.b2 = x; x.b.b2 = x;
// @ts-ignore
x.c = x.b; x.c = x.b;
expect(isSerializable(x)).toBe(false); expect(isSerializable(x)).toBe(false);
const y = [ const y: any = [
{ {
label: 'home', label: 'home',
children: [{ label: 'product' }], children: [{ label: 'product' }],
@@ -71,19 +69,16 @@ it('returns false for circular references', () => {
{ label: 'about', extend: {} }, { label: 'about', extend: {} },
]; ];
// @ts-ignore
y[0].children[0].parent = y[0]; y[0].children[0].parent = y[0];
// @ts-ignore
y[1].extend.home = y[0].children[0]; y[1].extend.home = y[0].children[0];
expect(isSerializable(y)).toBe(false); expect(isSerializable(y)).toBe(false);
const z = { const z: any = {
name: 'sun', name: 'sun',
child: [{ name: 'flower' }], child: [{ name: 'flower' }],
}; };
// @ts-ignore
z.child[0].parent = z; z.child[0].parent = z;
expect(isSerializable(z)).toBe(false); expect(isSerializable(z)).toBe(false);

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render, act } from 'react-native-testing-library'; import { render, act } from 'react-native-testing-library';
import { import type {
DefaultRouterOptions, DefaultRouterOptions,
NavigationState, NavigationState,
Router, Router,

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render, act } from 'react-native-testing-library'; import { render, act } from 'react-native-testing-library';
import { Router, NavigationState } from '@react-navigation/routers'; import type { Router, NavigationState } from '@react-navigation/routers';
import useNavigationBuilder from '../useNavigationBuilder'; import useNavigationBuilder from '../useNavigationBuilder';
import BaseNavigationContainer from '../BaseNavigationContainer'; import BaseNavigationContainer from '../BaseNavigationContainer';
import Screen from '../Screen'; import Screen from '../Screen';

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render, act } from 'react-native-testing-library'; import { render, act } from 'react-native-testing-library';
import { NavigationState } from '@react-navigation/routers'; import type { NavigationState } from '@react-navigation/routers';
import useNavigationBuilder from '../useNavigationBuilder'; import useNavigationBuilder from '../useNavigationBuilder';
import useNavigationState from '../useNavigationState'; import useNavigationState from '../useNavigationState';
import BaseNavigationContainer from '../BaseNavigationContainer'; import BaseNavigationContainer from '../BaseNavigationContainer';

View File

@@ -1,6 +1,6 @@
import * as React from 'react'; import * as React from 'react';
import { render } from 'react-native-testing-library'; import { render } from 'react-native-testing-library';
import { import type {
Router, Router,
DefaultRouterOptions, DefaultRouterOptions,
NavigationState, NavigationState,

View File

@@ -5,7 +5,7 @@ import useRoute from '../useRoute';
import BaseNavigationContainer from '../BaseNavigationContainer'; import BaseNavigationContainer from '../BaseNavigationContainer';
import Screen from '../Screen'; import Screen from '../Screen';
import MockRouter from './__fixtures__/MockRouter'; import MockRouter from './__fixtures__/MockRouter';
import { RouteProp } from '../types'; import type { RouteProp } from '../types';
it('gets route prop from context', () => { it('gets route prop from context', () => {
expect.assertions(1); expect.assertions(1);

View File

@@ -0,0 +1,36 @@
import type { PathConfigMap } from './types';
type Options = {
initialRouteName?: string;
screens: PathConfigMap;
};
export default function checkLegacyPathConfig(
config?: Options
): [boolean, Options | undefined] {
let legacy = false;
if (config) {
// Assume legacy configuration if config has any other keys except `screens` and `initialRouteName`
legacy = Object.keys(config).some(
(key) => key !== 'screens' && key !== 'initialRouteName'
);
if (
legacy &&
(config.hasOwnProperty('screens') ||
config.hasOwnProperty('initialRouteName'))
) {
throw new Error(
'Found invalid keys in the configuration object. See https://reactnavigation.org/docs/configuring-links/ for more details on the shape of the configuration object.'
);
}
}
if (legacy) {
// @ts-expect-error: we have incorrect type for config since we don't type legacy config
return [legacy, { screens: config }];
}
return [legacy, config];
}

View File

@@ -1,7 +1,7 @@
import * as React from 'react'; import type * as React from 'react';
import { ParamListBase, NavigationState } from '@react-navigation/routers'; import type { ParamListBase, NavigationState } from '@react-navigation/routers';
import Screen from './Screen'; import Screen from './Screen';
import { TypedNavigator, EventMapBase } from './types'; import type { TypedNavigator, EventMapBase } from './types';
/** /**
* Higher order component to create a `Navigator` and `Screen` pair. * Higher order component to create a `Navigator` and `Screen` pair.
@@ -12,7 +12,7 @@ import { TypedNavigator, EventMapBase } from './types';
*/ */
export default function createNavigatorFactory< export default function createNavigatorFactory<
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase, EventMap extends EventMapBase,
NavigatorComponent extends React.ComponentType<any> NavigatorComponent extends React.ComponentType<any>
>(Navigator: NavigatorComponent) { >(Navigator: NavigatorComponent) {

View File

@@ -1,4 +1,4 @@
import { PartialState, NavigationState } from '@react-navigation/routers'; import type { PartialState, NavigationState } from '@react-navigation/routers';
type NavigateParams = { type NavigateParams = {
screen?: string; screen?: string;

View File

@@ -0,0 +1,29 @@
import type {
Route,
PartialState,
NavigationState,
} from '@react-navigation/routers';
export default function getFocusedRouteNameFromRoute(
route: Partial<Route<string>> & { state?: PartialState<NavigationState> }
): string | undefined {
const state = route.state;
const params = route.params as { screen?: unknown } | undefined;
const routeName = state
? // Get the currently active route name in the nested navigator
state.routes[
// If we have a partial state without index, for tab/drawer, first screen will be focused one, and last for stack
// The type property will only exist for rehydrated state and not for state from deep link
state.index ??
(typeof state.type === 'string' && state.type !== 'stack'
? 0
: state.routes.length - 1)
].name
: // If state doesn't exist, we need to default to `screen` param if available
typeof params?.screen === 'string'
? params.screen
: undefined;
return routeName;
}

View File

@@ -1,22 +1,35 @@
import queryString from 'query-string'; import queryString from 'query-string';
import { import type {
NavigationState, NavigationState,
PartialState, PartialState,
Route, Route,
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import checkLegacyPathConfig from './checkLegacyPathConfig';
import type { PathConfig, PathConfigMap } from './types';
type Options = { initialRouteName?: string; screens: PathConfigMap };
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>; type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
type StringifyConfig = Record<string, (value: any) => string>; type StringifyConfig = Record<string, (value: any) => string>;
type Options = { type ConfigItem = {
[routeName: string]: pattern?: string;
| string stringify?: StringifyConfig;
| { screens?: Record<string, ConfigItem>;
path?: string; };
stringify?: StringifyConfig;
screens?: Options; const getActiveRoute = (state: State): { name: string; params?: object } => {
}; const route =
typeof state.index === 'number'
? state.routes[state.index]
: state.routes[state.routes.length - 1];
if (route.state) {
return getActiveRoute(route.state);
}
return route;
}; };
/** /**
@@ -34,9 +47,11 @@ type Options = {
* ], * ],
* }, * },
* { * {
* Chat: { * screens: {
* path: 'chat/:author/:id', * Chat: {
* stringify: { author: author => author.toLowerCase() } * path: 'chat/:author/:id',
* stringify: { author: author => author.toLowerCase() }
* }
* } * }
* } * }
* ) * )
@@ -47,107 +62,142 @@ type Options = {
* @returns Path representing the state, e.g. /foo/bar?count=42. * @returns Path representing the state, e.g. /foo/bar?count=42.
*/ */
export default function getPathFromState( export default function getPathFromState(
state?: State, state: State,
options: Options = {} options?: Options
): string { ): string {
if (state === undefined) { if (state == null) {
throw Error('NavigationState not passed'); throw Error(
"Got 'undefined' for the navigation state. You must pass a valid state object."
);
} }
let path = '/';
const [legacy, compatOptions] = checkLegacyPathConfig(options);
// Create a normalized configs object which will be easier to use
const configs: Record<string, ConfigItem> = compatOptions
? createNormalizedConfigs(legacy, compatOptions.screens)
: {};
let path = '/';
let current: State | undefined = state; let current: State | undefined = state;
const allParams: Record<string, any> = {};
while (current) { while (current) {
let index = typeof current.index === 'number' ? current.index : 0; let index = typeof current.index === 'number' ? current.index : 0;
let route = current.routes[index] as Route<string> & { let route = current.routes[index] as Route<string> & {
state?: State; state?: State;
}; };
let currentOptions = options;
let pattern = route.name;
// we keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
let nestedRouteNames = '';
while (route.name in currentOptions) { let pattern: string | undefined;
if (typeof currentOptions[route.name] === 'string') {
pattern = currentOptions[route.name] as string; let focusedParams: Record<string, any> | undefined;
break; let focusedRoute = getActiveRoute(state);
} else if (typeof currentOptions[route.name] === 'object') { let currentOptions = configs;
// if there is no `screens` property, we return pattern
if ( // Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
!(currentOptions[route.name] as { let nestedRouteNames = [];
screens: Options;
}).screens let hasNext = true;
) {
pattern = (currentOptions[route.name] as { path: string }).path; while (route.name in currentOptions && hasNext) {
nestedRouteNames = `${nestedRouteNames}/${route.name}`; pattern = currentOptions[route.name].pattern;
break;
nestedRouteNames.push(route.name);
if (route.params) {
const stringify = currentOptions[route.name]?.stringify;
const currentParams = fromEntries(
Object.entries(route.params).map(([key, value]) => [
key,
stringify?.[key] ? stringify[key](value) : String(value),
])
);
if (pattern) {
Object.assign(allParams, currentParams);
}
if (focusedRoute === route) {
// If this is the focused route, keep the params for later use
// We save it here since it's been stringified already
focusedParams = { ...currentParams };
pattern
?.split('/')
.filter((p) => p.startsWith(':'))
// eslint-disable-next-line no-loop-func
.forEach((p) => {
const name = getParamName(p);
// Remove the params present in the pattern since we'll only use the rest for query string
if (focusedParams) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete focusedParams[name];
}
});
}
}
// If there is no `screens` property or no nested state, we return pattern
if (!currentOptions[route.name].screens || route.state === undefined) {
hasNext = false;
} else {
index =
typeof route.state.index === 'number'
? route.state.index
: route.state.routes.length - 1;
const nextRoute = route.state.routes[index];
const nestedConfig = currentOptions[route.name].screens;
// if there is config for next route name, we go deeper
if (nestedConfig && nextRoute.name in nestedConfig) {
route = nextRoute as Route<string> & { state?: State };
currentOptions = nestedConfig;
} else { } else {
// if it is the end of state, we return pattern // If not, there is no sense in going deeper in config
if (route.state === undefined) { hasNext = false;
pattern = (currentOptions[route.name] as { path: string }).path;
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
break;
} else {
index =
typeof route.state.index === 'number' ? route.state.index : 0;
const nextRoute = route.state.routes[index];
const deeperConfig = (currentOptions[route.name] as {
screens: Options;
}).screens;
// if there is config for next route name, we go deeper
if (nextRoute.name in deeperConfig) {
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
route = nextRoute as Route<string> & { state?: State };
currentOptions = deeperConfig;
} else {
// if not, there is no sense in going deeper in config
pattern = (currentOptions[route.name] as { path: string }).path;
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
break;
}
}
} }
} }
} }
if (pattern === undefined) { if (pattern === undefined) {
// cut the first `/` pattern = nestedRouteNames.join('/');
pattern = nestedRouteNames.substring(1);
} }
const config =
currentOptions[route.name] !== undefined
? (currentOptions[route.name] as { stringify?: StringifyConfig })
.stringify
: undefined;
const params = route.params
? // Stringify all of the param values before we use them
Object.entries(route.params).reduce<{
[key: string]: string;
}>((acc, [key, value]) => {
acc[key] = config?.[key] ? config[key](value) : String(value);
return acc;
}, {})
: undefined;
if (currentOptions[route.name] !== undefined) { if (currentOptions[route.name] !== undefined) {
path += pattern path += pattern
.split('/') .split('/')
.map((p) => { .map((p) => {
const name = p.replace(/^:/, '').replace(/\?$/, ''); const name = getParamName(p);
// We don't know what to show for wildcard patterns
// Showing the route name seems ok, though whatever we show here will be incorrect
// Since the page doesn't actually exist
if (p === '*') {
if (legacy) {
throw new Error(
"Please update your config to the new format to use wildcard pattern ('*'). https://reactnavigation.org/docs/configuring-links/#updating-config"
);
}
return route.name;
}
// If the path has a pattern for a param, put the param in the path // If the path has a pattern for a param, put the param in the path
if (params && name in params && p.startsWith(':')) { if (p.startsWith(':')) {
const value = params[name]; const value = allParams[name];
// Remove the used value from the params object since we'll use the rest for query string
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete if (value === undefined && p.endsWith('?')) {
delete params[name]; // Optional params without value assigned in route.params should be ignored
return '';
}
return encodeURIComponent(value); return encodeURIComponent(value);
} else if (p.endsWith('?')) {
// optional params without value assigned in route.params should be ignored
return '';
} }
return encodeURIComponent(p); return encodeURIComponent(p);
}) })
.join('/'); .join('/');
@@ -155,16 +205,21 @@ export default function getPathFromState(
path += encodeURIComponent(route.name); path += encodeURIComponent(route.name);
} }
if (!focusedParams) {
focusedParams = focusedRoute.params;
}
if (route.state) { if (route.state) {
path += '/'; path += '/';
} else if (params) { } else if (focusedParams) {
for (let param in params) { for (let param in focusedParams) {
if (params[param] === 'undefined') { if (focusedParams[param] === 'undefined') {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete params[param]; delete focusedParams[param];
} }
} }
const query = queryString.stringify(params);
const query = queryString.stringify(focusedParams);
if (query) { if (query) {
path += `?${query}`; path += `?${query}`;
@@ -180,3 +235,78 @@ export default function getPathFromState(
return path; return path;
} }
// Object.fromEntries is not available in older iOS versions
const fromEntries = <K extends string, V>(entries: (readonly [K, V])[]) =>
entries.reduce((acc, [k, v]) => {
acc[k] = v;
return acc;
}, {} as Record<K, V>);
const getParamName = (pattern: string) =>
pattern.replace(/^:/, '').replace(/\?$/, '');
const joinPaths = (...paths: string[]): string =>
([] as string[])
.concat(...paths.map((p) => p.split('/')))
.filter(Boolean)
.join('/');
const createConfigItem = (
legacy: boolean,
config: PathConfig | string,
parentPattern?: string
): ConfigItem => {
if (typeof config === 'string') {
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
return { pattern };
}
// If an object is specified as the value (e.g. Foo: { ... }),
// It can have `path` property and `screens` prop which has nested configs
let pattern: string | undefined;
if (legacy) {
pattern =
config.exact !== true && parentPattern && config.path
? joinPaths(parentPattern, config.path)
: config.path;
} else {
if (config.exact && config.path === undefined) {
throw new Error(
"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`."
);
}
pattern =
config.exact !== true
? joinPaths(parentPattern || '', config.path || '')
: config.path || '';
}
const screens = config.screens
? createNormalizedConfigs(legacy, config.screens, pattern)
: undefined;
return {
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
pattern: pattern?.split('/').filter(Boolean).join('/'),
stringify: config.stringify,
screens,
};
};
const createNormalizedConfigs = (
legacy: boolean,
options: PathConfigMap,
pattern?: string
): Record<string, ConfigItem> =>
fromEntries(
Object.entries(options).map(([name, c]) => {
const result = createConfigItem(legacy, c, pattern);
return [name, result];
})
);

View File

@@ -1,30 +1,27 @@
import escape from 'escape-string-regexp'; import escape from 'escape-string-regexp';
import queryString from 'query-string'; import queryString from 'query-string';
import { import type {
NavigationState, NavigationState,
PartialState, PartialState,
InitialState, InitialState,
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import checkLegacyPathConfig from './checkLegacyPathConfig';
import type { PathConfigMap } from './types';
type Options = {
initialRouteName?: string;
screens: PathConfigMap;
};
type ParseConfig = Record<string, (value: string) => any>; type ParseConfig = Record<string, (value: string) => any>;
type Options = {
[routeName: string]:
| string
| {
path?: string;
parse?: ParseConfig;
screens?: Options;
initialRouteName?: string;
};
};
type RouteConfig = { type RouteConfig = {
screen: string; screen: string;
match: RegExp | null; regex?: RegExp;
path: string;
pattern: string; pattern: string;
routeNames: string[]; routeNames: string[];
parse: ParseConfig | undefined; parse?: ParseConfig;
}; };
type InitialRouteConfig = { type InitialRouteConfig = {
@@ -45,9 +42,11 @@ type ResultState = PartialState<NavigationState> & {
* getStateFromPath( * getStateFromPath(
* '/chat/jane/42', * '/chat/jane/42',
* { * {
* Chat: { * screens: {
* path: 'chat/:author/:id', * Chat: {
* parse: { id: Number } * path: 'chat/:author/:id',
* parse: { id: Number }
* }
* } * }
* } * }
* ) * )
@@ -57,22 +56,20 @@ type ResultState = PartialState<NavigationState> & {
*/ */
export default function getStateFromPath( export default function getStateFromPath(
path: string, path: string,
options: Options = {} options?: Options
): ResultState | undefined { ): ResultState | undefined {
const [legacy, compatOptions] = checkLegacyPathConfig(options);
let initialRoutes: InitialRouteConfig[] = []; let initialRoutes: InitialRouteConfig[] = [];
// Create a normalized configs array which will be easier to use if (compatOptions?.initialRouteName) {
const configs = ([] as RouteConfig[]).concat( initialRoutes.push({
...Object.keys(options).map((key) => initialRouteName: compatOptions.initialRouteName,
createNormalizedConfigs(key, options, [], initialRoutes) connectedRoutes: Object.keys(compatOptions.screens),
) });
); }
// sort configs so the most exhaustive is always first to be chosen const screens = compatOptions?.screens;
configs.sort(
(config1, config2) =>
config2.pattern.split('/').length - config1.pattern.split('/').length
);
let remaining = path let remaining = path
.replace(/\/+/g, '/') // Replace multiple slash (//) with single ones .replace(/\/+/g, '/') // Replace multiple slash (//) with single ones
@@ -82,23 +79,104 @@ export default function getStateFromPath(
// Make sure there is a trailing slash // Make sure there is a trailing slash
remaining = remaining.endsWith('/') ? remaining : `${remaining}/`; remaining = remaining.endsWith('/') ? remaining : `${remaining}/`;
if (screens === undefined) {
// When no config is specified, use the path segments as route names
const routes = remaining
.split('/')
.filter(Boolean)
.map((segment, i, self) => {
const name = decodeURIComponent(segment);
if (i === self.length - 1) {
return { name, params: parseQueryParams(path) };
}
return { name };
});
if (routes.length) {
return createNestedStateObject(routes, initialRoutes);
}
return undefined;
}
// Create a normalized configs array which will be easier to use
const configs = ([] as RouteConfig[])
.concat(
...Object.keys(screens).map((key) =>
createNormalizedConfigs(
legacy,
key,
screens as PathConfigMap,
[],
initialRoutes
)
)
)
.sort((a, b) => {
// Sort config so that:
// - the most exhaustive ones are always at the beginning
// - patterns with wildcard are always at the end
// If one of the patterns starts with the other, it's more exhaustive
// So move it up
if (a.pattern.startsWith(b.pattern)) {
return 1;
}
if (b.pattern.startsWith(a.pattern)) {
return 1;
}
const aParts = a.pattern.split('/');
const bParts = b.pattern.split('/');
const aWildcardIndex = aParts.indexOf('*');
const bWildcardIndex = bParts.indexOf('*');
// If only one of the patterns has a wildcard, move it down in the list
if (aWildcardIndex === -1 && bWildcardIndex !== -1) {
return -1;
}
if (aWildcardIndex !== -1 && bWildcardIndex === -1) {
return 1;
}
if (aWildcardIndex === bWildcardIndex) {
// If `b` has more `/`, it's more exhaustive
// So we move it up in the list
return bParts.length - aParts.length;
}
// If the wildcard appears later in the pattern (has higher index), it's more specific
// So we move it up in the list
return bWildcardIndex - aWildcardIndex;
});
if (remaining === '/') { if (remaining === '/') {
// We need to add special handling of empty path so navigation to empty path also works // We need to add special handling of empty path so navigation to empty path also works
// When handling empty path, we should only look at the root level config // When handling empty path, we should only look at the root level config
const match = configs.find( const match = configs.find(
(config) => (config) =>
config.pattern === '' && config.path === '' &&
config.routeNames.every( config.routeNames.every(
// make sure that none of the parent configs have a non-empty path defined // Make sure that none of the parent configs have a non-empty path defined
(name) => !configs.find((c) => c.screen === name)?.pattern (name) => !configs.find((c) => c.screen === name)?.path
) )
); );
if (match) { if (match) {
return createNestedStateObject( return createNestedStateObject(
match.routeNames, match.routeNames.map((name, i, self) => {
initialRoutes, if (i === self.length - 1) {
parseQueryParams(path, match.parse) return { name, params: parseQueryParams(path, match.parse) };
}
return { name };
}),
initialRoutes
); );
} }
@@ -108,73 +186,67 @@ export default function getStateFromPath(
let result: PartialState<NavigationState> | undefined; let result: PartialState<NavigationState> | undefined;
let current: PartialState<NavigationState> | undefined; let current: PartialState<NavigationState> | undefined;
while (remaining) { if (legacy === false) {
let routeNames: string[] | undefined; // If we're not in legacy mode,, we match the whole path against the regex instead of segments
let params: Record<string, any> | undefined; // This makes sure matches such as wildcard will catch any unmatched routes, even if nested
const { routeNames, allParams, remainingPath } = matchAgainstConfigs(
remaining,
configs.map((c) => ({
...c,
// Add `$` to the regex to make sure it matches till end of the path and not just beginning
regex: c.regex ? new RegExp(c.regex.source + '$') : undefined,
}))
);
// Go through all configs, and see if the next path segment matches our regex if (routeNames !== undefined) {
for (const config of configs) { // This will always be empty if full path matched
if (!config.match) { remaining = remainingPath;
continue; current = createNestedStateObject(
createRouteObjects(configs, routeNames, allParams),
initialRoutes
);
result = current;
}
} else {
// In legacy mode, we divide the path into segments and match piece by piece
// This preserves the legacy behaviour, but we should remove it in next major
while (remaining) {
let { routeNames, allParams, remainingPath } = matchAgainstConfigs(
remaining,
configs
);
remaining = remainingPath;
// If we hadn't matched any segments earlier, use the path as route name
if (routeNames === undefined) {
const segments = remaining.split('/');
routeNames = [decodeURIComponent(segments[0])];
segments.shift();
remaining = segments.join('/');
} }
const match = remaining.match(config.match); const state = createNestedStateObject(
createRouteObjects(configs, routeNames, allParams),
initialRoutes
);
// If our regex matches, we need to extract params from the path if (current) {
if (match) { // The state should be nested inside the deepest route we parsed before
routeNames = [...config.routeNames]; while (current?.routes[current.index || 0].state) {
current = current.routes[current.index || 0].state;
const paramPatterns = config.pattern
.split('/')
.filter((p) => p.startsWith(':'));
if (paramPatterns.length) {
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
const key = p.replace(/^:/, '').replace(/\?$/, '');
const value = match[(i + 1) * 2].replace(/\//, ''); // The param segments appear every second item starting from 2 in the regex match result
if (value) {
acc[key] =
config.parse && config.parse[key]
? config.parse[key](value)
: value;
}
return acc;
}, {});
} }
remaining = remaining.replace(match[1], ''); (current as PartialState<NavigationState>).routes[
current?.index || 0
break; ].state = state;
} } else {
} result = state;
// If we hadn't matched any segments earlier, use the path as route name
if (routeNames === undefined) {
const segments = remaining.split('/');
routeNames = [decodeURIComponent(segments[0])];
segments.shift();
remaining = segments.join('/');
}
const state = createNestedStateObject(routeNames, initialRoutes, params);
if (current) {
// The state should be nested inside the deepest route we parsed before
while (current?.routes[current.index || 0].state) {
current = current.routes[current.index || 0].state;
} }
(current as PartialState<NavigationState>).routes[ current = state;
current?.index || 0
].state = state;
} else {
result = state;
} }
current = state;
} }
if (current == null || result == null) { if (current == null || result == null) {
@@ -194,44 +266,127 @@ export default function getStateFromPath(
return result; return result;
} }
function createNormalizedConfigs( const joinPaths = (...paths: string[]): string =>
key: string, ([] as string[])
routeConfig: Options, .concat(...paths.map((p) => p.split('/')))
.filter(Boolean)
.join('/');
const matchAgainstConfigs = (remaining: string, configs: RouteConfig[]) => {
let routeNames: string[] | undefined;
let allParams: Record<string, any> | undefined;
let remainingPath = remaining;
// Go through all configs, and see if the next path segment matches our regex
for (const config of configs) {
if (!config.regex) {
continue;
}
const match = remainingPath.match(config.regex);
// If our regex matches, we need to extract params from the path
if (match) {
routeNames = [...config.routeNames];
const paramPatterns = config.pattern
.split('/')
.filter((p) => p.startsWith(':'));
if (paramPatterns.length) {
allParams = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
const value = match![(i + 1) * 2].replace(/\//, ''); // The param segments appear every second item starting from 2 in the regex match result
acc[p] = value;
return acc;
}, {});
}
remainingPath = remainingPath.replace(match[1], '');
break;
}
}
return { routeNames, allParams, remainingPath };
};
const createNormalizedConfigs = (
legacy: boolean,
screen: string,
routeConfig: PathConfigMap,
routeNames: string[] = [], routeNames: string[] = [],
initials: InitialRouteConfig[] initials: InitialRouteConfig[],
): RouteConfig[] { parentPattern?: string
): RouteConfig[] => {
const configs: RouteConfig[] = []; const configs: RouteConfig[] = [];
routeNames.push(key); routeNames.push(screen);
const value = routeConfig[key]; const config = routeConfig[screen];
if (typeof value === 'string') { if (typeof config === 'string') {
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
configs.push(createConfigItem(key, routeNames, value)); const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
} else if (typeof value === 'object') {
configs.push(createConfigItem(legacy, screen, routeNames, pattern, config));
} else if (typeof config === 'object') {
let pattern: string | undefined;
// if an object is specified as the value (e.g. Foo: { ... }), // if an object is specified as the value (e.g. Foo: { ... }),
// it can have `path` property and // it can have `path` property and
// it could have `screens` prop which has nested configs // it could have `screens` prop which has nested configs
if (typeof value.path === 'string') { if (typeof config.path === 'string') {
configs.push(createConfigItem(key, routeNames, value.path, value.parse)); if (legacy) {
pattern =
config.exact !== true && parentPattern
? joinPaths(parentPattern, config.path)
: config.path;
} else {
if (config.exact && config.path === undefined) {
throw new Error(
"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`."
);
}
pattern =
config.exact !== true
? joinPaths(parentPattern || '', config.path || '')
: config.path || '';
}
configs.push(
createConfigItem(
legacy,
screen,
routeNames,
pattern,
config.path,
config.parse
)
);
} }
if (value.screens) { if (config.screens) {
// property `initialRouteName` without `screens` has no purpose // property `initialRouteName` without `screens` has no purpose
if (value.initialRouteName) { if (config.initialRouteName) {
initials.push({ initials.push({
initialRouteName: value.initialRouteName, initialRouteName: config.initialRouteName,
connectedRoutes: Object.keys(value.screens), connectedRoutes: Object.keys(config.screens),
}); });
} }
Object.keys(value.screens).forEach((nestedConfig) => {
Object.keys(config.screens).forEach((nestedConfig) => {
const result = createNormalizedConfigs( const result = createNormalizedConfigs(
legacy,
nestedConfig, nestedConfig,
value.screens as Options, config.screens as PathConfigMap,
routeNames, routeNames,
initials initials,
pattern ?? parentPattern
); );
configs.push(...result); configs.push(...result);
}); });
} }
@@ -240,56 +395,69 @@ function createNormalizedConfigs(
routeNames.pop(); routeNames.pop();
return configs; return configs;
} };
function createConfigItem( const createConfigItem = (
legacy: boolean,
screen: string, screen: string,
routeNames: string[], routeNames: string[],
pattern: string, pattern: string,
path: string,
parse?: ParseConfig parse?: ParseConfig
): RouteConfig { ): RouteConfig => {
const match = pattern // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
pattern = pattern.split('/').filter(Boolean).join('/');
const regex = pattern
? new RegExp( ? new RegExp(
`^(${pattern `^(${pattern
.split('/') .split('/')
.map((it) => { .map((it) => {
if (legacy && it === '*') {
throw new Error(
"Please update your config to the new format to use wildcard pattern ('*'). https://reactnavigation.org/docs/configuring-links/#updating-config"
);
}
if (it.startsWith(':')) { if (it.startsWith(':')) {
return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`; return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`;
} }
return `${escape(it)}\\/`; return `${it === '*' ? '.*' : escape(it)}\\/`;
}) })
.join('')})` .join('')})`
) )
: null; : undefined;
return { return {
screen, screen,
match, regex,
pattern, pattern,
path,
// The routeNames array is mutated, so copy it to keep the current state // The routeNames array is mutated, so copy it to keep the current state
routeNames: [...routeNames], routeNames: [...routeNames],
parse, parse,
}; };
} };
function findParseConfigForRoute( const findParseConfigForRoute = (
routeName: string, routeName: string,
flatConfig: RouteConfig[] flatConfig: RouteConfig[]
): ParseConfig | undefined { ): ParseConfig | undefined => {
for (const config of flatConfig) { for (const config of flatConfig) {
if (routeName === config.routeNames[config.routeNames.length - 1]) { if (routeName === config.routeNames[config.routeNames.length - 1]) {
return config.parse; return config.parse;
} }
} }
return undefined;
}
// tries to find an initial route connected with the one passed return undefined;
function findInitialRoute( };
// Try to find an initial route connected with the one passed
const findInitialRoute = (
routeName: string, routeName: string,
initialRoutes: InitialRouteConfig[] initialRoutes: InitialRouteConfig[]
): string | undefined { ): string | undefined => {
for (const config of initialRoutes) { for (const config of initialRoutes) {
if (config.connectedRoutes.includes(routeName)) { if (config.connectedRoutes.includes(routeName)) {
return config.initialRouteName === routeName return config.initialRouteName === routeName
@@ -298,28 +466,25 @@ function findInitialRoute(
} }
} }
return undefined; return undefined;
} };
// returns state object with values depending on whether // returns state object with values depending on whether
// it is the end of state and if there is initialRoute for this level // it is the end of state and if there is initialRoute for this level
function createStateObject( const createStateObject = (
initialRoute: string | undefined, initialRoute: string | undefined,
routeName: string, routeName: string,
isEmpty: boolean, params: Record<string, any> | undefined,
params?: Record<string, any> | undefined isEmpty: boolean
): InitialState { ): InitialState => {
if (isEmpty) { if (isEmpty) {
if (initialRoute) { if (initialRoute) {
return { return {
index: 1, index: 1,
routes: [ routes: [{ name: initialRoute }, { name: routeName as string, params }],
{ name: initialRoute },
{ name: routeName as string, ...(params && { params }) },
],
}; };
} else { } else {
return { return {
routes: [{ name: routeName as string, ...(params && { params }) }], routes: [{ name: routeName as string, params }],
}; };
} }
} else { } else {
@@ -328,53 +493,102 @@ function createStateObject(
index: 1, index: 1,
routes: [ routes: [
{ name: initialRoute }, { name: initialRoute },
{ name: routeName as string, state: { routes: [] } }, { name: routeName as string, params, state: { routes: [] } },
], ],
}; };
} else { } else {
return { routes: [{ name: routeName as string, state: { routes: [] } }] }; return {
routes: [{ name: routeName as string, params, state: { routes: [] } }],
};
} }
} }
} };
function createNestedStateObject( const createNestedStateObject = (
routeNames: string[], routes: { name: string; params?: object }[],
initialRoutes: InitialRouteConfig[], initialRoutes: InitialRouteConfig[]
params: object | undefined ) => {
) {
let state: InitialState; let state: InitialState;
let routeName = routeNames.shift() as string; let route = routes.shift() as { name: string; params?: object };
let initialRoute = findInitialRoute(routeName, initialRoutes); let initialRoute = findInitialRoute(route.name, initialRoutes);
state = createStateObject( state = createStateObject(
initialRoute, initialRoute,
routeName, route.name,
routeNames.length === 0, route.params,
params routes.length === 0
); );
if (routeNames.length > 0) { if (routes.length > 0) {
let nestedState = state; let nestedState = state;
while ((routeName = routeNames.shift() as string)) { while ((route = routes.shift() as { name: string; params?: object })) {
initialRoute = findInitialRoute(routeName, initialRoutes); initialRoute = findInitialRoute(route.name, initialRoutes);
nestedState.routes[nestedState.index || 0].state = createStateObject(
const nestedStateIndex =
nestedState.index || nestedState.routes.length - 1;
nestedState.routes[nestedStateIndex].state = createStateObject(
initialRoute, initialRoute,
routeName, route.name,
routeNames.length === 0, route.params,
params routes.length === 0
); );
if (routeNames.length > 0) {
nestedState = nestedState.routes[nestedState.index || 0] if (routes.length > 0) {
nestedState = nestedState.routes[nestedStateIndex]
.state as InitialState; .state as InitialState;
} }
} }
} }
return state; return state;
} };
function findFocusedRoute(state: InitialState) { const createRouteObjects = (
configs: RouteConfig[],
routeNames: string[],
allParams?: Record<string, any>
) =>
routeNames.map((name) => {
const config = configs.find((c) => c.screen === name);
let params: object | undefined;
if (allParams && config?.path) {
const pattern = config.path;
if (pattern) {
const paramPatterns = pattern
.split('/')
.filter((p) => p.startsWith(':'));
if (paramPatterns.length) {
params = paramPatterns.reduce<Record<string, any>>((acc, p) => {
const key = p.replace(/^:/, '').replace(/\?$/, '');
const value = allParams![p];
if (value) {
acc[key] =
config.parse && config.parse[key]
? config.parse[key](value)
: value;
}
return acc;
}, {});
}
}
}
if (params && Object.keys(params).length) {
return { name, params };
}
return { name };
});
const findFocusedRoute = (state: InitialState) => {
let current: InitialState | undefined = state; let current: InitialState | undefined = state;
while (current?.routes[current.index || 0].state) { while (current?.routes[current.index || 0].state) {
@@ -387,12 +601,12 @@ function findFocusedRoute(state: InitialState) {
]; ];
return route; return route;
} };
function parseQueryParams( const parseQueryParams = (
path: string, path: string,
parseConfig?: Record<string, (value: string) => any> parseConfig?: Record<string, (value: string) => any>
) { ) => {
const query = path.split('?')[1]; const query = path.split('?')[1];
const params = queryString.parse(query); const params = queryString.parse(query);
@@ -405,4 +619,4 @@ function parseQueryParams(
} }
return Object.keys(params).length ? params : undefined; return Object.keys(params).length ? params : undefined;
} };

View File

@@ -7,6 +7,8 @@ export { default as NavigationHelpersContext } from './NavigationHelpersContext'
export { default as NavigationContext } from './NavigationContext'; export { default as NavigationContext } from './NavigationContext';
export { default as NavigationRouteContext } from './NavigationRouteContext'; export { default as NavigationRouteContext } from './NavigationRouteContext';
export { default as CurrentRenderContext } from './CurrentRenderContext';
export { default as useNavigationBuilder } from './useNavigationBuilder'; export { default as useNavigationBuilder } from './useNavigationBuilder';
export { default as useNavigation } from './useNavigation'; export { default as useNavigation } from './useNavigation';
export { default as useRoute } from './useRoute'; export { default as useRoute } from './useRoute';
@@ -18,4 +20,6 @@ export { default as getStateFromPath } from './getStateFromPath';
export { default as getPathFromState } from './getPathFromState'; export { default as getPathFromState } from './getPathFromState';
export { default as getActionFromState } from './getActionFromState'; export { default as getActionFromState } from './getActionFromState';
export { default as getFocusedRouteNameFromRoute } from './getFocusedRouteNameFromRoute';
export * from './types'; export * from './types';

View File

@@ -0,0 +1,7 @@
/**
* Compare two arrays with primitive values as the content.
* We need to make sure that both values and order match.
*/
export default function isArrayEqual(a: any[], b: any[]) {
return a.length === b.length && a.every((it, index) => it === b[index]);
}

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import type * as React from 'react';
import { import type {
DefaultRouterOptions, DefaultRouterOptions,
NavigationState, NavigationState,
NavigationAction, NavigationAction,
@@ -10,7 +10,7 @@ import {
} from '@react-navigation/routers'; } from '@react-navigation/routers';
export type DefaultNavigatorOptions< export type DefaultNavigatorOptions<
ScreenOptions extends object ScreenOptions extends {}
> = DefaultRouterOptions & { > = DefaultRouterOptions & {
/** /**
* Children React Elements to extract the route configuration from. * Children React Elements to extract the route configuration from.
@@ -61,7 +61,7 @@ export type EventArg<
preventDefault(): void; preventDefault(): void;
} }
: {}) & : {}) &
(Data extends undefined ? {} : { readonly data: Data }); (undefined extends Data ? { readonly data?: Data } : { readonly data: Data });
export type EventListenerCallback< export type EventListenerCallback<
EventMap extends EventMapBase, EventMap extends EventMapBase,
@@ -107,8 +107,8 @@ export type EventEmitter<EventMap extends EventMapBase> = {
} & (EventMap[EventName]['canPreventDefault'] extends true } & (EventMap[EventName]['canPreventDefault'] extends true
? { canPreventDefault: true } ? { canPreventDefault: true }
: {}) & : {}) &
(EventMap[EventName]['data'] extends undefined (undefined extends EventMap[EventName]['data']
? {} ? { data?: EventMap[EventName]['data'] }
: { data: EventMap[EventName]['data'] }) : { data: EventMap[EventName]['data'] })
): EventArg< ): EventArg<
EventName, EventName,
@@ -152,7 +152,7 @@ type NavigationHelpersCommon<
* @param [params] Params object for the route. * @param [params] Params object for the route.
*/ */
navigate<RouteName extends keyof ParamList>( navigate<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends undefined | any ...args: undefined extends ParamList[RouteName]
? [RouteName] | [RouteName, ParamList[RouteName]] ? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]] : [RouteName, ParamList[RouteName]]
): void; ): void;
@@ -250,7 +250,7 @@ export type NavigationProp<
ParamList extends ParamListBase, ParamList extends ParamListBase,
RouteName extends keyof ParamList = string, RouteName extends keyof ParamList = string,
State extends NavigationState = NavigationState, State extends NavigationState = NavigationState,
ScreenOptions extends object = {}, ScreenOptions extends {} = {},
EventMap extends EventMapBase = {} EventMap extends EventMapBase = {}
> = NavigationHelpersCommon<ParamList, State> & { > = NavigationHelpersCommon<ParamList, State> & {
/** /**
@@ -275,8 +275,13 @@ export type RouteProp<
ParamList extends ParamListBase, ParamList extends ParamListBase,
RouteName extends keyof ParamList RouteName extends keyof ParamList
> = Omit<Route<Extract<RouteName, string>>, 'params'> & > = Omit<Route<Extract<RouteName, string>>, 'params'> &
(ParamList[RouteName] extends undefined (undefined extends ParamList[RouteName]
? {} ? {
/**
* Params for this route
*/
params?: ParamList[RouteName];
}
: { : {
/** /**
* Params for this route * Params for this route
@@ -321,7 +326,7 @@ export type Descriptor<
ParamList extends ParamListBase, ParamList extends ParamListBase,
RouteName extends keyof ParamList = string, RouteName extends keyof ParamList = string,
State extends NavigationState = NavigationState, State extends NavigationState = NavigationState,
ScreenOptions extends object = {}, ScreenOptions extends {} = {},
EventMap extends EventMapBase = {} EventMap extends EventMapBase = {}
> = { > = {
/** /**
@@ -360,7 +365,7 @@ export type RouteConfig<
ParamList extends ParamListBase, ParamList extends ParamListBase,
RouteName extends keyof ParamList, RouteName extends keyof ParamList,
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase EventMap extends EventMapBase
> = { > = {
/** /**
@@ -410,8 +415,43 @@ export type RouteConfig<
} }
); );
export type NavigationContainerEventMap = {
/**
* Event which fires when the navigation state changes.
*/
state: {
data: {
/**
* The updated state object after the state change.
*/
state: NavigationState | PartialState<NavigationState> | undefined;
};
};
/**
* Event which fires when current options changes.
*/
options: { data: { options: object } };
/**
* Event which fires when an action is dispatched.
* Only intended for debugging purposes, don't use it for app logic.
* This event will be emitted before state changes have been applied.
*/
__unsafe_action__: {
data: {
/**
* The action object which was dispatched.
*/
action: NavigationAction;
/**
* Whether the action was a no-op, i.e. resulted any state changes.
*/
noop: boolean;
};
};
};
export type NavigationContainerRef = NavigationHelpers<ParamListBase> & export type NavigationContainerRef = NavigationHelpers<ParamListBase> &
EventConsumer<{ state: { data: { state: NavigationState } } }> & { EventConsumer<NavigationContainerEventMap> & {
/** /**
* Reset the navigation state of the root navigator to the provided state. * Reset the navigation state of the root navigator to the provided state.
* *
@@ -422,12 +462,20 @@ export type NavigationContainerRef = NavigationHelpers<ParamListBase> &
* Get the rehydrated navigation state of the navigation tree. * Get the rehydrated navigation state of the navigation tree.
*/ */
getRootState(): NavigationState; getRootState(): NavigationState;
/**
* Get the currently focused navigation route.
*/
getCurrentRoute(): Route<string> | undefined;
/**
* Get the currently focused route's options.
*/
getCurrentOptions(): object | undefined;
}; };
export type TypedNavigator< export type TypedNavigator<
ParamList extends ParamListBase, ParamList extends ParamListBase,
State extends NavigationState, State extends NavigationState,
ScreenOptions extends object, ScreenOptions extends {},
EventMap extends EventMapBase, EventMap extends EventMapBase,
Navigator extends React.ComponentType<any> Navigator extends React.ComponentType<any>
> = { > = {
@@ -435,25 +483,14 @@ export type TypedNavigator<
* Navigator component which manages the child screens. * Navigator component which manages the child screens.
*/ */
Navigator: React.ComponentType< Navigator: React.ComponentType<
Omit< Omit<React.ComponentProps<Navigator>, keyof DefaultNavigatorOptions<any>> &
React.ComponentProps<Navigator>, Omit<DefaultNavigatorOptions<ScreenOptions>, 'initialRouteName'> & {
'initialRouteName' | 'screenOptions' /**
> & { * Name of the route to focus by on initial render.
/** * If not specified, usually the first route is used.
* Name of the route to focus by on initial render. */
* If not specified, usually the first route is used. initialRouteName?: keyof ParamList;
*/ }
initialRouteName?: keyof ParamList;
/**
* Default options for all screens under this navigator.
*/
screenOptions?:
| ScreenOptions
| ((props: {
route: RouteProp<ParamList, keyof ParamList>;
navigation: any;
}) => ScreenOptions);
}
>; >;
/** /**
* Component used for specifying route configuration. * Component used for specifying route configuration.
@@ -462,3 +499,16 @@ export type TypedNavigator<
_: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap> _: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap>
) => null; ) => null;
}; };
export type PathConfig = {
path?: string;
exact?: boolean;
parse?: Record<string, (value: string) => any>;
stringify?: Record<string, (value: any) => string>;
screens?: PathConfigMap;
initialRouteName?: string;
};
export type PathConfigMap = {
[routeName: string]: string | PathConfig;
};

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { ChildActionListener } from './NavigationBuilderContext'; import type { ChildActionListener } from './NavigationBuilderContext';
/** /**
* Hook which lets child navigators add action listeners. * Hook which lets child navigators add action listeners.

Some files were not shown because too many files have changed in this diff Show More