Compare commits

..

12 Commits

Author SHA1 Message Date
Kyle Fang
073f04b6eb test: rename screen 2021-06-27 09:54:36 +08:00
Kyle Fang
ed37e6aec0 docs: add comments on sort 2021-06-27 07:37:25 +08:00
Kyle Fang
f80ed7790e Merge branch 'main' of github.com:react-navigation/react-navigation into fix/sortOnPaths 2021-06-25 18:25:54 +08:00
Cedric van Putten
4c16083d51 chore: upgrade to expo-github-actions v6 2021-06-23 15:40:22 +02:00
Satyajit Sahoo
e7631ea239 chore: comment on closed issues regarding watching 2021-06-15 03:32:04 +02:00
Kyle Fang
32fe3f17d0 test: add case on :params 2021-06-14 15:39:37 +08:00
Kyle Fang
b7c5305453 fix: move :hello to bottom along with * 2021-06-14 15:38:36 +08:00
Max Schmitt
2ee435be3a chore: add nvmrc for using LTS Node.js version (#9668)
This should fix the Netlify builds too.
See here for reference: https://github.com/nvm-sh/nvm#nvmrc

The integration tests are failing but they are getting fixed in #9667.
2021-06-13 17:39:55 +02:00
Max Schmitt
016e7920df test: upgrade to the new Playwright test-runner (#9667)
Hey!

I made the following changes:

- Replaced Jest by the new Playwright test-runner
- Disabled the Jest linting rules for the Playwright e2e tests
- Rewrote the tests to the new test-runner
- Adjusted `Link.test.ts` which should be less flaky
- The tests run now across all three browsers: Chromium, Firefox, and WebKit

See here for reference about the new test-runner: https://playwright.dev/docs/test-intro

I extracted a fix for Netlify in #9668.

Let me know if you have any questions.
2021-06-13 17:38:46 +02:00
Satyajit Sahoo
26ba019155 chore: publish
- @react-navigation/bottom-tabs@6.0.0-next.19
 - @react-navigation/core@6.0.0-next.14
 - @react-navigation/devtools@6.0.0-next.15
 - @react-navigation/drawer@6.0.0-next.18
 - @react-navigation/elements@1.0.0-next.18
 - flipper-plugin-react-navigation@1.2.0
 - @react-navigation/material-bottom-tabs@6.0.0-next.15
 - @react-navigation/material-top-tabs@6.0.0-next.15
 - @react-navigation/native-stack@6.0.0-next.8
 - @react-navigation/native@6.0.0-next.14
 - @react-navigation/routers@6.0.0-next.5
 - @react-navigation/stack@6.0.0-next.26
2021-06-11 01:15:43 +02:00
Satyajit Sahoo
97772affa3 feat: show stack trace in the flipper plugin 2021-06-11 01:09:02 +02:00
Satyajit Sahoo
67f6950c14 chore: upgrade dependencies 2021-06-05 07:33:26 +02:00
118 changed files with 3813 additions and 3944 deletions

View File

@@ -75,9 +75,13 @@ jobs:
- 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
# Yarn does not execute the postinstall scripts if the package is in the cache
- run:
name: Install browsers
command: yarn playwright install
- run: - run:
name: Run integration tests name: Run integration tests
command: yarn example test --maxWorkers=2 command: yarn example test:e2e
build-packages: build-packages:
executor: default executor: default

View File

@@ -26,5 +26,11 @@
"rules": { "rules": {
"simple-import-sort/imports": "error", "simple-import-sort/imports": "error",
"simple-import-sort/exports": "error" "simple-import-sort/exports": "error"
} },
"overrides": [{
"files":["example/e2e/tests/*.ts"],
"rules": {
"jest/*": 0
}
}]
} }

31
.github/workflows/closed-issue.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Comment on closed issue
on:
issue_comment:
types: [created]
jobs:
closed-issue:
runs-on: ubuntu-latest
if: ${{ github.event.issue.state == 'closed' }}
steps:
- uses: actions/github-script@v3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const body = "Hey! This issue is closed and isn't watched by the core team. You are welcome to discuss the issue with others in this thread, but if you think this issue is still valid and needs to be tracked, please open a new issue with a repro.";
const comments = await github.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
if (comments.data.some(comment => comment.body === body)) {
return;
}
await github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body,
});

View File

@@ -16,10 +16,9 @@ jobs:
node-version: 14.x node-version: 14.x
- name: Setup Expo - name: Setup Expo
uses: expo/expo-github-action@v5 uses: expo/expo-github-action@v6
with: with:
expo-token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
expo-cache: true
- name: Restore yarn cache - name: Restore yarn cache
id: yarn-cache id: yarn-cache

View File

@@ -19,10 +19,9 @@ jobs:
node-version: 14.x node-version: 14.x
- name: Setup Expo - name: Setup Expo
uses: expo/expo-github-action@v5 uses: expo/expo-github-action@v6
with: with:
expo-token: ${{ secrets.EXPO_TOKEN }} token: ${{ secrets.EXPO_TOKEN }}
expo-cache: true
- name: Restore yarn cache - name: Restore yarn cache
id: yarn-cache id: yarn-cache

1
.nvmrc Normal file
View File

@@ -0,0 +1 @@
lts/*

File diff suppressed because one or more lines are too long

View File

@@ -2,4 +2,4 @@
# yarn lockfile v1 # yarn lockfile v1
yarn-path ".yarn/releases/yarn-1.18.0.js" yarn-path ".yarn/releases/yarn-1.22.10.cjs"

View File

@@ -4,7 +4,7 @@
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root * <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree. * directory of this source tree.
*/ */
package com.reactnavigation; package org.reactnavigation.example;
import android.content.Context; import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient; import com.facebook.flipper.android.AndroidFlipperClient;
@@ -66,4 +66,4 @@ public class ReactNativeFlipper {
} }
} }
} }
} }

View File

@@ -1,44 +0,0 @@
import { page } from '../config/setup-playwright';
beforeEach(async () => {
await page.click('[data-testid=LinkComponent]');
});
const getPageInfo = async () => ({
url: await page.evaluate(() => location.pathname + location.search),
title: await page.evaluate(() => document.title),
heading: (await page.accessibility.snapshot())?.children?.find(
(it) => it.role === 'heading'
)?.name,
});
it('loads the article page', async () => {
const { url, title, heading } = await getPageInfo();
expect(url).toBe('/link-component/article/gandalf');
expect(title).toBe('Article by Gandalf - React Navigation Example');
expect(heading).toBe('Article by Gandalf');
});
it('goes to the album page and goes back', async () => {
await page.click('[href="/link-component/music"]');
{
const { url, title, heading } = await getPageInfo();
expect(url).toBe('/link-component/music');
expect(title).toBe('Albums - React Navigation Example');
expect(heading).toBe('Albums');
}
await page.click('[aria-label="Article by Gandalf, back"]');
await page.waitForNavigation();
{
const { url, title, heading } = await getPageInfo();
expect(url).toBe('/link-component/article/gandalf');
expect(title).toBe('Article by Gandalf - React Navigation Example');
expect(heading).toBe('Article by Gandalf');
}
});

View File

@@ -1,28 +0,0 @@
/* eslint-env jest */
import { Browser, BrowserContext, chromium, Page } from 'playwright';
let browser: Browser;
let context: BrowserContext;
let page: Page;
beforeAll(async () => {
browser = await chromium.launch();
});
afterAll(async () => {
await browser.close();
});
beforeEach(async () => {
context = await browser.newContext();
page = await context.newPage();
await page.goto('http://localhost:3579');
});
afterEach(async () => {
await context.close();
});
export { browser, context, page };

View File

@@ -0,0 +1,28 @@
import type { PlaywrightTestConfig } from '@playwright/test';
import path from 'path';
const config: PlaywrightTestConfig = {
testDir: path.join(__dirname, 'tests'),
globalSetup: require.resolve('./config/setup-server.ts'),
globalTeardown: require.resolve('./config/teardown-server.ts'),
workers: 1,
reporter: 'list',
projects: [
{
name: 'Chromium',
use: { browserName: 'chromium' },
},
{
name: 'Firefox',
use: { browserName: 'firefox' },
},
{
name: 'WebKit',
use: { browserName: 'webkit' },
},
],
};
export default config;

View File

@@ -0,0 +1,43 @@
import type { Page } from '@playwright/test';
import { expect, it } from './baseFixture';
it.beforeEach(async ({ page }) => {
await page.click('[data-testid=LinkComponent]');
});
const waitAndAssertPageHeading = async (
page: Page,
expectedHeading: string
) => {
await page.waitForSelector(`text=${expectedHeading}`);
const heading = (await page.accessibility.snapshot())?.children?.find(
(it) => it.role === 'heading'
)?.name;
expect(heading).toBe(expectedHeading);
};
it('loads the article page', async ({ page }) => {
await page.waitForURL('**/link-component/article/gandalf');
expect(await page.title()).toBe(
'Article by Gandalf - React Navigation Example'
);
await waitAndAssertPageHeading(page, 'Article by Gandalf');
});
it('goes to the album page and goes back', async ({ page }) => {
await page.click('[href="/link-component/music"]');
await page.waitForURL('**/link-component/music');
expect(await page.title()).toBe('Albums - React Navigation Example');
await waitAndAssertPageHeading(page, 'Albums');
await page.click('[aria-label="Article by Gandalf, back"]');
await page.waitForNavigation();
await page.waitForURL('**/link-component/article/gandalf');
expect(await page.title()).toBe(
'Article by Gandalf - React Navigation Example'
);
await waitAndAssertPageHeading(page, 'Article by Gandalf');
});

View File

@@ -0,0 +1,11 @@
import { test as baseTest } from '@playwright/test';
const test = baseTest.extend({
page: async ({ page }, use) => {
await page.goto('http://localhost:3579');
await use(page);
},
});
export const it = test;
export const expect = test.expect;

View File

@@ -1,6 +1,6 @@
import { page } from '../config/setup-playwright'; import { expect, it } from './baseFixture';
it('loads the example app', async () => { it('loads the example app', async ({ page }) => {
const snapshot = await page.accessibility.snapshot(); const snapshot = await page.accessibility.snapshot();
expect( expect(

View File

@@ -1,3 +1,4 @@
import { expect, test as it } from '@playwright/test';
import cheerio from 'cheerio'; import cheerio from 'cheerio';
import fetch from 'node-fetch'; import fetch from 'node-fetch';

View File

@@ -23,15 +23,15 @@ PODS:
- UMImageLoaderInterface - UMImageLoaderInterface
- EXKeepAwake (9.1.2): - EXKeepAwake (9.1.2):
- UMCore - UMCore
- EXPermissions (12.0.0): - EXPermissions (12.0.1):
- UMCore - UMCore
- UMPermissionsInterface - UMPermissionsInterface
- EXSplashScreen (0.10.0): - EXSplashScreen (0.10.2):
- React-Core - React-Core
- UMCore - UMCore
- EXStructuredHeaders (1.0.1): - EXStructuredHeaders (1.0.1):
- UMCore - UMCore
- EXUpdates (0.5.4): - EXUpdates (0.5.5):
- EXStructuredHeaders - EXStructuredHeaders
- React-Core - React-Core
- UMCore - UMCore
@@ -271,9 +271,9 @@ PODS:
- React - React
- react-native-flipper (0.80.0): - react-native-flipper (0.80.0):
- React-Core - React-Core
- react-native-safe-area-context (3.2.0): - react-native-pager-view (5.1.10):
- React-Core - React-Core
- react-native-viewpager (5.0.12): - react-native-safe-area-context (3.2.0):
- React-Core - React-Core
- React-RCTActionSheet (0.63.4): - React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4) - React-Core/RCTActionSheetHeaders (= 0.63.4)
@@ -335,13 +335,13 @@ PODS:
- React-Core (= 0.63.4) - React-Core (= 0.63.4)
- React-cxxreact (= 0.63.4) - React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4) - React-jsi (= 0.63.4)
- RNCAsyncStorage (1.15.1): - RNCAsyncStorage (1.15.5):
- React-Core - React-Core
- RNCMaskedView (0.2.4): - RNCMaskedView (0.2.4):
- React-Core - React-Core
- RNGestureHandler (1.10.3): - RNGestureHandler (1.10.3):
- React-Core - React-Core
- RNReanimated (2.1.0): - RNReanimated (2.2.0):
- DoubleConversion - DoubleConversion
- FBLazyVector - FBLazyVector
- FBReactNativeSpec - FBReactNativeSpec
@@ -370,8 +370,9 @@ PODS:
- React-RCTVibration - React-RCTVibration
- ReactCommon/turbomodule/core - ReactCommon/turbomodule/core
- Yoga - Yoga
- RNScreens (3.0.0): - RNScreens (3.3.0):
- React-Core - React-Core
- React-RCTImage
- RNVectorIcons (8.1.0): - RNVectorIcons (8.1.0):
- React-Core - React-Core
- UMAppLoader (2.1.0) - UMAppLoader (2.1.0)
@@ -451,8 +452,8 @@ DEPENDENCIES:
- React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`) - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-appearance (from `../../node_modules/react-native-appearance`) - react-native-appearance (from `../../node_modules/react-native-appearance`)
- react-native-flipper (from `../../node_modules/react-native-flipper`) - react-native-flipper (from `../../node_modules/react-native-flipper`)
- react-native-pager-view (from `../../node_modules/react-native-pager-view`)
- 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-native-viewpager (from `../node_modules/react-native-pager-view`)
- 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`)
- React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`) - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`)
@@ -464,7 +465,7 @@ DEPENDENCIES:
- React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`) - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`) - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../../node_modules/@react-native-async-storage/async-storage`)" - "RNCAsyncStorage (from `../../node_modules/@react-native-async-storage/async-storage`)"
- "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" - "RNCMaskedView (from `../../node_modules/@react-native-masked-view/masked-view`)"
- 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`)
@@ -558,10 +559,10 @@ EXTERNAL SOURCES:
:path: "../../node_modules/react-native-appearance" :path: "../../node_modules/react-native-appearance"
react-native-flipper: react-native-flipper:
:path: "../../node_modules/react-native-flipper" :path: "../../node_modules/react-native-flipper"
react-native-pager-view:
:path: "../../node_modules/react-native-pager-view"
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-native-viewpager:
:path: "../node_modules/react-native-pager-view"
React-RCTActionSheet: React-RCTActionSheet:
:path: "../../node_modules/react-native/Libraries/ActionSheetIOS" :path: "../../node_modules/react-native/Libraries/ActionSheetIOS"
React-RCTAnimation: React-RCTAnimation:
@@ -585,7 +586,7 @@ EXTERNAL SOURCES:
RNCAsyncStorage: RNCAsyncStorage:
:path: "../../node_modules/@react-native-async-storage/async-storage" :path: "../../node_modules/@react-native-async-storage/async-storage"
RNCMaskedView: RNCMaskedView:
:path: "../node_modules/@react-native-masked-view/masked-view" :path: "../../node_modules/@react-native-masked-view/masked-view"
RNGestureHandler: RNGestureHandler:
:path: "../../node_modules/react-native-gesture-handler" :path: "../../node_modules/react-native-gesture-handler"
RNReanimated: RNReanimated:
@@ -635,10 +636,10 @@ SPEC CHECKSUMS:
EXFont: d6fb79f9863120f0d0b26b0c2d1453bc9511e9df EXFont: d6fb79f9863120f0d0b26b0c2d1453bc9511e9df
EXImageLoader: da941c9399e01ec28f2d5b270bdd21f2c8ca596c EXImageLoader: da941c9399e01ec28f2d5b270bdd21f2c8ca596c
EXKeepAwake: d4e4a3ed8c1c4fd940dd62fc5a8be2a190371fd4 EXKeepAwake: d4e4a3ed8c1c4fd940dd62fc5a8be2a190371fd4
EXPermissions: 67ff17d3c12ea06066492dde4242f8047658fd62 EXPermissions: 8f8c1c05580c4e02d4ee2c8dd74bfe173ff6a723
EXSplashScreen: 9d79ea338b7bb2ee94df51723870bac70b408d44 EXSplashScreen: a9baaf4fa866003884c90ba049f18760d6a8ce39
EXStructuredHeaders: be834496a4d9fd0069cd12ec1cc57b31c6d3b256 EXStructuredHeaders: be834496a4d9fd0069cd12ec1cc57b31c6d3b256
EXUpdates: e191b83e00d3e7ebfd7db3986806ceca09b7b322 EXUpdates: efe0e8c514dcff06a8fd0b63be6019a6365fb9c7
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
Flipper: d3da1aa199aad94455ae725e9f3aa43f3ec17021 Flipper: d3da1aa199aad94455ae725e9f3aa43f3ec17021
@@ -664,8 +665,8 @@ SPEC CHECKSUMS:
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
react-native-appearance: 0f0e5fc2fcef70e03d48c8fe6b00b9158c2ba8aa react-native-appearance: 0f0e5fc2fcef70e03d48c8fe6b00b9158c2ba8aa
react-native-flipper: 5a9d5959364fca6a8a9658d941343774cb197857 react-native-flipper: 5a9d5959364fca6a8a9658d941343774cb197857
react-native-pager-view: 967d50ce0f1b72e434a2d9f3b739ddbf7d5bbf83
react-native-safe-area-context: f0906bf8bc9835ac9a9d3f97e8bde2a997d8da79 react-native-safe-area-context: f0906bf8bc9835ac9a9d3f97e8bde2a997d8da79
react-native-viewpager: 98a850d1c7ac6263122d82618a77062a5f427073
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336 React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0 React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
@@ -676,11 +677,11 @@ SPEC CHECKSUMS:
React-RCTText: 5c51df3f08cb9dedc6e790161195d12bac06101c React-RCTText: 5c51df3f08cb9dedc6e790161195d12bac06101c
React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d
ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b
RNCAsyncStorage: 08719e311ab90492c2dafd6d6fb7ffb396493638 RNCAsyncStorage: 56a3355a10b5d660c48c6e37325ac85ebfd09885
RNCMaskedView: fc29d354a40316a990e8fb46391f08aea829c3aa RNCMaskedView: fc29d354a40316a990e8fb46391f08aea829c3aa
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211 RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNReanimated: 70f662b5232dd5d19ccff581e919a54ea73df51c RNReanimated: d9da990fc90123f4ffbfdda93d00fc15174863a8
RNScreens: e8e8dd0588b5da0ab57dcca76ab9b2d8987757e0 RNScreens: bf59f17fbf001f1025243eeed5f19419d3c11ef2
RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4 RNVectorIcons: 31cebfcf94e8cf8686eb5303ae0357da64d7a5a4
UMAppLoader: fe2708bb0ac5cd70052bc207d06aa3b7e72b9e97 UMAppLoader: fe2708bb0ac5cd70052bc207d06aa3b7e72b9e97
UMBarCodeScannerInterface: 79f92bea5f7af39b381a4c82298105ceb537408a UMBarCodeScannerInterface: 79f92bea5f7af39b381a4c82298105ceb537408a

View File

@@ -1,6 +0,0 @@
module.exports = {
testRegex: '/__integration_tests__/.*\\.(test|spec)\\.(js|tsx?)$',
globalSetup: './e2e/config/setup-server.tsx',
globalTeardown: './e2e/config/teardown-server.tsx',
setupFilesAfterEnv: ['./e2e/config/setup-playwright.tsx'],
};

View File

@@ -11,65 +11,63 @@
"ios": "react-native run-ios", "ios": "react-native run-ios",
"preios": "pod-install", "preios": "pod-install",
"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\"", "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:e2e": "playwright test --config=e2e/playwright.config.ts"
}, },
"dependencies": { "dependencies": {
"@expo/vector-icons": "^12.0.0", "@expo/vector-icons": "^12.0.5",
"@react-native-async-storage/async-storage": "^1.13.0", "@react-native-async-storage/async-storage": "^1.15.5",
"@react-native-masked-view/masked-view": "~0.2.4", "@react-native-masked-view/masked-view": "~0.2.4",
"color": "^3.1.3", "color": "^3.1.3",
"expo": "^41.0.1", "expo": "^41.0.1",
"expo-asset": "~8.3.1", "expo-asset": "~8.3.2",
"expo-blur": "~9.0.3", "expo-blur": "~9.0.3",
"expo-linking": "~2.2.3", "expo-linking": "~2.2.3",
"expo-splash-screen": "~0.10.0", "expo-splash-screen": "~0.10.2",
"expo-status-bar": "~1.0.4", "expo-status-bar": "~1.0.4",
"expo-updates": "~0.5.4", "expo-updates": "~0.5.5",
"koa": "^2.13.0", "koa": "^2.13.0",
"react": "16.13.1", "react": "16.13.1",
"react-dom": "16.13.1", "react-dom": "16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-appearance": "~0.3.3", "react-native-appearance": "~0.3.3",
"react-native-gesture-handler": "~1.10.2", "react-native-gesture-handler": "~1.10.2",
"react-native-pager-view": "~5.0.12", "react-native-pager-view": "~5.1.10",
"react-native-paper": "^4.9.1", "react-native-paper": "^4.9.1",
"react-native-reanimated": "~2.1.0", "react-native-reanimated": "~2.2.0",
"react-native-safe-area-context": "~3.2.0", "react-native-safe-area-context": "~3.2.0",
"react-native-screens": "~3.0.0", "react-native-screens": "~3.3.0",
"react-native-tab-view": "^3.0.1", "react-native-tab-view": "^3.0.1",
"react-native-unimodules": "~0.13.1", "react-native-unimodules": "~0.13.3",
"react-native-vector-icons": "^8.1.0", "react-native-vector-icons": "^8.1.0",
"react-native-web": "~0.15.0" "react-native-web": "~0.16.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.0", "@babel/core": "^7.14.3",
"@babel/node": "^7.13.13", "@babel/node": "^7.14.2",
"@expo/webpack-config": "~0.12.63", "@expo/webpack-config": "~0.12.76",
"@types/cheerio": "^0.22.28", "@playwright/test": "^1.12.2",
"@types/cheerio": "^0.22.29",
"@types/jest-dev-server": "^4.2.0", "@types/jest-dev-server": "^4.2.0",
"@types/koa": "^2.13.1", "@types/koa": "^2.13.3",
"@types/mock-require": "^2.0.0", "@types/mock-require": "^2.0.0",
"@types/node-fetch": "^2.5.9", "@types/node-fetch": "^2.5.10",
"@types/react": "~16.9.35", "@types/react": "~17.0.9",
"@types/react-dom": "~16.9.8", "@types/react-dom": "~17.0.6",
"@types/react-native": "~0.63.2", "@types/react-native": "~0.64.9",
"babel-jest": "~25.2.6",
"babel-loader": "^8.2.2", "babel-loader": "^8.2.2",
"babel-plugin-module-resolver": "^4.0.0", "babel-plugin-module-resolver": "^4.0.0",
"babel-preset-expo": "8.3.0", "babel-preset-expo": "8.3.0",
"cheerio": "^1.0.0-rc.3", "cheerio": "^1.0.0-rc.9",
"expo-cli": "^4.4.4", "expo-cli": "^4.5.2",
"jest": "^26.6.3", "jest-dev-server": "^5.0.3",
"jest-dev-server": "^4.4.0",
"mock-require": "^3.0.3", "mock-require": "^3.0.3",
"mock-require-assets": "^0.0.1", "mock-require-assets": "^0.0.1",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"nodemon": "^2.0.6", "nodemon": "^2.0.6",
"playwright": "^1.11.0", "pod-install": "^0.1.23",
"pod-install": "^0.1.19",
"react-native-flipper": "~0.80.0", "react-native-flipper": "~0.80.0",
"react-test-renderer": "~16.13.1", "react-test-renderer": "~16.13.1",
"serve": "^11.3.0", "serve": "^11.3.0",
"typescript": "~4.2.3" "typescript": "^4.3.2"
} }
} }

View File

@@ -19,13 +19,10 @@ import Chat from '../Shared/Chat';
import Contacts from '../Shared/Contacts'; import Contacts from '../Shared/Contacts';
import SimpleStackScreen, { SimpleStackParams } from './SimpleStack'; import SimpleStackScreen, { SimpleStackParams } from './SimpleStack';
const getTabBarIcon = (name: string) => ({ const getTabBarIcon =
color, (name: string) =>
size, ({ color, size }: { color: string; size: number }) =>
}: { <MaterialCommunityIcons name={name} color={color} size={size} />;
color: string;
size: number;
}) => <MaterialCommunityIcons name={name} color={color} size={size} />;
type BottomTabParams = { type BottomTabParams = {
TabStack: NavigatorScreenParams<SimpleStackParams>; TabStack: NavigatorScreenParams<SimpleStackParams>;

View File

@@ -15,7 +15,8 @@ type MaterialBottomTabParams = {
TabChat: undefined; TabChat: undefined;
}; };
const MaterialBottomTabs = createMaterialBottomTabNavigator<MaterialBottomTabParams>(); const MaterialBottomTabs =
createMaterialBottomTabNavigator<MaterialBottomTabParams>();
export default function MaterialBottomTabsScreen() { export default function MaterialBottomTabsScreen() {
return ( return (

View File

@@ -155,9 +155,8 @@ export default function App() {
const [theme, setTheme] = React.useState(DefaultTheme); const [theme, setTheme] = React.useState(DefaultTheme);
const [isReady, setIsReady] = React.useState(Platform.OS === 'web'); const [isReady, setIsReady] = React.useState(Platform.OS === 'web');
const [initialState, setInitialState] = React.useState< const [initialState, setInitialState] =
InitialState | undefined React.useState<InitialState | undefined>();
>();
React.useEffect(() => { React.useEffect(() => {
const restoreState = async () => { const restoreState = async () => {

View File

@@ -17,12 +17,8 @@ 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(__dirname, 'node_modules', 'react-native-web'), 'react-native': path.resolve(node_modules, 'react-native-web'),
'react-native-web': path.resolve( 'react-native-web': path.resolve(node_modules, 'react-native-web'),
__dirname,
'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'),
}); });

View File

@@ -29,21 +29,24 @@
"release": "lerna publish", "release": "lerna publish",
"example": "yarn --cwd example" "example": "yarn --cwd example"
}, },
"dependencies": {
"react-native-web": "~0.16.3"
},
"devDependencies": { "devDependencies": {
"@commitlint/config-conventional": "^12.1.1", "@commitlint/config-conventional": "^12.1.4",
"@types/jest": "^26.0.22", "@types/jest": "^26.0.23",
"babel-jest": "^26.6.3", "babel-jest": "^26.6.3",
"codecov": "^3.8.1", "codecov": "^3.8.2",
"commitlint": "^12.1.1", "commitlint": "^12.1.4",
"eslint": "^7.23.0", "eslint": "^7.27.0",
"eslint-config-satya164": "^3.1.10", "eslint-config-satya164": "^3.1.10",
"eslint-plugin-simple-import-sort": "^7.0.0", "eslint-plugin-simple-import-sort": "^7.0.0",
"husky": "^4.3.6", "husky": "^4.3.6",
"jest": "^26.6.3", "jest": "^26.6.3",
"lerna": "^4.0.0", "lerna": "^4.0.0",
"metro-react-native-babel-preset": "^0.65.2", "metro-react-native-babel-preset": "^0.66.0",
"prettier": "^2.2.1", "prettier": "^2.3.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"resolutions": { "resolutions": {
"react": "~16.13.1", "react": "~16.13.1",
@@ -67,6 +70,7 @@
"preset": "react-native" "preset": "react-native"
}, },
"prettier": { "prettier": {
"quoteProps": "consistent",
"tabWidth": 2, "tabWidth": 2,
"useTabs": false, "useTabs": false,
"singleQuote": true, "singleQuote": true,

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.19](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.18...@react-navigation/bottom-tabs@6.0.0-next.19) (2021-06-10)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [6.0.0-next.18](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.17...@react-navigation/bottom-tabs@6.0.0-next.18) (2021-06-01) # [6.0.0-next.18](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.17...@react-navigation/bottom-tabs@6.0.0-next.18) (2021-06-01)
**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": "6.0.0-next.18", "version": "6.0.0-next.19",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -36,23 +36,23 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/elements": "^1.0.0-next.17", "@react-navigation/elements": "^1.0.0-next.18",
"color": "^3.1.3", "color": "^3.1.3",
"warn-once": "^0.1.0" "warn-once": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/color": "^3.0.1", "@types/color": "^3.0.1",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-native-safe-area-context": "~3.2.0", "react-native-safe-area-context": "~3.2.0",
"react-native-screens": "~3.0.0", "react-native-screens": "~3.3.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -77,25 +77,21 @@ function BottomTabNavigator({
); );
} }
const { const { state, descriptors, navigation, NavigationContent } =
state, useNavigationBuilder<
descriptors, TabNavigationState<ParamListBase>,
navigation, TabRouterOptions,
NavigationContent, TabActionHelpers<ParamListBase>,
} = useNavigationBuilder< BottomTabNavigationOptions,
TabNavigationState<ParamListBase>, BottomTabNavigationEventMap
TabRouterOptions, >(TabRouter, {
TabActionHelpers<ParamListBase>, initialRouteName,
BottomTabNavigationOptions, backBehavior,
BottomTabNavigationEventMap children,
>(TabRouter, { screenListeners,
initialRouteName, screenOptions,
backBehavior, defaultScreenOptions,
children, });
screenListeners,
screenOptions,
defaultScreenOptions,
});
return ( return (
<NavigationContent> <NavigationContent>

View File

@@ -48,9 +48,8 @@ const shouldUseHorizontalLabels = ({
layout, layout,
dimensions, dimensions,
}: Options) => { }: Options) => {
const { tabBarLabelPosition, tabBarAdaptive = true } = descriptors[ const { tabBarLabelPosition, tabBarAdaptive = true } =
state.routes[state.index].key descriptors[state.routes[state.index].key].options;
].options;
if (tabBarLabelPosition) { if (tabBarLabelPosition) {
return tabBarLabelPosition === 'beside-icon'; return tabBarLabelPosition === 'beside-icon';

View File

@@ -137,7 +137,8 @@ export default function BottomTabView(props: Props) {
header={header({ header={header({
layout: dimensions, layout: dimensions,
route: descriptor.route, route: descriptor.route,
navigation: descriptor.navigation as BottomTabNavigationProp<ParamListBase>, navigation:
descriptor.navigation as BottomTabNavigationProp<ParamListBase>,
options: descriptor.options, options: descriptor.options,
})} })}
style={sceneContainerStyle} style={sceneContainerStyle}

View File

@@ -3,6 +3,17 @@
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.
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.13...@react-navigation/core@6.0.0-next.14) (2021-06-10)
### Features
* show stack trace in the flipper plugin ([97772af](https://github.com/react-navigation/react-navigation/commit/97772affa3c8f26489f0bdbfb6872ef4377b8ed1))
# [6.0.0-next.13](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.12...@react-navigation/core@6.0.0-next.13) (2021-05-29) # [6.0.0-next.13](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.12...@react-navigation/core@6.0.0-next.13) (2021-05-29)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/core", "name": "@react-navigation/core",
"description": "Core utilities for building navigators", "description": "Core utilities for building navigators",
"version": "6.0.0-next.13", "version": "6.0.0-next.14",
"keywords": [ "keywords": [
"react", "react",
"react-native", "react-native",
@@ -35,22 +35,22 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/routers": "^6.0.0-next.4", "@react-navigation/routers": "^6.0.0-next.5",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.22", "nanoid": "^3.1.23",
"query-string": "^7.0.0", "query-string": "^7.0.0",
"react-is": "^16.13.0" "react-is": "^16.13.0"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-is": "^16.7.1", "@types/react-is": "^17.0.0",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"immer": "^9.0.1", "immer": "^9.0.2",
"react": "~16.13.1", "react": "~16.13.1",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-test-renderer": "~16.13.1", "react-test-renderer": "~16.13.1",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"react": "*" "react": "*"

View File

@@ -95,15 +95,10 @@ const BaseNavigationContainer = React.forwardRef(
); );
} }
const [ const [state, getState, setState, scheduleUpdate, flushUpdates] =
state, useSyncState<State>(() =>
getState, getPartialState(initialState == null ? undefined : initialState)
setState, );
scheduleUpdate,
flushUpdates,
] = useSyncState<State>(() =>
getPartialState(initialState == null ? undefined : initialState)
);
const isFirstMountRef = React.useRef<boolean>(true); const isFirstMountRef = React.useRef<boolean>(true);
@@ -223,7 +218,10 @@ const BaseNavigationContainer = React.forwardRef(
const onDispatchAction = React.useCallback( const onDispatchAction = React.useCallback(
(action: NavigationAction, noop: boolean) => { (action: NavigationAction, noop: boolean) => {
emitter.emit({ type: '__unsafe_action__', data: { action, noop } }); emitter.emit({
type: '__unsafe_action__',
data: { action, noop, stack: stackRef.current },
});
}, },
[emitter] [emitter]
); );
@@ -246,12 +244,15 @@ const BaseNavigationContainer = React.forwardRef(
[emitter] [emitter]
); );
const stackRef = React.useRef<string | undefined>();
const builderContext = React.useMemo( const builderContext = React.useMemo(
() => ({ () => ({
addListener, addListener,
addKeyedListener, addKeyedListener,
onDispatchAction, onDispatchAction,
onOptionsChange, onOptionsChange,
stackRef,
}), }),
[addListener, addKeyedListener, onDispatchAction, onOptionsChange] [addListener, addKeyedListener, onDispatchAction, onOptionsChange]
); );
@@ -349,9 +350,8 @@ const BaseNavigationContainer = React.forwardRef(
} }
} }
const duplicateRouteNamesResult = checkDuplicateRouteNames( const duplicateRouteNamesResult =
hydratedState checkDuplicateRouteNames(hydratedState);
);
if (duplicateRouteNamesResult.length) { if (duplicateRouteNamesResult.length) {
const message = `Found screens with the same name nested inside one another. Check:\n${duplicateRouteNamesResult.map( const message = `Found screens with the same name nested inside one another. Check:\n${duplicateRouteNamesResult.map(

View File

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

View File

@@ -6,13 +6,14 @@ type Props = {
const MULTIPLE_NAVIGATOR_ERROR = `Another navigator is already registered for this container. You likely have multiple navigators under a single "NavigationContainer" or "Screen". Make sure each navigator is under a separate "Screen" container. See https://reactnavigation.org/docs/nesting-navigators for a guide on nesting.`; const MULTIPLE_NAVIGATOR_ERROR = `Another navigator is already registered for this container. You likely have multiple navigators under a single "NavigationContainer" or "Screen". Make sure each navigator is under a separate "Screen" container. See https://reactnavigation.org/docs/nesting-navigators for a guide on nesting.`;
export const SingleNavigatorContext = React.createContext< export const SingleNavigatorContext =
| { React.createContext<
register(key: string): void; | {
unregister(key: string): void; register(key: string): void;
} unregister(key: string): void;
| undefined }
>(undefined); | undefined
>(undefined);
/** /**
* Component which ensures that there's only one navigator nested under it. * Component which ensures that there's only one navigator nested under it.

View File

@@ -39,7 +39,10 @@ export type FocusedNavigationCallback<T> = (
export type FocusedNavigationListener = <T>( export type FocusedNavigationListener = <T>(
callback: FocusedNavigationCallback<T> callback: FocusedNavigationCallback<T>
) => { handled: boolean; result: T }; ) => {
handled: boolean;
result: T;
};
export type GetStateListener = () => NavigationState; export type GetStateListener = () => NavigationState;
@@ -58,6 +61,7 @@ const NavigationBuilderContext = React.createContext<{
onRouteFocus?: (key: string) => void; onRouteFocus?: (key: string) => void;
onDispatchAction: (action: NavigationAction, noop: boolean) => void; onDispatchAction: (action: NavigationAction, noop: boolean) => void;
onOptionsChange: (options: object) => void; onOptionsChange: (options: object) => void;
stackRef?: React.MutableRefObject<string | undefined>;
}>({ }>({
onDispatchAction: () => undefined, onDispatchAction: () => undefined,
onOptionsChange: () => undefined, onOptionsChange: () => undefined,

View File

@@ -6,8 +6,9 @@ import type { NavigationContainerRef } from './types';
/** /**
* Context which holds the route prop for a screen. * Context which holds the route prop for a screen.
*/ */
const NavigationContainerRefContext = React.createContext< const NavigationContainerRefContext =
NavigationContainerRef<ParamListBase> | undefined React.createContext<NavigationContainerRef<ParamListBase> | undefined>(
>(undefined); undefined
);
export default NavigationContainerRefContext; export default NavigationContainerRefContext;

View File

@@ -6,8 +6,7 @@ import type { NavigationProp } from './types';
/** /**
* Context which holds the navigation prop for a screen. * Context which holds the navigation prop for a screen.
*/ */
const NavigationContext = React.createContext< const NavigationContext =
NavigationProp<ParamListBase> | undefined React.createContext<NavigationProp<ParamListBase> | undefined>(undefined);
>(undefined);
export default NavigationContext; export default NavigationContext;

View File

@@ -7,8 +7,7 @@ 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.
* Navigators should use this context in their view component. * Navigators should use this context in their view component.
*/ */
const NavigationHelpersContext = React.createContext< const NavigationHelpersContext =
NavigationHelpers<ParamListBase> | undefined React.createContext<NavigationHelpers<ParamListBase> | undefined>(undefined);
>(undefined);
export default NavigationHelpersContext; export default NavigationHelpersContext;

View File

@@ -4,8 +4,7 @@ import * as React from 'react';
/** /**
* Context which holds the route prop for a screen. * Context which holds the route prop for a screen.
*/ */
const NavigationRouteContext = React.createContext<Route<string> | undefined>( const NavigationRouteContext =
undefined React.createContext<Route<string> | undefined>(undefined);
);
export default NavigationRouteContext; export default NavigationRouteContext;

View File

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

View File

@@ -2196,6 +2196,7 @@ it('tries to match wildcard patterns at the end', () => {
path: '/bar/:id/', path: '/bar/:id/',
screens: { screens: {
404: '*', 404: '*',
UserProfile: ':userSlug',
Test: 'test', Test: 'test',
}, },
}, },

View File

@@ -31,19 +31,21 @@ it('fires focus and blur events in root navigator', () => {
const fourthFocusCallback = jest.fn(); const fourthFocusCallback = jest.fn();
const fourthBlurCallback = jest.fn(); const fourthBlurCallback = jest.fn();
const createComponent = (focusCallback: any, blurCallback: any) => ({ const createComponent =
navigation, (focusCallback: any, blurCallback: any) =>
}: any) => { ({ navigation }: any) => {
React.useEffect(() => navigation.addListener('focus', focusCallback), [ React.useEffect(
navigation, () => navigation.addListener('focus', focusCallback),
]); [navigation]
);
React.useEffect(() => navigation.addListener('blur', blurCallback), [ React.useEffect(
navigation, () => navigation.addListener('blur', blurCallback),
]); [navigation]
);
return null; return null;
}; };
const navigation = React.createRef<any>(); const navigation = React.createRef<any>();
@@ -185,19 +187,21 @@ it('fires focus and blur events in nested navigator', () => {
const fourthFocusCallback = jest.fn(); const fourthFocusCallback = jest.fn();
const fourthBlurCallback = jest.fn(); const fourthBlurCallback = jest.fn();
const createComponent = (focusCallback: any, blurCallback: any) => ({ const createComponent =
navigation, (focusCallback: any, blurCallback: any) =>
}: any) => { ({ navigation }: any) => {
React.useEffect(() => navigation.addListener('focus', focusCallback), [ React.useEffect(
navigation, () => navigation.addListener('focus', focusCallback),
]); [navigation]
);
React.useEffect(() => navigation.addListener('blur', blurCallback), [ React.useEffect(
navigation, () => navigation.addListener('blur', blurCallback),
]); [navigation]
);
return null; return null;
}; };
const parent = React.createRef<any>(); const parent = React.createRef<any>();
const child = React.createRef<any>(); const child = React.createRef<any>();
@@ -392,9 +396,10 @@ it('fires blur event when a route is removed with a delay', async () => {
const First = () => null; const First = () => null;
const Second = ({ navigation }: any) => { const Second = ({ navigation }: any) => {
React.useEffect(() => navigation.addListener('blur', blurCallback), [ React.useEffect(
navigation, () => navigation.addListener('blur', blurCallback),
]); [navigation]
);
return null; return null;
}; };
@@ -447,13 +452,16 @@ it('fires custom events added with addListener', () => {
const secondCallback = jest.fn(); const secondCallback = jest.fn();
const thirdCallback = jest.fn(); const thirdCallback = jest.fn();
const createComponent = (callback: any) => ({ navigation }: any) => { const createComponent =
React.useEffect(() => navigation.addListener(eventName, callback), [ (callback: any) =>
navigation, ({ navigation }: any) => {
]); React.useEffect(
() => navigation.addListener(eventName, callback),
[navigation]
);
return null; return null;
}; };
const ref = React.createRef<any>(); const ref = React.createRef<any>();
@@ -526,9 +534,10 @@ it("doesn't call same listener multiple times with addListener", () => {
const callback = jest.fn(); const callback = jest.fn();
const Test = ({ navigation }: any) => { const Test = ({ navigation }: any) => {
React.useEffect(() => navigation.addListener(eventName, callback), [ React.useEffect(
navigation, () => navigation.addListener(eventName, callback),
]); [navigation]
);
return null; return null;
}; };
@@ -802,9 +811,10 @@ it('has option to prevent default', () => {
}; };
const Test = ({ navigation }: any) => { const Test = ({ navigation }: any) => {
React.useEffect(() => navigation.addListener(eventName, callback), [ React.useEffect(
navigation, () => navigation.addListener(eventName, callback),
]); [navigation]
);
return null; return null;
}; };

View File

@@ -143,27 +143,31 @@ export default function getStateFromPath<ParamList extends {}>(
const aParts = a.pattern.split('/'); const aParts = a.pattern.split('/');
const bParts = b.pattern.split('/'); const bParts = b.pattern.split('/');
const aWildcardIndex = aParts.indexOf('*'); for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
const bWildcardIndex = bParts.indexOf('*'); // if b is longer, b get higher priority
if (aParts[i] == null) {
// If only one of the patterns has a wildcard, move it down in the list return 1;
if (aWildcardIndex === -1 && bWildcardIndex !== -1) { }
return -1; // if a is longer, a get higher priority
if (bParts[i] == null) {
return -1;
}
const aWildCard = aParts[i] === '*' || aParts[i].startsWith(':');
const bWildCard = bParts[i] === '*' || bParts[i].startsWith(':');
// if both are wildcard we compare next component
if (aWildCard && bWildCard) {
continue;
}
// if only a is wild card, b get higher priority
if (aWildCard) {
return 1;
}
// if only b is wild card, a get higher priority
if (bWildCard) {
return -1;
}
} }
return bParts.length - aParts.length;
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;
}); });
// Check for duplicate patterns in the config // Check for duplicate patterns in the config

View File

@@ -524,43 +524,45 @@ export type NavigationContainerEventMap = {
* Whether the action was a no-op, i.e. resulted any state changes. * Whether the action was a no-op, i.e. resulted any state changes.
*/ */
noop: boolean; noop: boolean;
/**
* Stack trace of the action, this will only be available during development.
*/
stack: string | undefined;
}; };
}; };
}; };
export type NavigationContainerRef< export type NavigationContainerRef<ParamList extends {}> =
ParamList extends {} NavigationHelpers<ParamList> &
> = NavigationHelpers<ParamList> & EventConsumer<NavigationContainerEventMap> & {
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. *
* * @param state Navigation state object.
* @param state Navigation state object. */
*/ resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
resetRoot(state?: PartialState<NavigationState> | NavigationState): void; /**
/** * 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.
* Get the currently focused navigation route. */
*/ getCurrentRoute(): Route<string> | undefined;
getCurrentRoute(): Route<string> | undefined; /**
/** * Get the currently focused route's options.
* Get the currently focused route's options. */
*/ getCurrentOptions(): object | undefined;
getCurrentOptions(): object | undefined; /**
/** * Whether the navigation container is ready to handle actions.
* Whether the navigation container is ready to handle actions. */
*/ isReady(): boolean;
isReady(): boolean; };
};
export type NavigationContainerRefWithCurrent< export type NavigationContainerRefWithCurrent<ParamList extends {}> =
ParamList extends {} NavigationContainerRef<ParamList> & {
> = NavigationContainerRef<ParamList> & { current: NavigationContainerRef<ParamList> | null;
current: NavigationContainerRef<ParamList> | null; };
};
export type TypedNavigator< export type TypedNavigator<
ParamList extends ParamListBase, ParamList extends ParamListBase,

View File

@@ -60,10 +60,7 @@ type Options<
navigation: any; navigation: any;
options: ScreenOptions; options: ScreenOptions;
}) => ScreenOptions); }) => ScreenOptions);
onAction: ( onAction: (action: NavigationAction) => boolean;
action: NavigationAction,
visitedNavigators?: Set<string>
) => boolean;
getState: () => State; getState: () => State;
setState: (state: State) => void; setState: (state: State) => void;
addListener: AddListener; addListener: AddListener;
@@ -102,7 +99,7 @@ export default function useDescriptors<
emitter, emitter,
}: Options<State, ScreenOptions, EventMap>) { }: Options<State, ScreenOptions, EventMap>) {
const [options, setOptions] = React.useState<Record<string, object>>({}); const [options, setOptions] = React.useState<Record<string, object>>({});
const { onDispatchAction, onOptionsChange } = React.useContext( const { onDispatchAction, onOptionsChange, stackRef } = React.useContext(
NavigationBuilderContext NavigationBuilderContext
); );
@@ -115,6 +112,7 @@ export default function useDescriptors<
onRouteFocus, onRouteFocus,
onDispatchAction, onDispatchAction,
onOptionsChange, onOptionsChange,
stackRef,
}), }),
[ [
navigation, navigation,
@@ -124,6 +122,7 @@ export default function useDescriptors<
onRouteFocus, onRouteFocus,
onDispatchAction, onDispatchAction,
onOptionsChange, onOptionsChange,
stackRef,
] ]
); );

View File

@@ -2,11 +2,10 @@ import * as React from 'react';
import type { EventArg, EventConsumer, EventEmitter } from './types'; import type { EventArg, EventConsumer, EventEmitter } from './types';
export type NavigationEventEmitter< export type NavigationEventEmitter<T extends Record<string, any>> =
T extends Record<string, any> EventEmitter<T> & {
> = EventEmitter<T> & { create: (target: string) => EventConsumer<T>;
create: (target: string) => EventConsumer<T>; };
};
type Listeners = ((e: any) => void)[]; type Listeners = ((e: any) => void)[];

View File

@@ -40,8 +40,8 @@ export default function useFocusedListenersChildrenAdapter({
[focusedListeners, navigation] [focusedListeners, navigation]
); );
React.useEffect(() => addListener?.('focus', listener), [ React.useEffect(
addListener, () => addListener?.('focus', listener),
listener, [addListener, listener]
]); );
} }

View File

@@ -5,7 +5,6 @@ import type { KeyedListenerMap } from './NavigationBuilderContext';
/** /**
* Hook which lets child navigators add getters to be called for obtaining rehydrated state. * Hook which lets child navigators add getters to be called for obtaining rehydrated state.
*/ */
export default function useKeyedChildListeners() { export default function useKeyedChildListeners() {
const { current: keyedListeners } = React.useRef< const { current: keyedListeners } = React.useRef<
{ {
@@ -25,11 +24,9 @@ export default function useKeyedChildListeners() {
key: string, key: string,
listener: KeyedListenerMap[T] listener: KeyedListenerMap[T]
) => { ) => {
// @ts-expect-error: listener should be correct type according to `type`
keyedListeners[type][key] = listener; keyedListeners[type][key] = listener;
return () => { return () => {
// @ts-expect-error: listener should be correct type according to `type`
keyedListeners[type][key] = undefined; keyedListeners[type][key] = undefined;
}; };
}, },

View File

@@ -22,5 +22,5 @@ export default function useNavigation<
} }
// FIXME: Figure out a better way to do this // FIXME: Figure out a better way to do this
return ((navigation ?? root) as unknown) as T; return (navigation ?? root) as unknown as T;
} }

View File

@@ -220,7 +220,7 @@ export default function useNavigationBuilder<
const { children, screenListeners, ...rest } = options; const { children, screenListeners, ...rest } = options;
const { current: router } = React.useRef<Router<State, any>>( const { current: router } = React.useRef<Router<State, any>>(
createRouter({ createRouter({
...((rest as unknown) as RouterOptions), ...(rest as unknown as RouterOptions),
...(route?.params && ...(route?.params &&
route.params.state == null && route.params.state == null &&
route.params.initial !== false && route.params.initial !== false &&
@@ -230,11 +230,8 @@ export default function useNavigationBuilder<
}) })
); );
const routeConfigs = getRouteConfigsFromChildren< const routeConfigs =
State, getRouteConfigsFromChildren<State, ScreenOptions, EventMap>(children);
ScreenOptions,
EventMap
>(children);
const screens = routeConfigs.reduce< const screens = routeConfigs.reduce<
Record<string, ScreenConfigWithParent<State, ScreenOptions, EventMap>> Record<string, ScreenConfigWithParent<State, ScreenOptions, EventMap>>

View File

@@ -7,6 +7,7 @@ import {
} from '@react-navigation/routers'; } from '@react-navigation/routers';
import * as React from 'react'; import * as React from 'react';
import NavigationBuilderContext from './NavigationBuilderContext';
import type { NavigationHelpers, NavigationProp } from './types'; import type { NavigationHelpers, NavigationProp } from './types';
import type { NavigationEventEmitter } from './useEventEmitter'; import type { NavigationEventEmitter } from './useEventEmitter';
@@ -51,6 +52,8 @@ export default function useNavigationCache<
router, router,
emitter, emitter,
}: Options<State, EventMap>) { }: Options<State, EventMap>) {
const { stackRef } = React.useContext(NavigationBuilderContext);
// Cache object which holds navigation objects for each screen // Cache object which holds navigation objects for each screen
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change // We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
// In reality, these deps will rarely change, if ever // In reality, these deps will rarely change, if ever
@@ -70,6 +73,10 @@ export default function useNavigationCache<
>((acc, route) => { >((acc, route) => {
const previous = cache.current[route.key]; const previous = cache.current[route.key];
type Thunk =
| NavigationAction
| ((state: State) => NavigationAction | null | undefined);
if (previous) { if (previous) {
// If a cached navigation object already exists, reuse it // If a cached navigation object already exists, reuse it
acc[route.key] = previous; acc[route.key] = previous;
@@ -77,11 +84,7 @@ export default function useNavigationCache<
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { emit, ...rest } = navigation; const { emit, ...rest } = navigation;
const dispatch = ( const dispatch = (thunk: Thunk) => {
thunk:
| NavigationAction
| ((state: State) => NavigationAction | null | undefined)
) => {
const action = typeof thunk === 'function' ? thunk(getState()) : thunk; const action = typeof thunk === 'function' ? thunk(getState()) : thunk;
if (action != null) { if (action != null) {
@@ -89,10 +92,36 @@ export default function useNavigationCache<
} }
}; };
const withStack = (callback: () => void) => {
let isStackSet = false;
try {
if (
process.env.NODE_ENV !== 'production' &&
stackRef &&
!stackRef.current
) {
// Capture the stack trace for devtools
stackRef.current = new Error().stack;
isStackSet = true;
}
callback();
} finally {
if (isStackSet && stackRef) {
stackRef.current = undefined;
}
}
};
const helpers = Object.keys(actions).reduce<Record<string, () => void>>( const helpers = Object.keys(actions).reduce<Record<string, () => void>>(
(acc, name) => { (acc, name) => {
// @ts-expect-error: name is a valid key, but TypeScript is dumb acc[name] = (...args: any) =>
acc[name] = (...args: any) => dispatch(actions[name](...args)); withStack(() =>
// @ts-expect-error: name is a valid key, but TypeScript is dumb
dispatch(actions[name](...args))
);
return acc; return acc;
}, },
{} {}
@@ -103,7 +132,7 @@ export default function useNavigationCache<
...helpers, ...helpers,
// FIXME: too much work to fix the types for now // FIXME: too much work to fix the types for now
...(emitter.create(route.key) as any), ...(emitter.create(route.key) as any),
dispatch, dispatch: (thunk: Thunk) => withStack(() => dispatch(thunk)),
setOptions: (options: object) => setOptions: (options: object) =>
setOptions((o) => ({ setOptions((o) => ({
...o, ...o,

View File

@@ -6,9 +6,8 @@ import type { NavigationContainerRefWithCurrent } from './types';
export default function useNavigationContainerRef< export default function useNavigationContainerRef<
ParamList extends {} = ReactNavigation.RootParamList ParamList extends {} = ReactNavigation.RootParamList
>(): NavigationContainerRefWithCurrent<ParamList> { >(): NavigationContainerRefWithCurrent<ParamList> {
const navigation = React.useRef<NavigationContainerRefWithCurrent<ParamList> | null>( const navigation =
null React.useRef<NavigationContainerRefWithCurrent<ParamList> | null>(null);
);
if (navigation.current == null) { if (navigation.current == null) {
navigation.current = createNavigationContainerRef<ParamList>(); navigation.current = createNavigationContainerRef<ParamList>();

View File

@@ -17,10 +17,7 @@ import type { NavigationEventEmitter } from './useEventEmitter';
PrivateValueStore; PrivateValueStore;
type Options<State extends NavigationState, Action extends NavigationAction> = { type Options<State extends NavigationState, Action extends NavigationAction> = {
onAction: ( onAction: (action: NavigationAction) => boolean;
action: NavigationAction,
visitedNavigators?: Set<string>
) => boolean;
getState: () => State; getState: () => State;
emitter: NavigationEventEmitter<any>; emitter: NavigationEventEmitter<any>;
router: Router<State, Action>; router: Router<State, Action>;

View File

@@ -52,9 +52,8 @@ export default function useOnAction({
onDispatchAction, onDispatchAction,
} = React.useContext(NavigationBuilderContext); } = React.useContext(NavigationBuilderContext);
const routerConfigOptionsRef = React.useRef<RouterConfigOptions>( const routerConfigOptionsRef =
routerConfigOptions React.useRef<RouterConfigOptions>(routerConfigOptions);
);
React.useEffect(() => { React.useEffect(() => {
routerConfigOptionsRef.current = routerConfigOptions; routerConfigOptionsRef.current = routerConfigOptions;
@@ -158,10 +157,10 @@ export default function useOnAction({
beforeRemoveListeners, beforeRemoveListeners,
}); });
React.useEffect(() => addListenerParent?.('action', onAction), [ React.useEffect(
addListenerParent, () => addListenerParent?.('action', onAction),
onAction, [addListenerParent, onAction]
]); );
return onAction; return onAction;
} }

View File

@@ -3,6 +3,17 @@
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.
# [6.0.0-next.15](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.14...@react-navigation/devtools@6.0.0-next.15) (2021-06-10)
### Features
* show stack trace in the flipper plugin ([97772af](https://github.com/react-navigation/react-navigation/commit/97772affa3c8f26489f0bdbfb6872ef4377b8ed1))
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.13...@react-navigation/devtools@6.0.0-next.14) (2021-05-29) # [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.13...@react-navigation/devtools@6.0.0-next.14) (2021-05-29)
**Note:** Version bump only for package @react-navigation/devtools **Note:** Version bump only for package @react-navigation/devtools

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/devtools", "name": "@react-navigation/devtools",
"description": "Developer tools for React Navigation", "description": "Developer tools for React Navigation",
"version": "6.0.0-next.14", "version": "6.0.0-next.15",
"keywords": [ "keywords": [
"react", "react",
"react-native", "react-native",
@@ -37,18 +37,18 @@
}, },
"dependencies": { "dependencies": {
"deep-equal": "^2.0.5", "deep-equal": "^2.0.5",
"nanoid": "^3.1.22" "nanoid": "^3.1.23"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/core": "^6.0.0-next.13", "@react-navigation/core": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/deep-equal": "^1.0.1", "@types/deep-equal": "^1.0.1",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-native-flipper": "^0.80.0", "react-native-flipper": "^0.80.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"react": "*" "react": "*"

View File

@@ -6,20 +6,42 @@ import type {
import deepEqual from 'deep-equal'; import deepEqual from 'deep-equal';
import * as React from 'react'; import * as React from 'react';
type StackFrame = {
lineNumber: number | null;
column: number | null;
file: string | null;
methodName: string;
};
type StackFrameResult = StackFrame & {
collapse: boolean;
};
type StackResult = {
stack: StackFrameResult[];
};
type InitData = {
type: 'init';
state: NavigationState | undefined;
};
type ActionData = {
type: 'action';
action: NavigationAction;
state: NavigationState | undefined;
stack: string | undefined;
};
export default function useDevToolsBase( export default function useDevToolsBase(
ref: React.RefObject<NavigationContainerRef<any>>, ref: React.RefObject<NavigationContainerRef<any>>,
callback: ( callback: (result: InitData | ActionData) => void
...args:
| [type: 'init', state: NavigationState | undefined]
| [
type: 'action',
action: NavigationAction,
state: NavigationState | undefined
]
) => void
) { ) {
const lastStateRef = React.useRef<NavigationState | undefined>(); const lastStateRef = React.useRef<NavigationState | undefined>();
const lastActionRef = React.useRef<NavigationAction | undefined>(); const lastActionRef =
React.useRef<
{ action: NavigationAction; stack: string | undefined } | undefined
>();
const callbackRef = React.useRef(callback); const callbackRef = React.useRef(callback);
const lastResetRef = React.useRef<NavigationState | undefined>(undefined); const lastResetRef = React.useRef<NavigationState | undefined>(undefined);
@@ -27,8 +49,73 @@ export default function useDevToolsBase(
callbackRef.current = callback; callbackRef.current = callback;
}); });
const symbolicate = async (stack: string | undefined) => {
if (stack == null) {
return undefined;
}
const frames = stack
.split('\n')
.slice(2)
.map((line): StackFrame | null => {
const partMatch = line.match(/^((.+)@)?(.+):(\d+):(\d+)$/);
if (!partMatch) {
return null;
}
const [, , methodName, file, lineNumber, column] = partMatch;
return {
methodName,
file,
lineNumber: Number(lineNumber),
column: Number(column),
};
})
.filter(Boolean) as StackFrame[];
const urlMatch = frames[0].file?.match(/^https?:\/\/.+(:\d+)?\//);
if (!urlMatch) {
return stack;
}
try {
const result: StackResult = await fetch(`${urlMatch[0]}symbolicate`, {
method: 'POST',
body: JSON.stringify({ stack: frames }),
}).then((res) => res.json());
return result.stack
.filter((it) => !it.collapse)
.map(
({ methodName, file, lineNumber, column }) =>
`${methodName}@${file}:${lineNumber}:${column}`
)
.join('\n');
} catch (err) {
return stack;
}
};
const pendingPromiseRef = React.useRef<Promise<void>>(Promise.resolve());
const send = React.useCallback((data: ActionData) => {
// We need to make sure that our callbacks executed in the same order
pendingPromiseRef.current = pendingPromiseRef.current.then(async () => {
if (data.stack) {
const stack = await symbolicate(data.stack);
callbackRef.current({ ...data, stack });
} else {
callbackRef.current(data);
}
});
}, []);
React.useEffect(() => { React.useEffect(() => {
let timer: number; let timer: any;
let unsubscribeAction: (() => void) | undefined; let unsubscribeAction: (() => void) | undefined;
let unsubscribeState: (() => void) | undefined; let unsubscribeState: (() => void) | undefined;
@@ -43,7 +130,7 @@ export default function useDevToolsBase(
const state = ref.current.getRootState(); const state = ref.current.getRootState();
lastStateRef.current = state; lastStateRef.current = state;
callbackRef.current('init', state); callbackRef.current({ type: 'init', state });
} }
}, 100); }, 100);
}); });
@@ -56,9 +143,14 @@ export default function useDevToolsBase(
if (e.data.noop) { if (e.data.noop) {
// Even if the state didn't change, it's useful to show the action // Even if the state didn't change, it's useful to show the action
callbackRef.current('action', action, lastStateRef.current); send({
type: 'action',
action,
state: lastStateRef.current,
stack: e.data.stack,
});
} else { } else {
lastActionRef.current = action; lastActionRef.current = e.data;
} }
}); });
@@ -74,17 +166,22 @@ export default function useDevToolsBase(
const state = navigation.getRootState(); const state = navigation.getRootState();
const lastState = lastStateRef.current; const lastState = lastStateRef.current;
const action = lastActionRef.current; const lastChange = lastActionRef.current;
lastActionRef.current = undefined; lastActionRef.current = undefined;
lastStateRef.current = state; lastStateRef.current = state;
// If we don't have an action and the state didn't change, then it's probably extraneous // If we don't have an action and the state didn't change, then it's probably extraneous
if (action === undefined && deepEqual(state, lastState)) { if (lastChange === undefined && deepEqual(state, lastState)) {
return; return;
} }
callbackRef.current('action', action ?? { type: '@@UNKNOWN' }, state); send({
type: 'action',
action: lastChange ? lastChange.action : { type: '@@UNKNOWN' },
state,
stack: lastChange?.stack,
});
}); });
}; };
@@ -95,7 +192,7 @@ export default function useDevToolsBase(
unsubscribeState?.(); unsubscribeState?.();
clearTimeout(timer); clearTimeout(timer);
}; };
}, [ref]); }, [ref, send]);
const resetRoot = React.useCallback( const resetRoot = React.useCallback(
(state: NavigationState) => { (state: NavigationState) => {

View File

@@ -26,25 +26,26 @@ export default function useFlipper(
const connectionRef = React.useRef<Flipper.FlipperConnection>(); const connectionRef = React.useRef<Flipper.FlipperConnection>();
const { resetRoot } = useDevToolsBase(ref, (...args) => { const { resetRoot } = useDevToolsBase(ref, (result) => {
const connection = connectionRef.current; const connection = connectionRef.current;
if (!connection) { if (!connection) {
return; return;
} }
switch (args[0]) { switch (result.type) {
case 'init': case 'init':
connection.send('init', { connection.send('init', {
id: nanoid(), id: nanoid(),
state: args[1], state: result.state,
}); });
break; break;
case 'action': case 'action':
connection.send('action', { connection.send('action', {
id: nanoid(), id: nanoid(),
action: args[1], action: result.action,
state: args[2], state: result.state,
stack: result.stack,
}); });
break; break;
} }

View File

@@ -32,19 +32,19 @@ export default function useReduxDevToolsExtension(
}); });
} }
const { resetRoot } = useDevToolsBase(ref, (...args) => { const { resetRoot } = useDevToolsBase(ref, (result) => {
const devTools = devToolsRef.current; const devTools = devToolsRef.current;
if (!devTools) { if (!devTools) {
return; return;
} }
switch (args[0]) { switch (result.type) {
case 'init': case 'init':
devTools.init(args[1]); devTools.init(result.state);
break; break;
case 'action': case 'action':
devTools.send(args[1], args[2]); devTools.send(result.action, result.state);
break; break;
} }
}); });

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.18](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.17...@react-navigation/drawer@6.0.0-next.18) (2021-06-10)
**Note:** Version bump only for package @react-navigation/drawer
# [6.0.0-next.17](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.16...@react-navigation/drawer@6.0.0-next.17) (2021-06-01) # [6.0.0-next.17](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.16...@react-navigation/drawer@6.0.0-next.17) (2021-06-01)
**Note:** Version bump only for package @react-navigation/drawer **Note:** Version bump only for package @react-navigation/drawer

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/drawer", "name": "@react-navigation/drawer",
"description": "Drawer navigator component with animated transitions and gesturess", "description": "Drawer navigator component with animated transitions and gesturess",
"version": "6.0.0-next.17", "version": "6.0.0-next.18",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -41,24 +41,24 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/elements": "^1.0.0-next.17", "@react-navigation/elements": "^1.0.0-next.18",
"color": "^3.1.3", "color": "^3.1.3",
"warn-once": "^0.1.0" "warn-once": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-native-gesture-handler": "~1.10.2", "react-native-gesture-handler": "~1.10.2",
"react-native-reanimated": "~2.1.0", "react-native-reanimated": "~2.2.0",
"react-native-safe-area-context": "~3.2.0", "react-native-safe-area-context": "~3.2.0",
"react-native-screens": "~3.0.0", "react-native-screens": "~3.3.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -74,26 +74,22 @@ function DrawerNavigator({
); );
} }
const { const { state, descriptors, navigation, NavigationContent } =
state, useNavigationBuilder<
descriptors, DrawerNavigationState<ParamListBase>,
navigation, DrawerRouterOptions,
NavigationContent, DrawerActionHelpers<ParamListBase>,
} = useNavigationBuilder< DrawerNavigationOptions,
DrawerNavigationState<ParamListBase>, DrawerNavigationEventMap
DrawerRouterOptions, >(DrawerRouter, {
DrawerActionHelpers<ParamListBase>, initialRouteName,
DrawerNavigationOptions, defaultStatus,
DrawerNavigationEventMap backBehavior,
>(DrawerRouter, { children,
initialRouteName, screenListeners,
defaultStatus, screenOptions,
backBehavior, defaultScreenOptions,
children, });
screenListeners,
screenOptions,
defaultScreenOptions,
});
return ( return (
<NavigationContent> <NavigationContent>

View File

@@ -1,7 +1,6 @@
import * as React from 'react'; import * as React from 'react';
const DrawerStatusContext = React.createContext<'open' | 'closed' | undefined>( const DrawerStatusContext =
undefined React.createContext<'open' | 'closed' | undefined>(undefined);
);
export default DrawerStatusContext; export default DrawerStatusContext;

View File

@@ -9,9 +9,8 @@ export default function DrawerContent({
state, state,
...rest ...rest
}: DrawerContentComponentProps) { }: DrawerContentComponentProps) {
const { drawerContentStyle, drawerContentContainerStyle } = descriptors[ const { drawerContentStyle, drawerContentContainerStyle } =
state.routes[state.index].key descriptors[state.routes[state.index].key].options;
].options;
return ( return (
<DrawerContentScrollView <DrawerContentScrollView

View File

@@ -26,7 +26,7 @@ export default function DrawerItemList({
}: Props) { }: Props) {
const buildLink = useLinkBuilder(); const buildLink = useLinkBuilder();
return (state.routes.map((route, i) => { return state.routes.map((route, i) => {
const focused = i === state.index; const focused = i === state.index;
const { const {
title, title,
@@ -69,5 +69,5 @@ export default function DrawerItemList({
}} }}
/> />
); );
}) as React.ReactNode) as React.ReactElement; }) as React.ReactNode as React.ReactElement;
} }

View File

@@ -238,7 +238,8 @@ function DrawerViewBase({
header={header({ header={header({
layout: dimensions, layout: dimensions,
route: descriptor.route, route: descriptor.route,
navigation: descriptor.navigation as DrawerNavigationProp<ParamListBase>, navigation:
descriptor.navigation as DrawerNavigationProp<ParamListBase>,
options: descriptor.options, options: descriptor.options,
})} })}
style={sceneContainerStyle} style={sceneContainerStyle}

View File

@@ -9,9 +9,11 @@ const Dummy: any = ({ children }: { children: React.ReactNode }) => (
<>{children}</> <>{children}</>
); );
export const PanGestureHandler = Dummy as React.ComponentType<PanGestureHandlerProperties>; export const PanGestureHandler =
Dummy as React.ComponentType<PanGestureHandlerProperties>;
export const TapGestureHandler = Dummy as React.ComponentType<TapGestureHandlerProperties>; export const TapGestureHandler =
Dummy as React.ComponentType<TapGestureHandlerProperties>;
export const GestureHandlerRootView = View; export const GestureHandlerRootView = View;

View File

@@ -471,10 +471,8 @@ export default class DrawerView extends React.Component<DrawerProps> {
}; };
private toggleStatusBar = (hidden: boolean) => { private toggleStatusBar = (hidden: boolean) => {
const { const { hideStatusBarOnOpen: hideStatusBar, statusBarAnimation } =
hideStatusBarOnOpen: hideStatusBar, this.props;
statusBarAnimation,
} = this.props;
if (hideStatusBar && this.isStatusBarHidden !== hidden) { if (hideStatusBar && this.isStatusBarHidden !== hidden) {
this.isStatusBarHidden = hidden; this.isStatusBarHidden = hidden;

View File

@@ -3,6 +3,14 @@
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.
# [1.0.0-next.18](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.17...@react-navigation/elements@1.0.0-next.18) (2021-06-10)
**Note:** Version bump only for package @react-navigation/elements
# [1.0.0-next.17](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.16...@react-navigation/elements@1.0.0-next.17) (2021-06-01) # [1.0.0-next.17](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.16...@react-navigation/elements@1.0.0-next.17) (2021-06-01)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/elements", "name": "@react-navigation/elements",
"description": "UI Components for React Navigation", "description": "UI Components for React Navigation",
"version": "1.0.0-next.17", "version": "1.0.0-next.18",
"keywords": [ "keywords": [
"react-native", "react-native",
"react-navigation", "react-navigation",
@@ -37,16 +37,16 @@
"clean": "del lib" "clean": "del lib"
}, },
"devDependencies": { "devDependencies": {
"@react-native-masked-view/masked-view": "^0.2.3", "@react-native-masked-view/masked-view": "^0.2.4",
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -35,9 +35,8 @@ export default function HeaderBackButton({
}: HeaderBackButtonProps) { }: HeaderBackButtonProps) {
const { colors } = useTheme(); const { colors } = useTheme();
const [initialLabelWidth, setInitialLabelWidth] = React.useState< const [initialLabelWidth, setInitialLabelWidth] =
undefined | number React.useState<undefined | number>(undefined);
>(undefined);
const tintColor = const tintColor =
customTintColor !== undefined customTintColor !== undefined

View File

@@ -4,7 +4,8 @@
import * as React from 'react'; import * as React from 'react';
import { UIManager } from 'react-native'; import { UIManager } from 'react-native';
type MaskedViewType = typeof import('@react-native-masked-view/masked-view').default; type MaskedViewType =
typeof import('@react-native-masked-view/masked-view').default;
type Props = React.ComponentProps<MaskedViewType> & { type Props = React.ComponentProps<MaskedViewType> & {
children: React.ReactElement; children: React.ReactElement;

View File

@@ -3,6 +3,17 @@
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.
# [1.2.0](https://github.com/react-navigation/react-navigation/compare/flipper-plugin-react-navigation@1.1.4...flipper-plugin-react-navigation@1.2.0) (2021-06-10)
### Features
* show stack trace in the flipper plugin ([97772af](https://github.com/react-navigation/react-navigation/commit/97772affa3c8f26489f0bdbfb6872ef4377b8ed1))
## [1.1.4](https://github.com/react-navigation/react-navigation/compare/flipper-plugin-react-navigation@1.1.3...flipper-plugin-react-navigation@1.1.4) (2021-05-29) ## [1.1.4](https://github.com/react-navigation/react-navigation/compare/flipper-plugin-react-navigation@1.1.3...flipper-plugin-react-navigation@1.1.4) (2021-05-29)
**Note:** Version bump only for package flipper-plugin-react-navigation **Note:** Version bump only for package flipper-plugin-react-navigation

View File

@@ -2,7 +2,7 @@
"$schema": "https://fbflipper.com/schemas/plugin-package/v2.json", "$schema": "https://fbflipper.com/schemas/plugin-package/v2.json",
"name": "flipper-plugin-react-navigation", "name": "flipper-plugin-react-navigation",
"description": "Developer tools for React Navigation", "description": "Developer tools for React Navigation",
"version": "1.1.4", "version": "1.2.0",
"main": "dist/bundle.js", "main": "dist/bundle.js",
"license": "MIT", "license": "MIT",
"keywords": [ "keywords": [
@@ -34,13 +34,13 @@
"@ant-design/icons": "^4.6.2", "@ant-design/icons": "^4.6.2",
"@babel/preset-react": "^7.12.13", "@babel/preset-react": "^7.12.13",
"@babel/preset-typescript": "^7.13.0", "@babel/preset-typescript": "^7.13.0",
"@react-navigation/core": "^6.0.0-next.13", "@react-navigation/core": "^6.0.0-next.14",
"@types/react": "^17.0.3", "@types/react": "^17.0.9",
"@types/react-dom": "^17.0.2", "@types/react-dom": "^17.0.6",
"antd": "^4.14.0", "antd": "^4.16.1",
"flipper": "^0.90.2", "flipper": "^0.92.0",
"flipper-pkg": "^0.90.2", "flipper-pkg": "^0.92.0",
"flipper-plugin": "^0.90.2", "flipper-plugin": "^0.92.0",
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1" "react-dom": "^17.0.1"
} }

View File

@@ -19,13 +19,11 @@ export function LinkingTester({ linking, active }: Props) {
const [rawConfig, setRawConfig] = React.useState(''); const [rawConfig, setRawConfig] = React.useState('');
const [path, setPath] = React.useState(''); const [path, setPath] = React.useState('');
const [state, setState] = React.useState< const [state, setState] =
ReturnType<typeof getStateFromPath> | undefined React.useState<ReturnType<typeof getStateFromPath> | undefined>();
>();
const [action, setAction] = React.useState< const [action, setAction] =
ReturnType<typeof getActionFromState> | undefined React.useState<ReturnType<typeof getActionFromState> | undefined>();
>();
const [error, setError] = React.useState<string | undefined>(); const [error, setError] = React.useState<string | undefined>();

View File

@@ -45,7 +45,11 @@ export function Logs({ active, logs, index, resetTo }: Props) {
{active ? ( {active ? (
<DetailSidebar> <DetailSidebar>
{selectedItem && ( {selectedItem && (
<Sidebar action={selectedItem.action} state={selectedItem.state} /> <Sidebar
action={selectedItem.action}
state={selectedItem.state}
stack={selectedItem.stack}
/>
)} )}
</DetailSidebar> </DetailSidebar>
) : null} ) : null}

View File

@@ -1,4 +1,5 @@
import { Layout, ManagedDataInspector } from 'flipper'; import { Layout, ManagedDataInspector, styled } from 'flipper';
import { theme } from 'flipper-plugin';
import * as React from 'react'; import * as React from 'react';
import { Title4 } from './Typography'; import { Title4 } from './Typography';
@@ -6,12 +7,65 @@ import { Title4 } from './Typography';
export function Sidebar({ export function Sidebar({
action, action,
state, state,
stack,
}: { }: {
action: object; action: object;
state: object | undefined; state: object | undefined;
stack: string | undefined;
}) { }) {
return ( return (
<Layout.Container gap pad> <Layout.Container gap pad>
{stack ? (
<>
<Title4>Stack</Title4>
<Code>
{stack.split('\n').map((line, index) => {
const match = line.match(/^(.+)@(.+):(\d+):(\d+)$/);
if (match) {
const [, methodName, file, lineNumber, column] = match;
if (file.includes('/node_modules/@react-navigation')) {
return null;
}
return (
// eslint-disable-next-line react/no-array-index-key
<div key={index}>
{methodName.split('.').map((part, i, self) => {
if (i === self.length - 1 && i !== 0) {
return <Method>{part}</Method>;
}
if (self.length !== 1) {
return (
<>
{part}
<Separator>.</Separator>
</>
);
}
return part;
})}{' '}
<Separator>(</Separator>
<StringToken>{file.split('/').pop()}</StringToken>
<Separator>:</Separator>
<NumberToken>{lineNumber}</NumberToken>:
<NumberToken>{column}</NumberToken>
<Separator>)</Separator>
</div>
);
}
return (
// eslint-disable-next-line react/no-array-index-key
<div key={index}>{line}</div>
);
})}
</Code>
</>
) : null}
<Title4>Action</Title4> <Title4>Action</Title4>
<ManagedDataInspector data={action} expandRoot={false} /> <ManagedDataInspector data={action} expandRoot={false} />
<Title4>State</Title4> <Title4>State</Title4>
@@ -19,3 +73,25 @@ export function Sidebar({
</Layout.Container> </Layout.Container>
); );
} }
const Code = styled.div({
fontSize: 11,
fontFamily: theme.monospace.fontFamily,
margin: '7.5px 0px',
});
const StringToken = styled.span({
color: 'rgb(224, 76, 96)',
});
const NumberToken = styled.span({
color: 'rgb(77, 187, 166)',
});
const Method = styled.span({
color: 'rgb(123, 100, 192)',
});
const Separator = styled.span({
color: '#555',
});

View File

@@ -1,8 +1,9 @@
import { styled } from 'flipper'; import { styled } from 'flipper';
import { theme } from 'flipper-plugin';
export const Title4 = styled.h4({ export const Title4 = styled.h4({
fontWeight: 600, fontWeight: 600,
fontSize: 14, fontSize: theme.fontSize.default,
lineHeight: 1.4, lineHeight: 1.4,
letterSpacing: -0.24, letterSpacing: -0.24,
marginBottom: 0, marginBottom: 0,

View File

@@ -30,6 +30,7 @@ export type Log = {
id: string; id: string;
action: NavigationAction; action: NavigationAction;
state: NavigationState | undefined; state: NavigationState | undefined;
stack: string | undefined;
}; };
export type StoreType = { export type StoreType = {

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.15](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.14...@react-navigation/material-bottom-tabs@6.0.0-next.15) (2021-06-10)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.13...@react-navigation/material-bottom-tabs@6.0.0-next.14) (2021-06-01) # [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.13...@react-navigation/material-bottom-tabs@6.0.0-next.14) (2021-06-01)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs **Note:** Version bump only for package @react-navigation/material-bottom-tabs

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/material-bottom-tabs", "name": "@react-navigation/material-bottom-tabs",
"description": "Integration for bottom navigation component from react-native-paper", "description": "Integration for bottom navigation component from react-native-paper",
"version": "6.0.0-next.14", "version": "6.0.0-next.15",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -41,13 +41,13 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/elements": "^1.0.0-next.17" "@react-navigation/elements": "^1.0.0-next.18"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"@types/react-native-vector-icons": "^6.4.6", "@types/react-native-vector-icons": "^6.4.6",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
@@ -56,7 +56,7 @@
"react-native-paper": "^4.9.1", "react-native-paper": "^4.9.1",
"react-native-safe-area-context": "~3.2.0", "react-native-safe-area-context": "~3.2.0",
"react-native-vector-icons": "^8.1.0", "react-native-vector-icons": "^8.1.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -34,24 +34,20 @@ function MaterialBottomTabNavigator({
screenOptions, screenOptions,
...rest ...rest
}: Props) { }: Props) {
const { const { state, descriptors, navigation, NavigationContent } =
state, useNavigationBuilder<
descriptors, TabNavigationState<ParamListBase>,
navigation, TabRouterOptions,
NavigationContent, TabActionHelpers<ParamListBase>,
} = useNavigationBuilder< MaterialBottomTabNavigationOptions,
TabNavigationState<ParamListBase>, MaterialBottomTabNavigationEventMap
TabRouterOptions, >(TabRouter, {
TabActionHelpers<ParamListBase>, initialRouteName,
MaterialBottomTabNavigationOptions, backBehavior,
MaterialBottomTabNavigationEventMap children,
>(TabRouter, { screenListeners,
initialRouteName, screenOptions,
backBehavior, });
children,
screenListeners,
screenOptions,
});
return ( return (
<NavigationContent> <NavigationContent>

View File

@@ -37,8 +37,8 @@ let MaterialCommunityIcons: React.ComponentType<
try { try {
// Optionally require vector-icons // Optionally require vector-icons
MaterialCommunityIcons = require('react-native-vector-icons/MaterialCommunityIcons') MaterialCommunityIcons =
.default; require('react-native-vector-icons/MaterialCommunityIcons').default;
} catch (e) { } catch (e) {
let isErrorLogged = false; let isErrorLogged = false;

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.15](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.14...@react-navigation/material-top-tabs@6.0.0-next.15) (2021-06-10)
**Note:** Version bump only for package @react-navigation/material-top-tabs
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.13...@react-navigation/material-top-tabs@6.0.0-next.14) (2021-05-29) # [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.13...@react-navigation/material-top-tabs@6.0.0-next.14) (2021-05-29)
**Note:** Version bump only for package @react-navigation/material-top-tabs **Note:** Version bump only for package @react-navigation/material-top-tabs

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/material-top-tabs", "name": "@react-navigation/material-top-tabs",
"description": "Integration for the animated tab view component from react-native-tab-view", "description": "Integration for the animated tab view component from react-native-tab-view",
"version": "6.0.0-next.14", "version": "6.0.0-next.15",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -45,17 +45,17 @@
"warn-once": "^0.1.0" "warn-once": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-native-pager-view": "^5.0.12", "react-native-pager-view": "^5.1.10",
"react-native-tab-view": "^3.0.1", "react-native-tab-view": "^3.0.1",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -78,24 +78,20 @@ function MaterialTopTabNavigator({
); );
} }
const { const { state, descriptors, navigation, NavigationContent } =
state, useNavigationBuilder<
descriptors, TabNavigationState<ParamListBase>,
navigation, TabRouterOptions,
NavigationContent, TabActionHelpers<ParamListBase>,
} = useNavigationBuilder< MaterialTopTabNavigationOptions,
TabNavigationState<ParamListBase>, MaterialTopTabNavigationEventMap
TabRouterOptions, >(TabRouter, {
TabActionHelpers<ParamListBase>, initialRouteName,
MaterialTopTabNavigationOptions, backBehavior,
MaterialTopTabNavigationEventMap children,
>(TabRouter, { screenListeners,
initialRouteName, screenOptions,
backBehavior, });
children,
screenListeners,
screenOptions,
});
return ( return (
<NavigationContent> <NavigationContent>

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native-stack@6.0.0-next.7...@react-navigation/native-stack@6.0.0-next.8) (2021-06-10)
**Note:** Version bump only for package @react-navigation/native-stack
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native-stack@6.0.0-next.6...@react-navigation/native-stack@6.0.0-next.7) (2021-06-01) # [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native-stack@6.0.0-next.6...@react-navigation/native-stack@6.0.0-next.7) (2021-06-01)
**Note:** Version bump only for package @react-navigation/native-stack **Note:** Version bump only for package @react-navigation/native-stack

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/native-stack", "name": "@react-navigation/native-stack",
"description": "Native stack navigator using react-native-screens", "description": "Native stack navigator using react-native-screens",
"version": "6.0.0-next.7", "version": "6.0.0-next.8",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -41,19 +41,19 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/elements": "^1.0.0-next.17", "@react-navigation/elements": "^1.0.0-next.18",
"warn-once": "^0.1.0" "warn-once": "^0.1.0"
}, },
"devDependencies": { "devDependencies": {
"@react-navigation/native": "^6.0.0-next.13", "@react-navigation/native": "^6.0.0-next.14",
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"react": "~16.13.1", "react": "~16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"react-native-screens": "^3.0.0", "react-native-screens": "^3.3.0",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^6.0.0", "@react-navigation/native": "^6.0.0",

View File

@@ -243,7 +243,7 @@ export type NativeStackNavigationOptions = {
* *
* @platform ios * @platform ios
*/ */
statusBarAnimation?: ScreenStackHeaderConfigProps['statusBarAnimation']; statusBarAnimation?: ScreenProps['statusBarAnimation'];
/** /**
* Whether the status bar should be hidden on this screen. * Whether the status bar should be hidden on this screen.
* Requires setting `View controller-based status bar appearance -> YES` in your Info.plist file. * Requires setting `View controller-based status bar appearance -> YES` in your Info.plist file.
@@ -261,7 +261,7 @@ export type NativeStackNavigationOptions = {
* *
* @platform ios * @platform ios
*/ */
statusBarStyle?: ScreenStackHeaderConfigProps['statusBarStyle']; statusBarStyle?: ScreenProps['statusBarStyle'];
/** /**
* Style object for the scene content. * Style object for the scene content.
*/ */
@@ -319,7 +319,7 @@ export type NativeStackNavigationOptions = {
* - "landscape_left": landscape-left orientation is permitted. * - "landscape_left": landscape-left orientation is permitted.
* - "landscape_right": landscape-right orientation is permitted. * - "landscape_right": landscape-right orientation is permitted.
*/ */
orientation?: ScreenStackHeaderConfigProps['screenOrientation']; orientation?: ScreenProps['screenOrientation'];
}; };
export type NativeStackNavigatorProps = DefaultNavigatorOptions< export type NativeStackNavigatorProps = DefaultNavigatorOptions<

View File

@@ -9,7 +9,7 @@ type ContainerProps = ViewProps & {
children: React.ReactNode; children: React.ReactNode;
}; };
let Container = (View as unknown) as React.ComponentType<ContainerProps>; let Container = View as unknown as React.ComponentType<ContainerProps>;
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
const DebugContainer = (props: ContainerProps) => { const DebugContainer = (props: ContainerProps) => {

View File

@@ -41,11 +41,7 @@ export default function HeaderConfig({
headerTitleStyle, headerTitleStyle,
headerTranslucent, headerTranslucent,
route, route,
orientation,
headerSearchBarOptions, headerSearchBarOptions,
statusBarAnimation,
statusBarHidden,
statusBarStyle,
title, title,
}: Props): JSX.Element { }: Props): JSX.Element {
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
@@ -65,15 +61,12 @@ export default function HeaderConfig({
const headerStyleFlattened = StyleSheet.flatten(headerStyle) || {}; const headerStyleFlattened = StyleSheet.flatten(headerStyle) || {};
const headerLargeStyleFlattened = StyleSheet.flatten(headerLargeStyle) || {}; const headerLargeStyleFlattened = StyleSheet.flatten(headerLargeStyle) || {};
const [ const [backTitleFontFamily, largeTitleFontFamily, titleFontFamily] =
backTitleFontFamily, processFonts([
largeTitleFontFamily, headerBackTitleStyleFlattened.fontFamily,
titleFontFamily, headerLargeTitleStyleFlattened.fontFamily,
] = processFonts([ headerTitleStyleFlattened.fontFamily,
headerBackTitleStyleFlattened.fontFamily, ]);
headerLargeTitleStyleFlattened.fontFamily,
headerTitleStyleFlattened.fontFamily,
]);
const titleText = title !== undefined ? title : route.name; const titleText = title !== undefined ? title : route.name;
@@ -126,10 +119,6 @@ export default function HeaderConfig({
largeTitleFontSize={headerLargeTitleStyleFlattened.fontSize} largeTitleFontSize={headerLargeTitleStyleFlattened.fontSize}
largeTitleFontWeight={headerLargeTitleStyleFlattened.fontWeight} largeTitleFontWeight={headerLargeTitleStyleFlattened.fontWeight}
largeTitleHideShadow={headerLargeTitleShadowVisible === false} largeTitleHideShadow={headerLargeTitleShadowVisible === false}
screenOrientation={orientation}
statusBarAnimation={statusBarAnimation}
statusBarHidden={statusBarHidden}
statusBarStyle={statusBarStyle}
title={typeof headerTitle === 'string' ? headerTitle : titleText} title={typeof headerTitle === 'string' ? headerTitle : titleText}
titleColor={ titleColor={
headerTitleStyleFlattened.color ?? headerTintColor ?? colors.text headerTitleStyleFlattened.color ?? headerTintColor ?? colors.text

View File

@@ -102,6 +102,10 @@ function NativeStackViewInner({ state, navigation, descriptors }: Props) {
headerShown, headerShown,
animationTypeForReplace = 'pop', animationTypeForReplace = 'pop',
animation, animation,
orientation,
statusBarAnimation,
statusBarHidden,
statusBarStyle,
} = options; } = options;
let { presentation = 'card' } = options; let { presentation = 'card' } = options;
@@ -131,6 +135,10 @@ function NativeStackViewInner({ state, navigation, descriptors }: Props) {
replaceAnimation={animationTypeForReplace} replaceAnimation={animationTypeForReplace}
stackPresentation={presentation === 'card' ? 'push' : presentation} stackPresentation={presentation === 'card' ? 'push' : presentation}
stackAnimation={animation} stackAnimation={animation}
screenOrientation={orientation}
statusBarAnimation={statusBarAnimation}
statusBarHidden={statusBarHidden}
statusBarStyle={statusBarStyle}
onWillAppear={() => { onWillAppear={() => {
navigation.emit({ navigation.emit({
type: 'transitionStart', type: 'transitionStart',

View File

@@ -3,6 +3,14 @@
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.
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.13...@react-navigation/native@6.0.0-next.14) (2021-06-10)
**Note:** Version bump only for package @react-navigation/native
# [6.0.0-next.13](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.12...@react-navigation/native@6.0.0-next.13) (2021-05-29) # [6.0.0-next.13](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.12...@react-navigation/native@6.0.0-next.13) (2021-05-29)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/native", "name": "@react-navigation/native",
"description": "React Native integration for React Navigation", "description": "React Native integration for React Navigation",
"version": "6.0.0-next.13", "version": "6.0.0-next.14",
"keywords": [ "keywords": [
"react-native", "react-native",
"react-navigation", "react-navigation",
@@ -37,21 +37,21 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/core": "^6.0.0-next.13", "@react-navigation/core": "^6.0.0-next.14",
"escape-string-regexp": "^4.0.0", "escape-string-regexp": "^4.0.0",
"nanoid": "^3.1.22" "nanoid": "^3.1.23"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/react-native": "^7.2.0", "@testing-library/react-native": "^7.2.0",
"@types/react": "^16.9.53", "@types/react": "^17.0.9",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^17.0.6",
"@types/react-native": "~0.64.4", "@types/react-native": "~0.64.9",
"del-cli": "^3.0.1", "del-cli": "^3.0.1",
"react": "~16.13.1", "react": "~16.13.1",
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-native": "~0.63.4", "react-native": "~0.63.4",
"react-native-builder-bob": "^0.18.1", "react-native-builder-bob": "^0.18.1",
"typescript": "^4.2.3" "typescript": "^4.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"react": "*", "react": "*",

View File

@@ -67,9 +67,8 @@ function NavigationContainerInner(
validatePathConfig(linking.config); validatePathConfig(linking.config);
} }
const refContainer = React.useRef<NavigationContainerRef<ParamListBase>>( const refContainer =
null React.useRef<NavigationContainerRef<ParamListBase>>(null);
);
useBackButton(refContainer); useBackButton(refContainer);
useDocumentTitle(refContainer, documentTitle); useDocumentTitle(refContainer, documentTitle);

View File

@@ -7,8 +7,7 @@ export type ServerContextType = {
}; };
}; };
const ServerContext = React.createContext<ServerContextType | undefined>( const ServerContext =
undefined React.createContext<ServerContextType | undefined>(undefined);
);
export default ServerContext; export default ServerContext;

View File

@@ -16,6 +16,7 @@ import NavigationContainer from '../NavigationContainer';
global.window = window; global.window = window;
// We want to use the web version of useLinking // We want to use the web version of useLinking
// eslint-disable-next-line import/extensions
jest.mock('../useLinking', () => require('../useLinking.tsx').default); jest.mock('../useLinking', () => require('../useLinking.tsx').default);
it('integrates with the history API', () => { it('integrates with the history API', () => {

View File

@@ -19,6 +19,7 @@ window.addEventListener = () => {};
window.removeEventListener = () => {}; window.removeEventListener = () => {};
// We want to use the web version of useLinking // We want to use the web version of useLinking
// eslint-disable-next-line import/extensions
jest.mock('../useLinking', () => require('../useLinking.tsx').default); jest.mock('../useLinking', () => require('../useLinking.tsx').default);
it('renders correct state with location', () => { it('renders correct state with location', () => {

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