mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 22:42:25 +08:00
Compare commits
58 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ced2a24aa6 | ||
|
|
ebf1345b39 | ||
|
|
df3544d9b4 | ||
|
|
c1e46f8e33 | ||
|
|
021a9111d7 | ||
|
|
d3ace96981 | ||
|
|
edbc6b1e84 | ||
|
|
c52d19bec8 | ||
|
|
6dd45fcff9 | ||
|
|
d62fbfe255 | ||
|
|
b14094619f | ||
|
|
4c4d864af2 | ||
|
|
e1969f4e17 | ||
|
|
175c07a28c | ||
|
|
2980627cbf | ||
|
|
d024ec6d74 | ||
|
|
4d1b85c751 | ||
|
|
4a818fdfb3 | ||
|
|
0194de1061 | ||
|
|
7b25c8eb2e | ||
|
|
9304a8a16c | ||
|
|
51b40879bd | ||
|
|
51f4d11fdf | ||
|
|
c2aa4bb2eb | ||
|
|
199a892a6d | ||
|
|
60cb3c9ba7 | ||
|
|
6ccceaea8b | ||
|
|
d14f38b80a | ||
|
|
c481748f00 | ||
|
|
d45dbe97dc | ||
|
|
7623945f6e | ||
|
|
1dddaff45c | ||
|
|
21b397f0d6 | ||
|
|
2ff0531695 | ||
|
|
0149e85a95 | ||
|
|
3c47716826 | ||
|
|
acc9646426 | ||
|
|
6dce0780ed | ||
|
|
dd7cff2016 | ||
|
|
740c6b6706 | ||
|
|
039017bc2a | ||
|
|
b85a1c3055 | ||
|
|
18f8188dc8 | ||
|
|
47a1229837 | ||
|
|
00b11e303e | ||
|
|
f384706741 | ||
|
|
d1a6f3e30e | ||
|
|
fd6636a8cd | ||
|
|
eb24fea8b9 | ||
|
|
85ae378d8c | ||
|
|
bea14aa26f | ||
|
|
4d1e102f8c | ||
|
|
f07cd13561 | ||
|
|
f6d06768d3 | ||
|
|
3381d680d7 | ||
|
|
fcd1cc64c1 | ||
|
|
3999fc2836 | ||
|
|
9fd2635756 |
@@ -1,89 +1,96 @@
|
|||||||
version: 2
|
version: 2.1
|
||||||
|
|
||||||
defaults: &defaults
|
executors:
|
||||||
docker:
|
default:
|
||||||
- image: circleci/node:10
|
docker:
|
||||||
working_directory: ~/project
|
- image: circleci/node:10
|
||||||
|
working_directory: ~/project
|
||||||
|
environment:
|
||||||
|
YARN_CACHE_FOLDER: "~/.cache/yarn"
|
||||||
|
|
||||||
|
commands:
|
||||||
|
attach_project:
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: ~/project
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
install-dependencies:
|
install-dependencies:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v1-dependencies-{{ checksum "yarn.lock" }}
|
- v2-dependencies-{{ checksum "yarn.lock" }}
|
||||||
- v1-dependencies-
|
- v2-dependencies-
|
||||||
- run:
|
- run:
|
||||||
name: Install project dependencies
|
name: Install project dependencies
|
||||||
command: yarn install --frozen-lockfile
|
command: yarn install --frozen-lockfile
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: v1-dependencies-{{ checksum "yarn.lock" }}
|
key: v2-dependencies-{{ checksum "yarn.lock" }}
|
||||||
paths: node_modules
|
paths: ~/.cache/yarn
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths: .
|
paths: .
|
||||||
|
|
||||||
lint-and-typecheck:
|
lint-and-typecheck:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
- run:
|
||||||
- run:
|
name: Lint files
|
||||||
name: Lint files
|
command: yarn lint
|
||||||
command: yarn lint
|
- run:
|
||||||
- run:
|
name: Typecheck files
|
||||||
name: Typecheck files
|
command: yarn typescript
|
||||||
command: yarn typescript
|
|
||||||
unit-tests:
|
unit-tests:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
- run:
|
||||||
- run:
|
name: Run unit tests
|
||||||
name: Run unit tests
|
command: yarn test --coverage
|
||||||
command: yarn test --coverage
|
- run:
|
||||||
- run:
|
name: Upload test coverage
|
||||||
name: Upload test coverage
|
command: cat ./coverage/lcov.info | ./node_modules/.bin/codecov
|
||||||
command: cat ./coverage/lcov.info | ./node_modules/.bin/codecov
|
- store_artifacts:
|
||||||
- store_artifacts:
|
path: coverage
|
||||||
path: coverage
|
destination: coverage
|
||||||
destination: coverage
|
|
||||||
integration-tests:
|
integration-tests:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
- run:
|
||||||
- run:
|
name: Install Headless Chrome dependencies
|
||||||
name: Install Headless Chrome dependencies
|
command: |
|
||||||
command: |
|
sudo apt-get install -yq \
|
||||||
sudo apt-get install -yq \
|
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
|
||||||
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
|
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
|
||||||
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \
|
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
|
||||||
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \
|
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
|
||||||
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \
|
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
|
||||||
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
|
- run:
|
||||||
- run:
|
name: Build example for web
|
||||||
name: Build example for web
|
command: yarn example expo build:web --no-pwa
|
||||||
command: yarn example expo build:web --no-pwa
|
- run:
|
||||||
- run:
|
name: Run integration tests
|
||||||
name: Run integration tests
|
command: yarn example test --maxWorkers=2
|
||||||
command: yarn example test --maxWorkers=2
|
|
||||||
build-packages:
|
build-packages:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
- run:
|
||||||
- run:
|
name: Build packages in the monorepo
|
||||||
name: Build packages in the monorepo
|
command: yarn lerna run prepare
|
||||||
command: yarn lerna run prepare
|
- run:
|
||||||
- run:
|
name: Verify paths for types
|
||||||
name: Verify paths for types
|
command: node scripts/check-types-path.js
|
||||||
command: node scripts/check-types-path.js
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
|
||||||
build-and-test:
|
build-and-test:
|
||||||
jobs:
|
jobs:
|
||||||
- install-dependencies
|
- install-dependencies
|
||||||
|
|||||||
41
example/CHANGELOG.md
Normal file
41
example/CHANGELOG.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.1.0](https://github.com/react-navigation/react-navigation/compare/@react-navigation/example@5.0.0-alpha.23...@react-navigation/example@5.1.0) (2020-05-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add config to enable redux devtools integration ([c9c825b](https://github.com/react-navigation/react-navigation/commit/c9c825bee61426635a28ee149eeeff3d628171cd))
|
||||||
|
* clamp interpolated styles ([67798af](https://github.com/react-navigation/react-navigation/commit/67798af869dcbbf323629fc7e7cc9062d1e12c29))
|
||||||
|
* disable screens when mode is modal on older expo versions ([94d7b28](https://github.com/react-navigation/react-navigation/commit/94d7b28c0b2ce0d56c99b224610f305be6451626))
|
||||||
|
* dispatch pop early when screen is closed with gesture ([#336](https://github.com/react-navigation/react-navigation/issues/336)) ([3d937d1](https://github.com/react-navigation/react-navigation/commit/3d937d1e6571cd613e830d64f7b2e7426076d371)), closes [#267](https://github.com/react-navigation/react-navigation/issues/267)
|
||||||
|
* provide initial values for safe area to prevent blank screen ([#238](https://github.com/react-navigation/react-navigation/issues/238)) ([77b7570](https://github.com/react-navigation/react-navigation/commit/77b757091c0451e20bca01138629669c7da544a8))
|
||||||
|
* render fallback only if linking is enabled. closes [#8161](https://github.com/react-navigation/react-navigation/issues/8161) ([1c075ff](https://github.com/react-navigation/react-navigation/commit/1c075ffb169d233ed0515efea264a5a69b4de52e))
|
||||||
|
* return onPress instead of onClick for useLinkProps ([ae5442e](https://github.com/react-navigation/react-navigation/commit/ae5442ebe812b91fa1f12164f27d1aeed918ab0e))
|
||||||
|
* rtl in native app example ([50b366e](https://github.com/react-navigation/react-navigation/commit/50b366e7341f201d29a44f20b7771b3a832b0045))
|
||||||
|
* screens integration on Android ([#294](https://github.com/react-navigation/react-navigation/issues/294)) ([9bfb295](https://github.com/react-navigation/react-navigation/commit/9bfb29562020c61b4d5c9bee278bcb1c7bdb8b67))
|
||||||
|
* spread parent params to children in compat navigator ([24febf6](https://github.com/react-navigation/react-navigation/commit/24febf6ea99be2e5f22005fdd2a82136d647255c)), closes [#6785](https://github.com/react-navigation/react-navigation/issues/6785)
|
||||||
|
* update screens for native stack ([5411816](https://github.com/react-navigation/react-navigation/commit/54118161885738a6d20b062c7e6679f3bace8424))
|
||||||
|
* wrap navigators in gesture handler root ([41a5e1a](https://github.com/react-navigation/react-navigation/commit/41a5e1a385aa5180abc3992a4c67077c37b998b9))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `animationTypeForReplace` option ([#297](https://github.com/react-navigation/react-navigation/issues/297)) ([6262f72](https://github.com/react-navigation/react-navigation/commit/6262f7298bff843571fb4b1a677d3beabe29833e))
|
||||||
|
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/react-navigation/issues/308)) ([b931ae6](https://github.com/react-navigation/react-navigation/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
|
||||||
|
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
|
||||||
|
* add a useLinkProps hook ([f2291d1](https://github.com/react-navigation/react-navigation/commit/f2291d110faa2aa8e10c9133c1c0c28d54af7917))
|
||||||
|
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/commit/942d2be2c72720469475ce12ec8df23825994dbf))
|
||||||
|
* add custom theme support ([#211](https://github.com/react-navigation/react-navigation/issues/211)) ([00fc616](https://github.com/react-navigation/react-navigation/commit/00fc616de0572bade8aa85052cdc8290360b1d7f))
|
||||||
|
* add deeplinking to native example ([#309](https://github.com/react-navigation/react-navigation/issues/309)) ([e55e866](https://github.com/react-navigation/react-navigation/commit/e55e866af2f2163ee89bc527997cda13ffeb2abe))
|
||||||
|
* add headerStatusBarHeight option to stack ([b201fd2](https://github.com/react-navigation/react-navigation/commit/b201fd20716a2f03cb9373c72281f5d396a9356d))
|
||||||
|
* add Link component as useLinkTo hook for navigating to links ([2573b5b](https://github.com/react-navigation/react-navigation/commit/2573b5beaac1240434e52f3f57bb29da2f541c88))
|
||||||
|
* add openByDefault option to drawer ([36689e2](https://github.com/react-navigation/react-navigation/commit/36689e24c21b474692bb7ecd0b901c8afbbe9a20))
|
||||||
|
* add permanent drawer type ([#7818](https://github.com/react-navigation/react-navigation/issues/7818)) ([6a5d0a0](https://github.com/react-navigation/react-navigation/commit/6a5d0a035afae60d91aef78401ec8826295746fe))
|
||||||
|
* add preventDefault functionality in material bottom tabs ([3dede31](https://github.com/react-navigation/react-navigation/commit/3dede316ccab3b2403a475f60ce20b5c4e4cc068))
|
||||||
|
* emit appear and dismiss events for native stack ([f1df4a0](https://github.com/react-navigation/react-navigation/commit/f1df4a080877b3642e748a41a5ffc2da8c449a8c))
|
||||||
|
* initialState should take priority over deep link ([039017b](https://github.com/react-navigation/react-navigation/commit/039017bc2af69120d2d10e8f2c8a62919c37eb65))
|
||||||
|
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/react-navigation/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
|
||||||
@@ -7,12 +7,6 @@
|
|||||||
"slug": "react-navigation-example",
|
"slug": "react-navigation-example",
|
||||||
"description": "Demo app to showcase various functionality of React Navigation",
|
"description": "Demo app to showcase various functionality of React Navigation",
|
||||||
"privacy": "public",
|
"privacy": "public",
|
||||||
"sdkVersion": "37.0.0",
|
|
||||||
"platforms": [
|
|
||||||
"ios",
|
|
||||||
"android",
|
|
||||||
"web"
|
|
||||||
],
|
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"splash": {
|
"splash": {
|
||||||
@@ -20,15 +14,16 @@
|
|||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"updates": {
|
"sdkVersion": "37.0.0",
|
||||||
"fallbackToCacheTimeout": 0
|
"platforms": ["ios", "android", "web"],
|
||||||
},
|
|
||||||
"assetBundlePatterns": [
|
|
||||||
"**/*"
|
|
||||||
],
|
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true
|
"supportsTablet": true
|
||||||
},
|
},
|
||||||
|
"updates": {
|
||||||
|
"fallbackToCacheTimeout": 0
|
||||||
|
},
|
||||||
|
"assetBundlePatterns": ["**/*"],
|
||||||
|
"scheme": "rne",
|
||||||
"entryPoint": "App.tsx"
|
"entryPoint": "App.tsx"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ beforeEach(async () => {
|
|||||||
|
|
||||||
it('loads the article page', async () => {
|
it('loads the article page', async () => {
|
||||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||||
'/link-component/Article?author=Gandalf'
|
'/link-component/article/gandalf'
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
((await page.accessibility.snapshot()) as any)?.children?.find(
|
((await page.accessibility.snapshot()) as any)?.children?.find(
|
||||||
@@ -16,24 +16,24 @@ it('loads the article page', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('goes to the album page and goes back', async () => {
|
it('goes to the album page and goes back', async () => {
|
||||||
await page.click('[href="/link-component/Album"]');
|
await page.click('[href="/link-component/music"]');
|
||||||
|
|
||||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||||
'/link-component/Album'
|
'/link-component/music'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
((await page.accessibility.snapshot()) as any)?.children?.find(
|
((await page.accessibility.snapshot()) as any)?.children?.find(
|
||||||
(it: any) => it.role === 'heading'
|
(it: any) => it.role === 'heading'
|
||||||
)?.name
|
)?.name
|
||||||
).toBe('Album');
|
).toBe('Albums');
|
||||||
|
|
||||||
await page.click('[aria-label="Article by Gandalf, back"]');
|
await page.click('[aria-label="Article by Gandalf, back"]');
|
||||||
|
|
||||||
await page.waitForNavigation();
|
await page.waitForNavigation();
|
||||||
|
|
||||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||||
'/link-component/Article?author=Gandalf'
|
'/link-component/article/gandalf'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -1,35 +1,38 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- boost-for-react-native (1.63.0)
|
- boost-for-react-native (1.63.0)
|
||||||
- DoubleConversion (1.1.6)
|
- DoubleConversion (1.1.6)
|
||||||
- EXAppLoaderProvider (8.0.0)
|
- EXBlur (8.1.0):
|
||||||
- EXBlur (8.0.0):
|
|
||||||
- UMCore
|
- UMCore
|
||||||
- EXConstants (8.0.0):
|
- EXConstants (9.0.0):
|
||||||
- UMConstantsInterface
|
- UMConstantsInterface
|
||||||
- UMCore
|
- UMCore
|
||||||
- EXErrorRecovery (1.0.0):
|
- EXErrorRecovery (1.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- EXFileSystem (8.0.0):
|
- EXFileSystem (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMFileSystemInterface
|
- UMFileSystemInterface
|
||||||
- EXFont (8.0.0):
|
- EXFont (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMFontInterface
|
- UMFontInterface
|
||||||
- EXKeepAwake (8.0.0):
|
- EXImageLoader (1.0.1):
|
||||||
|
- React-Core
|
||||||
- UMCore
|
- UMCore
|
||||||
- EXLinearGradient (8.0.0):
|
- UMImageLoaderInterface
|
||||||
|
- EXKeepAwake (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- EXLocation (8.0.0):
|
- EXLinearGradient (8.1.0):
|
||||||
|
- UMCore
|
||||||
|
- EXLocation (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMPermissionsInterface
|
- UMPermissionsInterface
|
||||||
- UMTaskManagerInterface
|
- UMTaskManagerInterface
|
||||||
- EXPermissions (8.0.0):
|
- EXPermissions (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMPermissionsInterface
|
- UMPermissionsInterface
|
||||||
- EXSQLite (8.0.0):
|
- EXSQLite (8.1.0):
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMFileSystemInterface
|
- UMFileSystemInterface
|
||||||
- EXWebBrowser (8.0.0):
|
- EXWebBrowser (8.2.1):
|
||||||
- UMCore
|
- UMCore
|
||||||
- FBLazyVector (0.61.5)
|
- FBLazyVector (0.61.5)
|
||||||
- FBReactNativeSpec (0.61.5):
|
- FBReactNativeSpec (0.61.5):
|
||||||
@@ -50,8 +53,6 @@ PODS:
|
|||||||
- glog
|
- glog
|
||||||
- glog (0.3.5)
|
- glog (0.3.5)
|
||||||
- RCTRequired (0.61.5)
|
- RCTRequired (0.61.5)
|
||||||
- RCTRestart (0.0.13):
|
|
||||||
- React
|
|
||||||
- RCTTypeSafety (0.61.5):
|
- RCTTypeSafety (0.61.5):
|
||||||
- FBLazyVector (= 0.61.5)
|
- FBLazyVector (= 0.61.5)
|
||||||
- Folly (= 2018.10.22.00)
|
- Folly (= 2018.10.22.00)
|
||||||
@@ -214,7 +215,9 @@ PODS:
|
|||||||
- React-cxxreact (= 0.61.5)
|
- React-cxxreact (= 0.61.5)
|
||||||
- React-jsi (= 0.61.5)
|
- React-jsi (= 0.61.5)
|
||||||
- React-jsinspector (0.61.5)
|
- React-jsinspector (0.61.5)
|
||||||
- react-native-safe-area-context (0.6.2):
|
- react-native-restart (0.0.15):
|
||||||
|
- React
|
||||||
|
- react-native-safe-area-context (1.0.0):
|
||||||
- React
|
- React
|
||||||
- React-RCTActionSheet (0.61.5):
|
- React-RCTActionSheet (0.61.5):
|
||||||
- React-Core/RCTActionSheetHeaders (= 0.61.5)
|
- React-Core/RCTActionSheetHeaders (= 0.61.5)
|
||||||
@@ -251,39 +254,41 @@ PODS:
|
|||||||
- React-cxxreact (= 0.61.5)
|
- React-cxxreact (= 0.61.5)
|
||||||
- React-jsi (= 0.61.5)
|
- React-jsi (= 0.61.5)
|
||||||
- ReactCommon/jscallinvoker (= 0.61.5)
|
- ReactCommon/jscallinvoker (= 0.61.5)
|
||||||
- RNCMaskedView (0.1.5):
|
- RNCMaskedView (0.1.10):
|
||||||
- React
|
- React
|
||||||
- RNGestureHandler (1.5.5):
|
- RNGestureHandler (1.6.1):
|
||||||
- React
|
- React
|
||||||
- RNReanimated (1.4.0):
|
- RNReanimated (1.8.0):
|
||||||
- React
|
- React
|
||||||
- RNScreens (2.0.0-alpha.33):
|
- RNScreens (2.7.0):
|
||||||
- React
|
- React
|
||||||
- UMBarCodeScannerInterface (5.0.0)
|
- UMAppLoader (1.0.2)
|
||||||
- UMCameraInterface (5.0.0)
|
- UMBarCodeScannerInterface (5.1.0)
|
||||||
- UMConstantsInterface (5.0.0)
|
- UMCameraInterface (5.1.0)
|
||||||
- UMCore (5.0.0)
|
- UMConstantsInterface (5.1.0)
|
||||||
- UMFaceDetectorInterface (5.0.0)
|
- UMCore (5.1.2)
|
||||||
- UMFileSystemInterface (5.0.0)
|
- UMFaceDetectorInterface (5.1.0)
|
||||||
- UMFontInterface (5.0.0)
|
- UMFileSystemInterface (5.1.0)
|
||||||
- UMImageLoaderInterface (5.0.0)
|
- UMFontInterface (5.1.0)
|
||||||
- UMPermissionsInterface (5.0.0)
|
- UMImageLoaderInterface (5.1.0)
|
||||||
- UMReactNativeAdapter (5.0.0):
|
- UMPermissionsInterface (5.1.0):
|
||||||
|
- UMCore
|
||||||
|
- UMReactNativeAdapter (5.2.0):
|
||||||
- React-Core
|
- React-Core
|
||||||
- UMCore
|
- UMCore
|
||||||
- UMFontInterface
|
- UMFontInterface
|
||||||
- UMSensorsInterface (5.0.0)
|
- UMSensorsInterface (5.1.0)
|
||||||
- UMTaskManagerInterface (5.0.0)
|
- UMTaskManagerInterface (5.1.0)
|
||||||
- Yoga (1.14.0)
|
- Yoga (1.14.0)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
- DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||||
- EXAppLoaderProvider (from `../../node_modules/expo-app-loader-provider/ios`)
|
|
||||||
- EXBlur (from `../../node_modules/expo-blur/ios`)
|
- EXBlur (from `../../node_modules/expo-blur/ios`)
|
||||||
- EXConstants (from `../../node_modules/expo-constants/ios`)
|
- EXConstants (from `../../node_modules/expo-constants/ios`)
|
||||||
- EXErrorRecovery (from `../../node_modules/expo-error-recovery/ios`)
|
- EXErrorRecovery (from `../../node_modules/expo-error-recovery/ios`)
|
||||||
- EXFileSystem (from `../../node_modules/expo-file-system/ios`)
|
- EXFileSystem (from `../../node_modules/expo-file-system/ios`)
|
||||||
- EXFont (from `../../node_modules/expo-font/ios`)
|
- EXFont (from `../../node_modules/expo-font/ios`)
|
||||||
|
- EXImageLoader (from `../../node_modules/expo-image-loader/ios`)
|
||||||
- EXKeepAwake (from `../../node_modules/expo-keep-awake/ios`)
|
- EXKeepAwake (from `../../node_modules/expo-keep-awake/ios`)
|
||||||
- EXLinearGradient (from `../../node_modules/expo-linear-gradient/ios`)
|
- EXLinearGradient (from `../../node_modules/expo-linear-gradient/ios`)
|
||||||
- EXLocation (from `../../node_modules/expo-location/ios`)
|
- EXLocation (from `../../node_modules/expo-location/ios`)
|
||||||
@@ -295,7 +300,6 @@ DEPENDENCIES:
|
|||||||
- Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
- Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||||
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||||
- RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
|
- RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
|
||||||
- RCTRestart (from `../../node_modules/react-native-restart/ios`)
|
|
||||||
- RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
|
- RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
|
||||||
- React (from `../../node_modules/react-native/`)
|
- React (from `../../node_modules/react-native/`)
|
||||||
- React-Core (from `../../node_modules/react-native/`)
|
- React-Core (from `../../node_modules/react-native/`)
|
||||||
@@ -306,6 +310,7 @@ DEPENDENCIES:
|
|||||||
- React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
|
- React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
|
||||||
- React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
|
- React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
|
||||||
- React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
|
- React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
|
||||||
|
- react-native-restart (from `../../node_modules/react-native-restart`)
|
||||||
- react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
|
- react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
|
||||||
- React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
|
- React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
|
||||||
- React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
|
- React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
|
||||||
@@ -322,10 +327,11 @@ DEPENDENCIES:
|
|||||||
- RNGestureHandler (from `../../node_modules/react-native-gesture-handler`)
|
- RNGestureHandler (from `../../node_modules/react-native-gesture-handler`)
|
||||||
- RNReanimated (from `../../node_modules/react-native-reanimated`)
|
- RNReanimated (from `../../node_modules/react-native-reanimated`)
|
||||||
- RNScreens (from `../../node_modules/react-native-screens`)
|
- RNScreens (from `../../node_modules/react-native-screens`)
|
||||||
|
- UMAppLoader (from `../../node_modules/unimodules-app-loader/ios`)
|
||||||
- UMBarCodeScannerInterface (from `../../node_modules/unimodules-barcode-scanner-interface/ios`)
|
- UMBarCodeScannerInterface (from `../../node_modules/unimodules-barcode-scanner-interface/ios`)
|
||||||
- UMCameraInterface (from `../../node_modules/unimodules-camera-interface/ios`)
|
- UMCameraInterface (from `../../node_modules/unimodules-camera-interface/ios`)
|
||||||
- UMConstantsInterface (from `../../node_modules/unimodules-constants-interface/ios`)
|
- UMConstantsInterface (from `../../node_modules/unimodules-constants-interface/ios`)
|
||||||
- "UMCore (from `../../node_modules/@unimodules/core/ios`)"
|
- "UMCore (from `../../node_modules/react-native-unimodules/node_modules/@unimodules/core/ios`)"
|
||||||
- UMFaceDetectorInterface (from `../../node_modules/unimodules-face-detector-interface/ios`)
|
- UMFaceDetectorInterface (from `../../node_modules/unimodules-face-detector-interface/ios`)
|
||||||
- UMFileSystemInterface (from `../../node_modules/unimodules-file-system-interface/ios`)
|
- UMFileSystemInterface (from `../../node_modules/unimodules-file-system-interface/ios`)
|
||||||
- UMFontInterface (from `../../node_modules/unimodules-font-interface/ios`)
|
- UMFontInterface (from `../../node_modules/unimodules-font-interface/ios`)
|
||||||
@@ -343,42 +349,30 @@ SPEC REPOS:
|
|||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
DoubleConversion:
|
DoubleConversion:
|
||||||
:podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
:podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
|
||||||
EXAppLoaderProvider:
|
|
||||||
:path: !ruby/object:Pathname
|
|
||||||
path: "../../node_modules/expo-app-loader-provider/ios"
|
|
||||||
EXBlur:
|
EXBlur:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-blur/ios"
|
||||||
path: "../../node_modules/expo-blur/ios"
|
|
||||||
EXConstants:
|
EXConstants:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-constants/ios"
|
||||||
path: "../../node_modules/expo-constants/ios"
|
|
||||||
EXErrorRecovery:
|
EXErrorRecovery:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-error-recovery/ios"
|
||||||
path: "../../node_modules/expo-error-recovery/ios"
|
|
||||||
EXFileSystem:
|
EXFileSystem:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-file-system/ios"
|
||||||
path: "../../node_modules/expo-file-system/ios"
|
|
||||||
EXFont:
|
EXFont:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-font/ios"
|
||||||
path: "../../node_modules/expo-font/ios"
|
EXImageLoader:
|
||||||
|
:path: "../../node_modules/expo-image-loader/ios"
|
||||||
EXKeepAwake:
|
EXKeepAwake:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-keep-awake/ios"
|
||||||
path: "../../node_modules/expo-keep-awake/ios"
|
|
||||||
EXLinearGradient:
|
EXLinearGradient:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-linear-gradient/ios"
|
||||||
path: "../../node_modules/expo-linear-gradient/ios"
|
|
||||||
EXLocation:
|
EXLocation:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-location/ios"
|
||||||
path: "../../node_modules/expo-location/ios"
|
|
||||||
EXPermissions:
|
EXPermissions:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-permissions/ios"
|
||||||
path: "../../node_modules/expo-permissions/ios"
|
|
||||||
EXSQLite:
|
EXSQLite:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-sqlite/ios"
|
||||||
path: "../../node_modules/expo-sqlite/ios"
|
|
||||||
EXWebBrowser:
|
EXWebBrowser:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/expo-web-browser/ios"
|
||||||
path: "../../node_modules/expo-web-browser/ios"
|
|
||||||
FBLazyVector:
|
FBLazyVector:
|
||||||
:path: "../../node_modules/react-native/Libraries/FBLazyVector"
|
:path: "../../node_modules/react-native/Libraries/FBLazyVector"
|
||||||
FBReactNativeSpec:
|
FBReactNativeSpec:
|
||||||
@@ -389,8 +383,6 @@ EXTERNAL SOURCES:
|
|||||||
:podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
|
:podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||||
RCTRequired:
|
RCTRequired:
|
||||||
:path: "../../node_modules/react-native/Libraries/RCTRequired"
|
:path: "../../node_modules/react-native/Libraries/RCTRequired"
|
||||||
RCTRestart:
|
|
||||||
:path: "../../node_modules/react-native-restart/ios"
|
|
||||||
RCTTypeSafety:
|
RCTTypeSafety:
|
||||||
:path: "../../node_modules/react-native/Libraries/TypeSafety"
|
:path: "../../node_modules/react-native/Libraries/TypeSafety"
|
||||||
React:
|
React:
|
||||||
@@ -407,6 +399,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../../node_modules/react-native/ReactCommon/jsiexecutor"
|
:path: "../../node_modules/react-native/ReactCommon/jsiexecutor"
|
||||||
React-jsinspector:
|
React-jsinspector:
|
||||||
:path: "../../node_modules/react-native/ReactCommon/jsinspector"
|
:path: "../../node_modules/react-native/ReactCommon/jsinspector"
|
||||||
|
react-native-restart:
|
||||||
|
:path: "../../node_modules/react-native-restart"
|
||||||
react-native-safe-area-context:
|
react-native-safe-area-context:
|
||||||
:path: "../../node_modules/react-native-safe-area-context"
|
:path: "../../node_modules/react-native-safe-area-context"
|
||||||
React-RCTActionSheet:
|
React-RCTActionSheet:
|
||||||
@@ -437,66 +431,55 @@ EXTERNAL SOURCES:
|
|||||||
:path: "../../node_modules/react-native-reanimated"
|
:path: "../../node_modules/react-native-reanimated"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../../node_modules/react-native-screens"
|
:path: "../../node_modules/react-native-screens"
|
||||||
|
UMAppLoader:
|
||||||
|
:path: "../../node_modules/unimodules-app-loader/ios"
|
||||||
UMBarCodeScannerInterface:
|
UMBarCodeScannerInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-barcode-scanner-interface/ios"
|
||||||
path: "../../node_modules/unimodules-barcode-scanner-interface/ios"
|
|
||||||
UMCameraInterface:
|
UMCameraInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-camera-interface/ios"
|
||||||
path: "../../node_modules/unimodules-camera-interface/ios"
|
|
||||||
UMConstantsInterface:
|
UMConstantsInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-constants-interface/ios"
|
||||||
path: "../../node_modules/unimodules-constants-interface/ios"
|
|
||||||
UMCore:
|
UMCore:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/react-native-unimodules/node_modules/@unimodules/core/ios"
|
||||||
path: "../../node_modules/@unimodules/core/ios"
|
|
||||||
UMFaceDetectorInterface:
|
UMFaceDetectorInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-face-detector-interface/ios"
|
||||||
path: "../../node_modules/unimodules-face-detector-interface/ios"
|
|
||||||
UMFileSystemInterface:
|
UMFileSystemInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-file-system-interface/ios"
|
||||||
path: "../../node_modules/unimodules-file-system-interface/ios"
|
|
||||||
UMFontInterface:
|
UMFontInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-font-interface/ios"
|
||||||
path: "../../node_modules/unimodules-font-interface/ios"
|
|
||||||
UMImageLoaderInterface:
|
UMImageLoaderInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-image-loader-interface/ios"
|
||||||
path: "../../node_modules/unimodules-image-loader-interface/ios"
|
|
||||||
UMPermissionsInterface:
|
UMPermissionsInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-permissions-interface/ios"
|
||||||
path: "../../node_modules/unimodules-permissions-interface/ios"
|
|
||||||
UMReactNativeAdapter:
|
UMReactNativeAdapter:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/@unimodules/react-native-adapter/ios"
|
||||||
path: "../../node_modules/@unimodules/react-native-adapter/ios"
|
|
||||||
UMSensorsInterface:
|
UMSensorsInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-sensors-interface/ios"
|
||||||
path: "../../node_modules/unimodules-sensors-interface/ios"
|
|
||||||
UMTaskManagerInterface:
|
UMTaskManagerInterface:
|
||||||
:path: !ruby/object:Pathname
|
:path: "../../node_modules/unimodules-task-manager-interface/ios"
|
||||||
path: "../../node_modules/unimodules-task-manager-interface/ios"
|
|
||||||
Yoga:
|
Yoga:
|
||||||
:path: "../../node_modules/react-native/ReactCommon/yoga"
|
:path: "../../node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||||
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
|
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
|
||||||
EXAppLoaderProvider: ebdb6bc2632c1ccadbe49f5e4104d8d690969c49
|
EXBlur: aa14d84bff6e9c2232fbcaf54ad809eee1cc41dc
|
||||||
EXBlur: d1604f66f89a9414f5ee65dfb23874437c1bb147
|
EXConstants: 5304709b1bea70a4828f48ba4c7fc3ec3b2d9b17
|
||||||
EXConstants: 4051b16c17ef3defa03c541d42811dc92b249146
|
EXErrorRecovery: 8f4c21ab2f51bf75defe4536f841a37de59b0661
|
||||||
EXErrorRecovery: d36db99ec6a3808f313f01b0890eb443796dd1c2
|
EXFileSystem: cf4232ba7c62dc49b78c2d36005f97b6fddf0b01
|
||||||
EXFileSystem: 6e0d9bb6cc4ea404dbb8f583c1a8a2dcdf4b83b6
|
EXFont: 8326ecf966be559f7ced7c8e221a32fc4d9ed8b0
|
||||||
EXFont: 6187b5ab46ee578d5f8e7f2ea092752e78772235
|
EXImageLoader: 5ad6896fa1ef2ee814b551873cbf7a7baccc694a
|
||||||
EXKeepAwake: 66e9f80b6d129633725a0e42f8d285c229876811
|
EXKeepAwake: d045bc2cf1ad5a04f0323cc7c894b95b414042e0
|
||||||
EXLinearGradient: 75f302f9d6484267a3f6d3252df2e7a5f00e716a
|
EXLinearGradient: 97d8095d1e4ad96f7893e010e564796ed8aeea42
|
||||||
EXLocation: 3c75d012ca92eed94d4338778d79c49d1252393a
|
EXLocation: bbd487fd96a18a3ad9725389bbb94c4a5f78edf3
|
||||||
EXPermissions: 9bc08859a675d291e89be9a0870155c27c16ac35
|
EXPermissions: 24b97f734ce9172d245a5be38ad9ccfcb6135964
|
||||||
EXSQLite: 220226a354912b100dfe913f5fe6f31762c8927e
|
EXSQLite: 877ad6c8eb169353a2f94d5ad26510ffadd46a1f
|
||||||
EXWebBrowser: db32607359fb7b55b7b7b91df32dd3d8355bb3b7
|
EXWebBrowser: 5902f99ac5ac551e5c82ff46f13a337b323aa9ea
|
||||||
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
|
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
|
||||||
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
|
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
|
||||||
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
|
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
|
||||||
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
|
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
|
||||||
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
|
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
|
||||||
RCTRestart: dd19aab87fc1118e05b6b5b91b959105647f56b4
|
|
||||||
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
|
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
|
||||||
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
|
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
|
||||||
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
|
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
|
||||||
@@ -505,7 +488,8 @@ SPEC CHECKSUMS:
|
|||||||
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
|
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
|
||||||
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
|
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
|
||||||
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
|
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
|
||||||
react-native-safe-area-context: 25260c5d0b9c53fd7aa88e569e2edae72af1f6a3
|
react-native-restart: fff228304625f55de2ebd4de43938110f4c888ed
|
||||||
|
react-native-safe-area-context: a346c75f2288147527365ce27b59ca6d38c27805
|
||||||
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
|
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
|
||||||
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
|
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
|
||||||
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
|
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
|
||||||
@@ -516,24 +500,25 @@ SPEC CHECKSUMS:
|
|||||||
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
|
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
|
||||||
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
|
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
|
||||||
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
|
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
|
||||||
RNCMaskedView: dd13f9f7b146a9ad82f9b7eb6c9b5548fcf6e990
|
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
|
||||||
RNGestureHandler: d2270608171c868581b840cfc692f2962c05cd17
|
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
|
||||||
RNReanimated: b2ab0b693dddd2339bd2f300e770f6302d2e960c
|
RNReanimated: 955cf4068714003d2f1a6e2bae3fb1118f359aff
|
||||||
RNScreens: 1c7fd499b915c77c21e8e6c327890c5af9b4cf7e
|
RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
|
||||||
UMBarCodeScannerInterface: 3802c8574ef119c150701d679ab386e2266d6a54
|
UMAppLoader: ee77a072f9e15128f777ccd6d2d00f52ab4387e6
|
||||||
UMCameraInterface: 985d301f688ed392f815728f0dd906ca34b7ccb1
|
UMBarCodeScannerInterface: 9dc692b87e5f20fe277fa57aa47f45d418c3cc6c
|
||||||
UMConstantsInterface: bda5f8bd3403ad99e663eb3c4da685d063c5653c
|
UMCameraInterface: 625878bbf2ba188a8548675e1d1d2e438a653e6d
|
||||||
UMCore: 7ab08669a8bb2e61f557c1fe9784521cb5aa28e3
|
UMConstantsInterface: 64060cf86587bcd90b1dbd804cceb6d377a308c1
|
||||||
UMFaceDetectorInterface: ce14e8e597f6a52aa66e4ab956cb5bff4fa8acf8
|
UMCore: eb200e882eadafcd31ead290770835fd648c0945
|
||||||
UMFileSystemInterface: 2ed004c9620f43f0b36b33c42ce668500850d6a4
|
UMFaceDetectorInterface: d6677d6ddc9ab95a0ca857aa7f8ba76656cc770f
|
||||||
UMFontInterface: 24fbc0a02ade6c60ad3ee3e2b5d597c8dcfc3208
|
UMFileSystemInterface: c70ea7147198b9807080f3597f26236be49b0165
|
||||||
UMImageLoaderInterface: 3976a14c588341228881ff75970fbabf122efca4
|
UMFontInterface: d9d3b27af698c5389ae9e20b99ef56a083f491fb
|
||||||
UMPermissionsInterface: 2abf9f7f4aa7110e27beaf634a7deda2d50ff3d7
|
UMImageLoaderInterface: 14dd2c46c67167491effc9e91250e9510f12709e
|
||||||
UMReactNativeAdapter: 230406e3335a8dbd4c9c0e654488a1cf3b44552f
|
UMPermissionsInterface: 5e83a9167c177e4a0f0a3539345983cc749efb3e
|
||||||
UMSensorsInterface: d708a892ef1500bdd9fc3ff03f7836c66d1634d3
|
UMReactNativeAdapter: 126da3486c1a1f11945b649d557d6c2ebb9407b2
|
||||||
UMTaskManagerInterface: a98e37a576a5220bf43b8faf33cfdc129d2f441d
|
UMSensorsInterface: 48941f70175e2975af1a9386c6d6cb16d8126805
|
||||||
|
UMTaskManagerInterface: cb890c79c63885504ddc0efd7a7d01481760aca2
|
||||||
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
|
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
|
||||||
|
|
||||||
PODFILE CHECKSUM: c48a21ff513d3eadafa50f8797207ef2be75e234
|
PODFILE CHECKSUM: c48a21ff513d3eadafa50f8797207ef2be75e234
|
||||||
|
|
||||||
COCOAPODS: 1.8.4
|
COCOAPODS: 1.9.1
|
||||||
|
|||||||
@@ -8,26 +8,25 @@ const blacklist = require('metro-config/src/defaults/blacklist');
|
|||||||
const root = path.resolve(__dirname, '..');
|
const root = path.resolve(__dirname, '..');
|
||||||
const packages = path.resolve(root, 'packages');
|
const packages = path.resolve(root, 'packages');
|
||||||
|
|
||||||
|
const workspaces = fs
|
||||||
|
// List all packages under `packages/`
|
||||||
|
.readdirSync(packages)
|
||||||
|
// Ignore hidden files such as .DS_Store
|
||||||
|
.filter((p) => !p.startsWith('.'))
|
||||||
|
.map((p) => path.join(packages, p));
|
||||||
|
|
||||||
// Get the list of dependencies for all packages in the monorepo
|
// Get the list of dependencies for all packages in the monorepo
|
||||||
const modules = ['@expo/vector-icons']
|
const modules = ['@expo/vector-icons']
|
||||||
.concat(
|
.concat(
|
||||||
...fs
|
...workspaces.map((it) => {
|
||||||
// List all packages under `packages/`
|
const pak = JSON.parse(
|
||||||
.readdirSync(packages)
|
fs.readFileSync(path.join(it, 'package.json'), 'utf8')
|
||||||
// Ignore hidden files such as .DS_Store
|
);
|
||||||
.filter((p) => !p.startsWith('.'))
|
|
||||||
.map((p) => {
|
|
||||||
const pak = JSON.parse(
|
|
||||||
fs.readFileSync(path.join(packages, p, 'package.json'), 'utf8')
|
|
||||||
);
|
|
||||||
|
|
||||||
// We need to collect list of deps that this package imports
|
// We need to make sure that only one version is loaded for peerDependencies
|
||||||
// Collecting both dependencies are peerDependencies should do it
|
// So we blacklist them at the root, and alias them to the versions in example's node_modules
|
||||||
return Object.keys({
|
return pak.peerDependencies ? Object.keys(pak.peerDependencies) : [];
|
||||||
...pak.dependencies,
|
})
|
||||||
...pak.peerDependencies,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
.sort()
|
.sort()
|
||||||
.filter(
|
.filter(
|
||||||
@@ -45,15 +44,16 @@ module.exports = {
|
|||||||
watchFolders: [root],
|
watchFolders: [root],
|
||||||
|
|
||||||
resolver: {
|
resolver: {
|
||||||
// We need to blacklist `node_modules` of all our packages
|
// We need to blacklist the peerDependencies we've collected in packages' node_modules
|
||||||
// This will avoid Metro throwing duplicate module errors
|
|
||||||
blacklistRE: blacklist(
|
blacklistRE: blacklist(
|
||||||
fs
|
[].concat(
|
||||||
.readdirSync(packages)
|
...workspaces.map((it) =>
|
||||||
.map((p) => path.join(packages, p))
|
modules.map(
|
||||||
.map(
|
(m) =>
|
||||||
(it) => new RegExp(`^${escape(path.join(it, 'node_modules'))}\\/.*$`)
|
new RegExp(`^${escape(path.join(it, 'node_modules', m))}\\/.*$`)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
// When we import a package from the monorepo, metro won't be able to find their deps
|
// When we import a package from the monorepo, metro won't be able to find their deps
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/example",
|
"name": "@react-navigation/example",
|
||||||
"description": "Demo app to showcase various functionality of React Navigation",
|
"description": "Demo app to showcase various functionality of React Navigation",
|
||||||
"version": "5.0.0",
|
"version": "5.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
@@ -12,33 +12,33 @@
|
|||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^10.0.0",
|
"@expo/vector-icons": "^10.2.0",
|
||||||
"@react-native-community/masked-view": "^0.1.7",
|
"@react-native-community/masked-view": "^0.1.10",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"expo": "^37.0.0",
|
"expo": "^37.0.8",
|
||||||
"expo-asset": "~8.1.3",
|
"expo-asset": "~8.1.3",
|
||||||
"expo-blur": "~8.1.0",
|
"expo-blur": "~8.1.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-dom": "~16.9.0",
|
"react-dom": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-paper": "^3.7.0",
|
"react-native-paper": "^3.10.1",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-restart": "^0.0.14",
|
"react-native-restart": "^0.0.15",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^1.0.0",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"react-native-tab-view": "2.14.0",
|
"react-native-tab-view": "2.14.0",
|
||||||
"react-native-unimodules": "~0.8.1",
|
"react-native-unimodules": "~0.9.1",
|
||||||
"react-native-web": "^0.11.7"
|
"react-native-web": "^0.11.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@expo/webpack-config": "^0.11.19",
|
"@expo/webpack-config": "^0.11.19",
|
||||||
"@types/jest-dev-server": "^4.2.0",
|
"@types/jest-dev-server": "^4.2.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.60.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"babel-preset-expo": "^8.1.0",
|
"babel-preset-expo": "^8.1.0",
|
||||||
"expo-cli": "^3.17.18",
|
"expo-cli": "^3.20.1",
|
||||||
"jest": "^25.2.7",
|
"jest": "^26.0.1",
|
||||||
"jest-dev-server": "^4.4.0",
|
"jest-dev-server": "^4.4.0",
|
||||||
"playwright": "^0.14.0",
|
"playwright": "^0.14.0",
|
||||||
"serve": "^11.3.0",
|
"serve": "^11.3.0",
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform } from 'react-native';
|
import { View, ScrollView, StyleSheet, Platform } from 'react-native';
|
||||||
|
import { Button } from 'react-native-paper';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
import {
|
||||||
|
createBottomTabNavigator,
|
||||||
|
BottomTabNavigationProp,
|
||||||
|
} from '@react-navigation/bottom-tabs';
|
||||||
import TouchableBounce from '../Shared/TouchableBounce';
|
import TouchableBounce from '../Shared/TouchableBounce';
|
||||||
import Albums from '../Shared/Albums';
|
import Albums from '../Shared/Albums';
|
||||||
import Contacts from '../Shared/Contacts';
|
import Contacts from '../Shared/Contacts';
|
||||||
@@ -23,6 +27,36 @@ type BottomTabParams = {
|
|||||||
Chat: undefined;
|
Chat: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
|
const AlbumsScreen = ({
|
||||||
|
navigation,
|
||||||
|
}: {
|
||||||
|
navigation: BottomTabNavigationProp<BottomTabParams>;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<ScrollView>
|
||||||
|
<View style={styles.buttons}>
|
||||||
|
<Button
|
||||||
|
mode="outlined"
|
||||||
|
onPress={() => navigation.setOptions({ tabBarVisible: false })}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Hide tab bar
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
mode="outlined"
|
||||||
|
onPress={() => navigation.setOptions({ tabBarVisible: true })}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Show tab bar
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const BottomTabs = createBottomTabNavigator<BottomTabParams>();
|
const BottomTabs = createBottomTabNavigator<BottomTabParams>();
|
||||||
|
|
||||||
export default function BottomTabsScreen() {
|
export default function BottomTabsScreen() {
|
||||||
@@ -62,7 +96,7 @@ export default function BottomTabsScreen() {
|
|||||||
/>
|
/>
|
||||||
<BottomTabs.Screen
|
<BottomTabs.Screen
|
||||||
name="Albums"
|
name="Albums"
|
||||||
component={Albums}
|
component={AlbumsScreen}
|
||||||
options={{
|
options={{
|
||||||
title: 'Albums',
|
title: 'Albums',
|
||||||
tabBarIcon: getTabBarIcon('image-album'),
|
tabBarIcon: getTabBarIcon('image-album'),
|
||||||
@@ -71,3 +105,13 @@ export default function BottomTabsScreen() {
|
|||||||
</BottomTabs.Navigator>
|
</BottomTabs.Navigator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
buttons: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 8,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
margin: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import Albums from '../Shared/Albums';
|
|||||||
|
|
||||||
type SimpleStackParams = {
|
type SimpleStackParams = {
|
||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
Album: undefined;
|
Albums: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
@@ -53,24 +53,24 @@ const ArticleScreen = ({
|
|||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
<Link
|
<Link
|
||||||
to="/link-component/Album"
|
to="/link-component/music"
|
||||||
style={[styles.button, { padding: 8 }]}
|
style={[styles.button, { padding: 8 }]}
|
||||||
>
|
>
|
||||||
Go to /link-component/Album
|
Go to /link-component/music
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to="/link-component/Album"
|
to="/link-component/music"
|
||||||
action={StackActions.replace('Album')}
|
action={StackActions.replace('Albums')}
|
||||||
style={[styles.button, { padding: 8 }]}
|
style={[styles.button, { padding: 8 }]}
|
||||||
>
|
>
|
||||||
Replace with /link-component/Album
|
Replace with /link-component/music
|
||||||
</Link>
|
</Link>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
to="/link-component/Album"
|
to="/link-component/music"
|
||||||
mode="contained"
|
mode="contained"
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
>
|
>
|
||||||
Go to /link-component/Album
|
Go to /link-component/music
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
<Button
|
<Button
|
||||||
mode="outlined"
|
mode="outlined"
|
||||||
@@ -97,17 +97,17 @@ const AlbumsScreen = ({
|
|||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
<Link
|
<Link
|
||||||
to="/link-component/Article?author=Babel"
|
to="/link-component/article/babel"
|
||||||
style={[styles.button, { padding: 8 }]}
|
style={[styles.button, { padding: 8 }]}
|
||||||
>
|
>
|
||||||
Go to /link-component/Article
|
Go to /link-component/article
|
||||||
</Link>
|
</Link>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
to="/link-component/Article?author=Babel"
|
to="/link-component/article/babel"
|
||||||
mode="contained"
|
mode="contained"
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
>
|
>
|
||||||
Go to /link-component/Article
|
Go to /link-component/article
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
<Button
|
<Button
|
||||||
mode="outlined"
|
mode="outlined"
|
||||||
@@ -144,9 +144,9 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
|||||||
initialParams={{ author: 'Gandalf' }}
|
initialParams={{ author: 'Gandalf' }}
|
||||||
/>
|
/>
|
||||||
<SimpleStack.Screen
|
<SimpleStack.Screen
|
||||||
name="Album"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
options={{ title: 'Album' }}
|
options={{ title: 'Albums' }}
|
||||||
/>
|
/>
|
||||||
</SimpleStack.Navigator>
|
</SimpleStack.Navigator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Dimensions, ScaledSize } from 'react-native';
|
import { Dimensions, ScaledSize } from 'react-native';
|
||||||
import { Appbar } from 'react-native-paper';
|
import { Appbar } from 'react-native-paper';
|
||||||
import { ParamListBase } from '@react-navigation/native';
|
import {
|
||||||
|
useTheme,
|
||||||
|
useNavigation,
|
||||||
|
ParamListBase,
|
||||||
|
} from '@react-navigation/native';
|
||||||
import { StackNavigationProp } from '@react-navigation/stack';
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import {
|
import {
|
||||||
createDrawerNavigator,
|
createDrawerNavigator,
|
||||||
DrawerNavigationProp,
|
DrawerNavigationProp,
|
||||||
DrawerContent,
|
DrawerContent,
|
||||||
|
DrawerContentComponentProps,
|
||||||
|
DrawerContentOptions,
|
||||||
} from '@react-navigation/drawer';
|
} from '@react-navigation/drawer';
|
||||||
import Article from '../Shared/Article';
|
import Article from '../Shared/Article';
|
||||||
import Albums from '../Shared/Albums';
|
import Albums from '../Shared/Albums';
|
||||||
@@ -15,7 +21,7 @@ import NewsFeed from '../Shared/NewsFeed';
|
|||||||
type DrawerParams = {
|
type DrawerParams = {
|
||||||
Article: undefined;
|
Article: undefined;
|
||||||
NewsFeed: undefined;
|
NewsFeed: undefined;
|
||||||
Album: undefined;
|
Albums: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DrawerNavigation = DrawerNavigationProp<DrawerParams>;
|
type DrawerNavigation = DrawerNavigationProp<DrawerParams>;
|
||||||
@@ -43,10 +49,11 @@ const Header = ({
|
|||||||
onGoBack: () => void;
|
onGoBack: () => void;
|
||||||
title: string;
|
title: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { colors } = useTheme();
|
||||||
const isLargeScreen = useIsLargeScreen();
|
const isLargeScreen = useIsLargeScreen();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Appbar.Header>
|
<Appbar.Header style={{ backgroundColor: colors.card, elevation: 1 }}>
|
||||||
{isLargeScreen ? null : <Appbar.BackAction onPress={onGoBack} />}
|
{isLargeScreen ? null : <Appbar.BackAction onPress={onGoBack} />}
|
||||||
<Appbar.Content title={title} />
|
<Appbar.Content title={title} />
|
||||||
</Appbar.Header>
|
</Appbar.Header>
|
||||||
@@ -80,6 +87,23 @@ const AlbumsScreen = ({ navigation }: { navigation: DrawerNavigation }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CustomDrawerContent = (
|
||||||
|
props: DrawerContentComponentProps<DrawerContentOptions>
|
||||||
|
) => {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
const navigation = useNavigation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Appbar.Header style={{ backgroundColor: colors.card, elevation: 1 }}>
|
||||||
|
<Appbar.Action icon="close" onPress={() => navigation.goBack()} />
|
||||||
|
<Appbar.Content title="Pages" />
|
||||||
|
</Appbar.Header>
|
||||||
|
<DrawerContent {...props} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const Drawer = createDrawerNavigator<DrawerParams>();
|
const Drawer = createDrawerNavigator<DrawerParams>();
|
||||||
|
|
||||||
type Props = Partial<React.ComponentProps<typeof Drawer.Navigator>> & {
|
type Props = Partial<React.ComponentProps<typeof Drawer.Navigator>> & {
|
||||||
@@ -100,15 +124,7 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {
|
|||||||
drawerType={isLargeScreen ? 'permanent' : 'back'}
|
drawerType={isLargeScreen ? 'permanent' : 'back'}
|
||||||
drawerStyle={isLargeScreen ? null : { width: '100%' }}
|
drawerStyle={isLargeScreen ? null : { width: '100%' }}
|
||||||
overlayColor="transparent"
|
overlayColor="transparent"
|
||||||
drawerContent={(props) => (
|
drawerContent={(props) => <CustomDrawerContent {...props} />}
|
||||||
<>
|
|
||||||
<Appbar.Header>
|
|
||||||
<Appbar.Action icon="close" onPress={() => navigation.goBack()} />
|
|
||||||
<Appbar.Content title="Pages" />
|
|
||||||
</Appbar.Header>
|
|
||||||
<DrawerContent {...props} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<Drawer.Screen name="Article" component={ArticleScreen} />
|
<Drawer.Screen name="Article" component={ArticleScreen} />
|
||||||
@@ -118,9 +134,9 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {
|
|||||||
options={{ title: 'Feed' }}
|
options={{ title: 'Feed' }}
|
||||||
/>
|
/>
|
||||||
<Drawer.Screen
|
<Drawer.Screen
|
||||||
name="Album"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
options={{ title: 'Album' }}
|
options={{ title: 'Albums' }}
|
||||||
/>
|
/>
|
||||||
</Drawer.Navigator>
|
</Drawer.Navigator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { ParamListBase } from '@react-navigation/native';
|
||||||
|
import { StackNavigationProp } from '@react-navigation/stack';
|
||||||
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
|
||||||
import Albums from '../Shared/Albums';
|
import Albums from '../Shared/Albums';
|
||||||
import Contacts from '../Shared/Contacts';
|
import Contacts from '../Shared/Contacts';
|
||||||
@@ -12,7 +14,15 @@ type MaterialTopTabParams = {
|
|||||||
|
|
||||||
const MaterialTopTabs = createMaterialTopTabNavigator<MaterialTopTabParams>();
|
const MaterialTopTabs = createMaterialTopTabNavigator<MaterialTopTabParams>();
|
||||||
|
|
||||||
export default function MaterialTopTabsScreen() {
|
type Props = {
|
||||||
|
navigation: StackNavigationProp<ParamListBase>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function MaterialTopTabsScreen({ navigation }: Props) {
|
||||||
|
navigation.setOptions({
|
||||||
|
cardStyle: { flex: 1 },
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MaterialTopTabs.Navigator>
|
<MaterialTopTabs.Navigator>
|
||||||
<MaterialTopTabs.Screen
|
<MaterialTopTabs.Screen
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import Albums from '../Shared/Albums';
|
|||||||
|
|
||||||
type ModalStackParams = {
|
type ModalStackParams = {
|
||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
Album: undefined;
|
Albums: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ModalStackNavigation = StackNavigationProp<ModalStackParams>;
|
type ModalStackNavigation = StackNavigationProp<ModalStackParams>;
|
||||||
@@ -31,7 +31,7 @@ const ArticleScreen = ({
|
|||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
<Button
|
<Button
|
||||||
mode="contained"
|
mode="contained"
|
||||||
onPress={() => navigation.push('Album')}
|
onPress={() => navigation.push('Albums')}
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
>
|
>
|
||||||
Push album
|
Push album
|
||||||
@@ -112,9 +112,9 @@ export default function SimpleStackScreen({ navigation, options }: Props) {
|
|||||||
initialParams={{ author: 'Gandalf' }}
|
initialParams={{ author: 'Gandalf' }}
|
||||||
/>
|
/>
|
||||||
<ModalPresentationStack.Screen
|
<ModalPresentationStack.Screen
|
||||||
name="Album"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
options={{ title: 'Album' }}
|
options={{ title: 'Albums' }}
|
||||||
/>
|
/>
|
||||||
</ModalPresentationStack.Navigator>
|
</ModalPresentationStack.Navigator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import NewsFeed from '../Shared/NewsFeed';
|
|||||||
type SimpleStackParams = {
|
type SimpleStackParams = {
|
||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
NewsFeed: undefined;
|
NewsFeed: undefined;
|
||||||
Album: undefined;
|
Albums: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
@@ -63,7 +63,7 @@ const NewsFeedScreen = ({
|
|||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
<Button
|
<Button
|
||||||
mode="contained"
|
mode="contained"
|
||||||
onPress={() => navigation.navigate('Album')}
|
onPress={() => navigation.navigate('Albums')}
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
>
|
>
|
||||||
Navigate to album
|
Navigate to album
|
||||||
@@ -136,9 +136,9 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
|||||||
options={{ title: 'Feed' }}
|
options={{ title: 'Feed' }}
|
||||||
/>
|
/>
|
||||||
<SimpleStack.Screen
|
<SimpleStack.Screen
|
||||||
name="Album"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
options={{ title: 'Album' }}
|
options={{ title: 'Albums' }}
|
||||||
/>
|
/>
|
||||||
</SimpleStack.Navigator>
|
</SimpleStack.Navigator>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import Albums from '../Shared/Albums';
|
|||||||
|
|
||||||
type SimpleStackParams = {
|
type SimpleStackParams = {
|
||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
Album: undefined;
|
Albums: undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
@@ -34,7 +34,7 @@ const ArticleScreen = ({
|
|||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
<Button
|
<Button
|
||||||
mode="contained"
|
mode="contained"
|
||||||
onPress={() => navigation.push('Album')}
|
onPress={() => navigation.push('Albums')}
|
||||||
style={styles.button}
|
style={styles.button}
|
||||||
>
|
>
|
||||||
Push album
|
Push album
|
||||||
@@ -131,10 +131,10 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
|||||||
initialParams={{ author: 'Gandalf' }}
|
initialParams={{ author: 'Gandalf' }}
|
||||||
/>
|
/>
|
||||||
<SimpleStack.Screen
|
<SimpleStack.Screen
|
||||||
name="Album"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
options={{
|
options={{
|
||||||
title: 'Album',
|
title: 'Albums',
|
||||||
headerBackTitle: 'Back',
|
headerBackTitle: 'Back',
|
||||||
headerTransparent: true,
|
headerTransparent: true,
|
||||||
headerBackground: () => (
|
headerBackground: () => (
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
I18nManager,
|
I18nManager,
|
||||||
Dimensions,
|
Dimensions,
|
||||||
ScaledSize,
|
ScaledSize,
|
||||||
|
Linking,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { enableScreens } from 'react-native-screens';
|
import { enableScreens } from 'react-native-screens';
|
||||||
@@ -138,18 +139,18 @@ export default function App() {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const restoreState = async () => {
|
const restoreState = async () => {
|
||||||
try {
|
try {
|
||||||
let state;
|
const initialUrl = await Linking.getInitialURL();
|
||||||
|
|
||||||
if (Platform.OS !== 'web' && state === undefined) {
|
if (Platform.OS !== 'web' || initialUrl === null) {
|
||||||
const savedState = await AsyncStorage.getItem(
|
const savedState = await AsyncStorage.getItem(
|
||||||
NAVIGATION_PERSISTENCE_KEY
|
NAVIGATION_PERSISTENCE_KEY
|
||||||
);
|
);
|
||||||
|
|
||||||
state = savedState ? JSON.parse(savedState) : undefined;
|
const state = savedState ? JSON.parse(savedState) : undefined;
|
||||||
}
|
|
||||||
|
|
||||||
if (state !== undefined) {
|
if (state !== undefined) {
|
||||||
setInitialState(state);
|
setInitialState(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@@ -238,6 +239,22 @@ export default function App() {
|
|||||||
{ Home: '' }
|
{ Home: '' }
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
Article: {
|
||||||
|
path: 'article/:author?',
|
||||||
|
parse: {
|
||||||
|
author: (author) =>
|
||||||
|
author.charAt(0).toUpperCase() +
|
||||||
|
author.slice(1).replace(/-/g, ' '),
|
||||||
|
},
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.toLowerCase().replace(/\s/g, '-'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Albums: 'music',
|
||||||
|
Chat: 'chat',
|
||||||
|
Contacts: 'people',
|
||||||
|
NewsFeed: 'feed',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
fallback={<Text>Loading…</Text>}
|
fallback={<Text>Loading…</Text>}
|
||||||
|
|||||||
@@ -24,19 +24,21 @@ module.exports = async function (env, argv) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Object.assign(config.resolve.alias, {
|
Object.assign(config.resolve.alias, {
|
||||||
react: path.resolve(node_modules, 'react'),
|
'react': path.resolve(node_modules, 'react'),
|
||||||
'react-native': path.resolve(node_modules, 'react-native-web'),
|
'react-native': path.resolve(node_modules, 'react-native-web'),
|
||||||
'react-native-web': path.resolve(node_modules, 'react-native-web'),
|
'react-native-web': path.resolve(node_modules, 'react-native-web'),
|
||||||
'@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'),
|
'@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'),
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.readdirSync(packages).forEach((name) => {
|
fs.readdirSync(packages)
|
||||||
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
.filter((name) => !name.startsWith('.'))
|
||||||
packages,
|
.forEach((name) => {
|
||||||
name,
|
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
||||||
'src'
|
packages,
|
||||||
);
|
name,
|
||||||
});
|
require(`../packages/${name}/package.json`).source
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -13,7 +13,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/satya164/react-navigation.git"
|
"url": "git+https://github.com/react-navigation/react-navigation.git"
|
||||||
},
|
},
|
||||||
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)",
|
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -27,23 +27,23 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||||
"@babel/preset-env": "^7.9.0",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@babel/preset-flow": "^7.9.0",
|
"@babel/preset-flow": "^7.9.0",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@babel/preset-typescript": "^7.9.0",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.6",
|
||||||
"@commitlint/config-conventional": "^8.3.4",
|
"@commitlint/config-conventional": "^8.3.4",
|
||||||
"@types/jest": "^25.2.1",
|
"@types/jest": "^25.2.1",
|
||||||
"babel-jest": "^25.2.6",
|
"babel-jest": "^26.0.1",
|
||||||
"codecov": "^3.6.5",
|
"codecov": "^3.6.5",
|
||||||
"commitlint": "^8.3.5",
|
"commitlint": "^8.3.5",
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.5",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-satya164": "^3.1.6",
|
"eslint-config-satya164": "^3.1.7",
|
||||||
"husky": "^4.2.3",
|
"husky": "^4.2.5",
|
||||||
"jest": "^25.2.7",
|
"jest": "^26.0.1",
|
||||||
"lerna": "^3.20.2",
|
"lerna": "^3.20.2",
|
||||||
"prettier": "^2.0.4",
|
"prettier": "^2.0.5",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -3,6 +3,96 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.5.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.7...@react-navigation/bottom-tabs@5.5.0) (2020-05-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* animate changes to tabBarVisible in BottomTabBar ([#8286](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/8286)) ([c1e46f8](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/c1e46f8e331e0054995aa476455af204d02d4170))
|
||||||
|
* update react-native-safe-area-context to 1.0.0 ([#8182](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/8182)) ([d62fbfe](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/d62fbfe255140f16b182e8b54b276a7c96f2aec6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.7](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.6...@react-navigation/bottom-tabs@5.4.7) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.6](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.5...@react-navigation/bottom-tabs@5.4.6) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.5](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.4...@react-navigation/bottom-tabs@5.4.5) (2020-05-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.3...@react-navigation/bottom-tabs@5.4.4) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.2...@react-navigation/bottom-tabs@5.4.3) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.1...@react-navigation/bottom-tabs@5.4.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.0...@react-navigation/bottom-tabs@5.4.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.4...@react-navigation/bottom-tabs@5.4.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.3...@react-navigation/bottom-tabs@5.3.4) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.2...@react-navigation/bottom-tabs@5.3.3) (2020-05-01)
|
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.2...@react-navigation/bottom-tabs@5.3.3) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/bottom-tabs",
|
"name": "@react-navigation/bottom-tabs",
|
||||||
"description": "Bottom tab navigator following iOS design guidelines",
|
"description": "Bottom tab navigator following iOS design guidelines",
|
||||||
"version": "5.3.3",
|
"version": "5.5.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -15,11 +15,13 @@
|
|||||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs",
|
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -34,16 +36,16 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^1.0.0",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export { default as BottomTabBar } from './views/BottomTabBar';
|
|||||||
export type {
|
export type {
|
||||||
BottomTabNavigationOptions,
|
BottomTabNavigationOptions,
|
||||||
BottomTabNavigationProp,
|
BottomTabNavigationProp,
|
||||||
|
BottomTabScreenProps,
|
||||||
BottomTabBarProps,
|
BottomTabBarProps,
|
||||||
BottomTabBarOptions,
|
BottomTabBarOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
Descriptor,
|
Descriptor,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type BottomTabNavigationEventMap = {
|
export type BottomTabNavigationEventMap = {
|
||||||
@@ -45,6 +46,14 @@ export type BottomTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type BottomTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: BottomTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type BottomTabNavigationOptions = {
|
export type BottomTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -53,52 +53,60 @@ export default function BottomTabBar({
|
|||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const buildLink = useLinkBuilder();
|
const buildLink = useLinkBuilder();
|
||||||
|
|
||||||
const [dimensions, setDimensions] = React.useState(() => {
|
const focusedRoute = state.routes[state.index];
|
||||||
const { height = 0, width = 0 } = Dimensions.get('window');
|
const focusedDescriptor = descriptors[focusedRoute.key];
|
||||||
|
const focusedOptions = focusedDescriptor.options;
|
||||||
|
|
||||||
return { height, width };
|
const [isKeyboardShown, setIsKeyboardShown] = React.useState(false);
|
||||||
});
|
|
||||||
|
|
||||||
const [layout, setLayout] = React.useState({
|
const shouldShowTabBar =
|
||||||
height: 0,
|
focusedOptions.tabBarVisible !== false &&
|
||||||
width: dimensions.width,
|
!(keyboardHidesTabBar && isKeyboardShown);
|
||||||
});
|
|
||||||
const [keyboardShown, setKeyboardShown] = React.useState(false);
|
|
||||||
|
|
||||||
const [visible] = React.useState(() => new Animated.Value(1));
|
const [isTabBarHidden, setIsTabBarHidden] = React.useState(!shouldShowTabBar);
|
||||||
|
|
||||||
const { routes } = state;
|
const [visible] = React.useState(
|
||||||
|
() => new Animated.Value(shouldShowTabBar ? 1 : 0)
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (keyboardShown) {
|
if (shouldShowTabBar) {
|
||||||
Animated.timing(visible, {
|
|
||||||
toValue: 0,
|
|
||||||
duration: 200,
|
|
||||||
useNativeDriver,
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}, [keyboardShown, visible]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const handleOrientationChange = ({ window }: { window: ScaledSize }) => {
|
|
||||||
setDimensions(window);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleKeyboardShow = () => setKeyboardShown(true);
|
|
||||||
|
|
||||||
const handleKeyboardHide = () =>
|
|
||||||
Animated.timing(visible, {
|
Animated.timing(visible, {
|
||||||
toValue: 1,
|
toValue: 1,
|
||||||
duration: 250,
|
duration: 250,
|
||||||
useNativeDriver,
|
useNativeDriver,
|
||||||
}).start(({ finished }) => {
|
}).start(({ finished }) => {
|
||||||
if (finished) {
|
if (finished) {
|
||||||
setKeyboardShown(false);
|
setIsTabBarHidden(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
setIsTabBarHidden(true);
|
||||||
|
|
||||||
|
Animated.timing(visible, {
|
||||||
|
toValue: 0,
|
||||||
|
duration: 200,
|
||||||
|
useNativeDriver,
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}, [shouldShowTabBar, visible]);
|
||||||
|
|
||||||
|
const [dimensions, setDimensions] = React.useState(() => {
|
||||||
|
const { height = 0, width = 0 } = Dimensions.get('window');
|
||||||
|
|
||||||
|
return { height, width };
|
||||||
|
});
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const handleOrientationChange = ({ window }: { window: ScaledSize }) => {
|
||||||
|
setDimensions(window);
|
||||||
|
};
|
||||||
|
|
||||||
Dimensions.addEventListener('change', handleOrientationChange);
|
Dimensions.addEventListener('change', handleOrientationChange);
|
||||||
|
|
||||||
|
const handleKeyboardShow = () => setIsKeyboardShown(true);
|
||||||
|
const handleKeyboardHide = () => setIsKeyboardShown(false);
|
||||||
|
|
||||||
if (Platform.OS === 'ios') {
|
if (Platform.OS === 'ios') {
|
||||||
Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
|
Keyboard.addListener('keyboardWillShow', handleKeyboardShow);
|
||||||
Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
|
Keyboard.addListener('keyboardWillHide', handleKeyboardHide);
|
||||||
@@ -118,7 +126,12 @@ export default function BottomTabBar({
|
|||||||
Keyboard.removeListener('keyboardDidHide', handleKeyboardHide);
|
Keyboard.removeListener('keyboardDidHide', handleKeyboardHide);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [visible]);
|
}, []);
|
||||||
|
|
||||||
|
const [layout, setLayout] = React.useState({
|
||||||
|
height: 0,
|
||||||
|
width: dimensions.width,
|
||||||
|
});
|
||||||
|
|
||||||
const handleLayout = (e: LayoutChangeEvent) => {
|
const handleLayout = (e: LayoutChangeEvent) => {
|
||||||
const { height, width } = e.nativeEvent.layout;
|
const { height, width } = e.nativeEvent.layout;
|
||||||
@@ -135,6 +148,7 @@ export default function BottomTabBar({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { routes } = state;
|
||||||
const shouldUseHorizontalLabels = () => {
|
const shouldUseHorizontalLabels = () => {
|
||||||
if (labelPosition) {
|
if (labelPosition) {
|
||||||
return labelPosition === 'beside-icon';
|
return labelPosition === 'beside-icon';
|
||||||
@@ -183,22 +197,19 @@ export default function BottomTabBar({
|
|||||||
backgroundColor: colors.card,
|
backgroundColor: colors.card,
|
||||||
borderTopColor: colors.border,
|
borderTopColor: colors.border,
|
||||||
},
|
},
|
||||||
keyboardHidesTabBar
|
{
|
||||||
? {
|
transform: [
|
||||||
// When the keyboard is shown, slide down the tab bar
|
{
|
||||||
transform: [
|
translateY: visible.interpolate({
|
||||||
{
|
inputRange: [0, 1],
|
||||||
translateY: visible.interpolate({
|
outputRange: [layout.height + insets.bottom, 0],
|
||||||
inputRange: [0, 1],
|
}),
|
||||||
outputRange: [layout.height, 0],
|
},
|
||||||
}),
|
],
|
||||||
},
|
// Absolutely position the tab bar so that the content is below it
|
||||||
],
|
// This is needed to avoid gap at bottom when the tab bar is hidden
|
||||||
// Absolutely position the tab bar so that the content is below it
|
position: isTabBarHidden ? 'absolute' : null,
|
||||||
// This is needed to avoid gap at bottom when the tab bar is hidden
|
},
|
||||||
position: keyboardShown ? 'absolute' : null,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
{
|
{
|
||||||
height: DEFAULT_TABBAR_HEIGHT + insets.bottom,
|
height: DEFAULT_TABBAR_HEIGHT + insets.bottom,
|
||||||
paddingBottom: insets.bottom,
|
paddingBottom: insets.bottom,
|
||||||
@@ -206,7 +217,7 @@ export default function BottomTabBar({
|
|||||||
},
|
},
|
||||||
style,
|
style,
|
||||||
]}
|
]}
|
||||||
pointerEvents={keyboardHidesTabBar && keyboardShown ? 'none' : 'auto'}
|
pointerEvents={isTabBarHidden ? 'none' : 'auto'}
|
||||||
>
|
>
|
||||||
<View style={styles.content} onLayout={handleLayout}>
|
<View style={styles.content} onLayout={handleLayout}>
|
||||||
{routes.map((route, index) => {
|
{routes.map((route, index) => {
|
||||||
|
|||||||
@@ -75,17 +75,8 @@ export default class BottomTabView extends React.Component<Props, State> {
|
|||||||
tabBarOptions,
|
tabBarOptions,
|
||||||
state,
|
state,
|
||||||
navigation,
|
navigation,
|
||||||
|
descriptors,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { descriptors } = this.props;
|
|
||||||
const route = state.routes[state.index];
|
|
||||||
const descriptor = descriptors[route.key];
|
|
||||||
const options = descriptor.options;
|
|
||||||
|
|
||||||
if (options.tabBarVisible === false) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tabBar({
|
return tabBar({
|
||||||
...tabBarOptions,
|
...tabBarOptions,
|
||||||
state: state,
|
state: state,
|
||||||
|
|||||||
@@ -3,6 +3,89 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.1.24](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.23...@react-navigation/compat@5.1.24) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.23](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.22...@react-navigation/compat@5.1.23) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.22](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.21...@react-navigation/compat@5.1.22) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.21](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.20...@react-navigation/compat@5.1.21) (2020-05-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.20](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.19...@react-navigation/compat@5.1.20) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.19](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.18...@react-navigation/compat@5.1.19) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.18](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.17...@react-navigation/compat@5.1.18) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.17](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.16...@react-navigation/compat@5.1.17) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.16](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.15...@react-navigation/compat@5.1.16) (2020-05-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.14...@react-navigation/compat@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.13...@react-navigation/compat@5.1.14) (2020-05-01)
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.13...@react-navigation/compat@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/compat
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/compat",
|
"name": "@react-navigation/compat",
|
||||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||||
"version": "5.1.14",
|
"version": "5.1.24",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@@ -10,11 +10,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/compatibility.html",
|
"homepage": "https://reactnavigation.org/docs/compatibility.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -25,9 +27,9 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,112 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.8.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.8.1...@react-navigation/core@5.8.2) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.8.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.8.0...@react-navigation/core@5.8.1) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.8.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.7.0...@react-navigation/core@5.8.0) (2020-05-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add getCurrentOptions ([#8277](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8277)) ([d024ec6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/d024ec6d74dffe481ce6fde732c729e20c1668f4))
|
||||||
|
* add getCurrentRoute ([#8254](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8254)) ([7b25c8e](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/7b25c8eb2e6f96128fd86b92615346ce55bedeca))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.7.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.6.1...@react-navigation/core@5.7.0) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't use Object.fromEntries ([51f4d11](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/51f4d11fdf4bd2bb06f8cd4094f051816590e62c))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add a PathConfig type ([60cb3c9](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/60cb3c9ba76d7ef166c9fe8b55f23728975b5b6e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.6.0...@react-navigation/core@5.6.1) (2020-05-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't use flat since it's not supported in node ([21b397f](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/21b397f0d6b96ec4875d3172f47533130bb08009))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.6.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.5.2...@react-navigation/core@5.6.0) (2020-05-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* ignore extra slashes in the pattern ([3c47716](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3c47716826d0dfa69dfa6112141c116723372ea1))
|
||||||
|
* ignore state updates when we're not mounted ([0149e85](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/0149e85a95b90c6a9d487fa753ddbf5d01c03e3d)), closes [#8226](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8226)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* merge path patterns for nested screens ([#8253](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8253)) ([acc9646](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/acc9646426fee53558d686dfbe5fd0e35361d8c0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.5.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.5.1...@react-navigation/core@5.5.2) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.5.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.5.0...@react-navigation/core@5.5.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* avoid cleaning up state when a new navigator is mounted. fixes [#8195](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8195) ([f6d0676](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/f6d06768d3c36d1f5beaffcb660f3c259209f2e7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.5.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.4.0...@react-navigation/core@5.5.0) (2020-05-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for optional params to linking ([#8196](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8196)) ([fcd1cc6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/fcd1cc64c151e4941f3f544a54b5048d853821f6))
|
||||||
|
* support params anywhere in path segement ([#8184](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8184)) ([3999fc2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3999fc28365c3a06a17d963c7be7fb7e897f99e0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.5...@react-navigation/core@5.4.0) (2020-04-30)
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.5...@react-navigation/core@5.4.0) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "5.4.0",
|
"version": "5.8.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -15,11 +15,13 @@
|
|||||||
"homepage": "https://reactnavigation.org",
|
"homepage": "https://reactnavigation.org",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
@@ -29,21 +31,21 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.4.2",
|
"@react-navigation/routers": "^5.4.7",
|
||||||
"escape-string-regexp": "^2.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"nanoid": "^3.0.2",
|
"nanoid": "^3.1.5",
|
||||||
"query-string": "^6.12.0",
|
"query-string": "^6.12.1",
|
||||||
"react-is": "^16.13.0",
|
"react-is": "^16.13.0",
|
||||||
"use-subscription": "^1.4.0"
|
"use-subscription": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-is": "^16.7.1",
|
"@types/react-is": "^16.7.1",
|
||||||
"@types/use-subscription": "^1.0.0",
|
"@types/use-subscription": "^1.0.0",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native-testing-library": "^1.12.0",
|
"react-native-testing-library": "^1.13.2",
|
||||||
"react-test-renderer": "~16.13.1",
|
"react-test-renderer": "~16.13.1",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,49 +13,22 @@ import { ScheduleUpdateContext } from './useScheduleUpdate';
|
|||||||
import useFocusedListeners from './useFocusedListeners';
|
import useFocusedListeners from './useFocusedListeners';
|
||||||
import useDevTools from './useDevTools';
|
import useDevTools from './useDevTools';
|
||||||
import useStateGetters from './useStateGetters';
|
import useStateGetters from './useStateGetters';
|
||||||
|
import useOptionsGetters from './useOptionsGetters';
|
||||||
import useEventEmitter from './useEventEmitter';
|
import useEventEmitter from './useEventEmitter';
|
||||||
import useSyncState from './useSyncState';
|
import useSyncState from './useSyncState';
|
||||||
import isSerializable from './isSerializable';
|
import isSerializable from './isSerializable';
|
||||||
|
|
||||||
import { NavigationContainerRef, NavigationContainerProps } from './types';
|
import { NavigationContainerRef, NavigationContainerProps } from './types';
|
||||||
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
|
|
||||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||||
|
|
||||||
const DEVTOOLS_CONFIG_KEY =
|
const DEVTOOLS_CONFIG_KEY =
|
||||||
'REACT_NAVIGATION_REDUX_DEVTOOLS_EXTENSION_INTEGRATION_ENABLED';
|
'REACT_NAVIGATION_REDUX_DEVTOOLS_EXTENSION_INTEGRATION_ENABLED';
|
||||||
|
|
||||||
const MISSING_CONTEXT_ERROR =
|
|
||||||
"Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.";
|
|
||||||
|
|
||||||
const NOT_INITIALIZED_ERROR =
|
const NOT_INITIALIZED_ERROR =
|
||||||
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
|
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
|
||||||
|
|
||||||
export const NavigationStateContext = React.createContext<{
|
|
||||||
isDefault?: true;
|
|
||||||
state?: NavigationState | PartialState<NavigationState>;
|
|
||||||
getKey: () => string | undefined;
|
|
||||||
setKey: (key: string) => void;
|
|
||||||
getState: () => NavigationState | PartialState<NavigationState> | undefined;
|
|
||||||
setState: (
|
|
||||||
state: NavigationState | PartialState<NavigationState> | undefined
|
|
||||||
) => void;
|
|
||||||
}>({
|
|
||||||
isDefault: true,
|
|
||||||
|
|
||||||
get getKey(): any {
|
|
||||||
throw new Error(MISSING_CONTEXT_ERROR);
|
|
||||||
},
|
|
||||||
get setKey(): any {
|
|
||||||
throw new Error(MISSING_CONTEXT_ERROR);
|
|
||||||
},
|
|
||||||
get getState(): any {
|
|
||||||
throw new Error(MISSING_CONTEXT_ERROR);
|
|
||||||
},
|
|
||||||
get setState(): any {
|
|
||||||
throw new Error(MISSING_CONTEXT_ERROR);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
let hasWarnedForSerialization = false;
|
let hasWarnedForSerialization = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -199,8 +172,21 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
return getStateForRoute('root');
|
return getStateForRoute('root');
|
||||||
}, [getStateForRoute]);
|
}, [getStateForRoute]);
|
||||||
|
|
||||||
|
const getCurrentRoute = React.useCallback(() => {
|
||||||
|
let state = getRootState();
|
||||||
|
if (state === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
while (state.routes[state.index].state !== undefined) {
|
||||||
|
state = state.routes[state.index].state as NavigationState;
|
||||||
|
}
|
||||||
|
return state.routes[state.index];
|
||||||
|
}, [getRootState]);
|
||||||
|
|
||||||
const emitter = useEventEmitter();
|
const emitter = useEventEmitter();
|
||||||
|
|
||||||
|
const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(ref, () => ({
|
||||||
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
|
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
|
||||||
any
|
any
|
||||||
@@ -221,6 +207,8 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
getRootState,
|
getRootState,
|
||||||
dangerouslyGetState: () => state,
|
dangerouslyGetState: () => state,
|
||||||
dangerouslyGetParent: () => undefined,
|
dangerouslyGetParent: () => undefined,
|
||||||
|
getCurrentRoute,
|
||||||
|
getCurrentOptions,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const builderContext = React.useMemo(
|
const builderContext = React.useMemo(
|
||||||
@@ -244,8 +232,9 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
setState,
|
setState,
|
||||||
getKey,
|
getKey,
|
||||||
setKey,
|
setKey,
|
||||||
|
addOptionsGetter,
|
||||||
}),
|
}),
|
||||||
[getKey, getState, setKey, setState, state]
|
[getKey, getState, setKey, setState, state, addOptionsGetter]
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
|||||||
35
packages/core/src/NavigationStateContext.tsx
Normal file
35
packages/core/src/NavigationStateContext.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { NavigationState, PartialState } from '@react-navigation/routers';
|
||||||
|
|
||||||
|
const MISSING_CONTEXT_ERROR =
|
||||||
|
"Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.";
|
||||||
|
|
||||||
|
export default React.createContext<{
|
||||||
|
isDefault?: true;
|
||||||
|
state?: NavigationState | PartialState<NavigationState>;
|
||||||
|
getKey: () => string | undefined;
|
||||||
|
setKey: (key: string) => void;
|
||||||
|
getState: () => NavigationState | PartialState<NavigationState> | undefined;
|
||||||
|
setState: (
|
||||||
|
state: NavigationState | PartialState<NavigationState> | undefined
|
||||||
|
) => void;
|
||||||
|
addOptionsGetter?: (
|
||||||
|
key: string,
|
||||||
|
getter: () => object | undefined | null
|
||||||
|
) => void;
|
||||||
|
}>({
|
||||||
|
isDefault: true,
|
||||||
|
|
||||||
|
get getKey(): any {
|
||||||
|
throw new Error(MISSING_CONTEXT_ERROR);
|
||||||
|
},
|
||||||
|
get setKey(): any {
|
||||||
|
throw new Error(MISSING_CONTEXT_ERROR);
|
||||||
|
},
|
||||||
|
get getState(): any {
|
||||||
|
throw new Error(MISSING_CONTEXT_ERROR);
|
||||||
|
},
|
||||||
|
get setState(): any {
|
||||||
|
throw new Error(MISSING_CONTEXT_ERROR);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -5,12 +5,13 @@ import {
|
|||||||
NavigationState,
|
NavigationState,
|
||||||
PartialState,
|
PartialState,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
import NavigationContext from './NavigationContext';
|
import NavigationContext from './NavigationContext';
|
||||||
import NavigationRouteContext from './NavigationRouteContext';
|
import NavigationRouteContext from './NavigationRouteContext';
|
||||||
import StaticContainer from './StaticContainer';
|
import StaticContainer from './StaticContainer';
|
||||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||||
import { NavigationProp, RouteConfig, EventMapBase } from './types';
|
import { NavigationProp, RouteConfig, EventMapBase } from './types';
|
||||||
|
import useOptionsGetters from './useOptionsGetters';
|
||||||
|
|
||||||
type Props<
|
type Props<
|
||||||
State extends NavigationState,
|
State extends NavigationState,
|
||||||
@@ -24,6 +25,7 @@ type Props<
|
|||||||
};
|
};
|
||||||
getState: () => State;
|
getState: () => State;
|
||||||
setState: (state: State) => void;
|
setState: (state: State) => void;
|
||||||
|
options: object;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,11 +42,24 @@ export default function SceneView<
|
|||||||
navigation,
|
navigation,
|
||||||
getState,
|
getState,
|
||||||
setState,
|
setState,
|
||||||
|
options,
|
||||||
}: Props<State, ScreenOptions, EventMap>) {
|
}: Props<State, ScreenOptions, EventMap>) {
|
||||||
const navigatorKeyRef = React.useRef<string | undefined>();
|
const navigatorKeyRef = React.useRef<string | undefined>();
|
||||||
|
|
||||||
const getKey = React.useCallback(() => navigatorKeyRef.current, []);
|
const getKey = React.useCallback(() => navigatorKeyRef.current, []);
|
||||||
|
|
||||||
|
const optionsRef = React.useRef<object | undefined>(options);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
optionsRef.current = options;
|
||||||
|
}, [options]);
|
||||||
|
|
||||||
|
const getOptions = React.useCallback(() => optionsRef.current, []);
|
||||||
|
|
||||||
|
const { addOptionsGetter } = useOptionsGetters({
|
||||||
|
key: route.key,
|
||||||
|
getOptions,
|
||||||
|
});
|
||||||
|
|
||||||
const setKey = React.useCallback((key: string) => {
|
const setKey = React.useCallback((key: string) => {
|
||||||
navigatorKeyRef.current = key;
|
navigatorKeyRef.current = key;
|
||||||
}, []);
|
}, []);
|
||||||
@@ -77,8 +92,16 @@ export default function SceneView<
|
|||||||
setState: setCurrentState,
|
setState: setCurrentState,
|
||||||
getKey,
|
getKey,
|
||||||
setKey,
|
setKey,
|
||||||
|
addOptionsGetter,
|
||||||
}),
|
}),
|
||||||
[getCurrentState, getKey, route.state, setCurrentState, setKey]
|
[
|
||||||
|
getCurrentState,
|
||||||
|
getKey,
|
||||||
|
route.state,
|
||||||
|
setCurrentState,
|
||||||
|
setKey,
|
||||||
|
addOptionsGetter,
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ import {
|
|||||||
NavigationState,
|
NavigationState,
|
||||||
Router,
|
Router,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import BaseNavigationContainer, {
|
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||||
NavigationStateContext,
|
import NavigationStateContext from '../NavigationStateContext';
|
||||||
} from '../BaseNavigationContainer';
|
|
||||||
import MockRouter, { MockActions } from './__fixtures__/MockRouter';
|
import MockRouter, { MockActions } from './__fixtures__/MockRouter';
|
||||||
import useNavigationBuilder from '../useNavigationBuilder';
|
import useNavigationBuilder from '../useNavigationBuilder';
|
||||||
import Screen from '../Screen';
|
import Screen from '../Screen';
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ it("doesn't add query param for empty params", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles state with config with nested screens', () => {
|
it('handles state with config with nested screens', () => {
|
||||||
const path = '/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true';
|
const path =
|
||||||
|
'/foo/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
@@ -182,8 +183,77 @@ it('handles state with config with nested screens', () => {
|
|||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles state with config with nested screens and exact', () => {
|
||||||
|
const path = '/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bar: 'bar/:type/:fruit',
|
||||||
|
Baz: {
|
||||||
|
path: 'baz/:author',
|
||||||
|
parse: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
count: Number,
|
||||||
|
valid: Boolean,
|
||||||
|
},
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) => author.toLowerCase(),
|
||||||
|
id: (id: number) => `x${id}`,
|
||||||
|
unknown: (_: unknown) => 'x',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { fruit: 'apple', type: 'sweet' },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
params: {
|
||||||
|
author: 'Jane',
|
||||||
|
count: '10',
|
||||||
|
answer: '42',
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
it('handles state with config with nested screens and unused configs', () => {
|
it('handles state with config with nested screens and unused configs', () => {
|
||||||
const path = '/foe/baz/jane?answer=42&count=10&valid=true';
|
const path = '/foo/foe/baz/jane?answer=42&count=10&valid=true';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
@@ -239,6 +309,66 @@ it('handles state with config with nested screens and unused configs', () => {
|
|||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles state with config with nested screens and unused configs with exact', () => {
|
||||||
|
const path = '/foe/baz/jane?answer=42&count=10&valid=true';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Baz: {
|
||||||
|
path: 'baz/:author',
|
||||||
|
parse: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
count: Number,
|
||||||
|
valid: Boolean,
|
||||||
|
},
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
|
unknown: (_: unknown) => 'x',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
params: {
|
||||||
|
author: 'Jane',
|
||||||
|
count: 10,
|
||||||
|
answer: '42',
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
it('handles nested object with stringify in it', () => {
|
it('handles nested object with stringify in it', () => {
|
||||||
const path = '/bar/sweet/apple/foo/bis/jane?answer=42&count=10&valid=true';
|
const path = '/bar/sweet/apple/foo/bis/jane?answer=42&count=10&valid=true';
|
||||||
const config = {
|
const config = {
|
||||||
@@ -252,7 +382,6 @@ it('handles nested object with stringify in it', () => {
|
|||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz',
|
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: 'bos',
|
||||||
Bis: {
|
Bis: {
|
||||||
@@ -312,8 +441,82 @@ it('handles nested object with stringify in it', () => {
|
|||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles nested object with stringify in it with exact', () => {
|
||||||
|
const path = '/bar/sweet/apple/foo/bis/jane?answer=42&count=10&valid=true';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bar: 'bar/:type/:fruit',
|
||||||
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
screens: {
|
||||||
|
Bos: 'bos',
|
||||||
|
Bis: {
|
||||||
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
|
},
|
||||||
|
parse: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
count: Number,
|
||||||
|
valid: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { fruit: 'apple', type: 'sweet' },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bis',
|
||||||
|
params: {
|
||||||
|
author: 'Jane',
|
||||||
|
count: 10,
|
||||||
|
answer: '42',
|
||||||
|
valid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
it('handles nested object for second route depth', () => {
|
it('handles nested object for second route depth', () => {
|
||||||
const path = '/baz';
|
const path = '/foo/bar/baz';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
@@ -351,7 +554,95 @@ it('handles nested object for second route depth', () => {
|
|||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles nested object for second route depth and and path and stringify in roots', () => {
|
it('handles nested object for second route depth with exact', () => {
|
||||||
|
const path = '/baz';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: 'foe',
|
||||||
|
Bar: {
|
||||||
|
path: 'bar',
|
||||||
|
screens: {
|
||||||
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
state: {
|
||||||
|
routes: [{ name: 'Baz' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles nested object for second route depth and path and stringify in roots', () => {
|
||||||
|
const path = '/foo/dathomir/bar/42/baz';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo/:planet',
|
||||||
|
stringify: {
|
||||||
|
id: (id: number) => `planet=${id}`,
|
||||||
|
},
|
||||||
|
screens: {
|
||||||
|
Foe: 'foe',
|
||||||
|
Bar: {
|
||||||
|
path: 'bar/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
screens: {
|
||||||
|
Baz: 'baz',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
params: { planet: 'dathomir' },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
state: {
|
||||||
|
routes: [{ name: 'Baz', params: { id: 42 } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles nested object for second route depth and path and stringify in roots with exact', () => {
|
||||||
const path = '/baz';
|
const path = '/baz';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
@@ -370,7 +661,10 @@ it('handles nested object for second route depth and and path and stringify in r
|
|||||||
id: Number,
|
id: Number,
|
||||||
},
|
},
|
||||||
screens: {
|
screens: {
|
||||||
Baz: 'baz',
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -470,7 +764,7 @@ it('keeps query params if path is empty', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('cuts nested configs too', () => {
|
it('cuts nested configs too', () => {
|
||||||
const path = '/baz';
|
const path = '/foo/baz';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
@@ -478,7 +772,48 @@ it('cuts nested configs too', () => {
|
|||||||
Bar: '',
|
Bar: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Baz: { path: 'baz' },
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
state: {
|
||||||
|
routes: [{ name: 'Baz' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cuts nested configs too with exact', () => {
|
||||||
|
const path = '/baz';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Bar: {
|
||||||
|
path: '',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
@@ -504,7 +839,7 @@ it('cuts nested configs too', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('handles empty path at the end', () => {
|
it('handles empty path at the end', () => {
|
||||||
const path = '/bar';
|
const path = '/foo/bar';
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
@@ -641,7 +976,6 @@ it('strips undefined query params', () => {
|
|||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz',
|
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: 'bos',
|
||||||
Bis: {
|
Bis: {
|
||||||
@@ -681,7 +1015,79 @@ it('strips undefined query params', () => {
|
|||||||
params: {
|
params: {
|
||||||
author: 'Jane',
|
author: 'Jane',
|
||||||
count: 10,
|
count: 10,
|
||||||
answer: undefined,
|
valid: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('strips undefined query params with exact', () => {
|
||||||
|
const path = '/bar/sweet/apple/foo/bis/jane?count=10&valid=true';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bar: 'bar/:type/:fruit',
|
||||||
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
screens: {
|
||||||
|
Bos: 'bos',
|
||||||
|
Bis: {
|
||||||
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
|
},
|
||||||
|
parse: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
count: Number,
|
||||||
|
valid: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { fruit: 'apple', type: 'sweet' },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bis',
|
||||||
|
params: {
|
||||||
|
author: 'Jane',
|
||||||
|
count: 10,
|
||||||
valid: true,
|
valid: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -714,7 +1120,6 @@ it('handles stripping all query params', () => {
|
|||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz',
|
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: 'bos',
|
||||||
Bis: {
|
Bis: {
|
||||||
@@ -753,9 +1158,6 @@ it('handles stripping all query params', () => {
|
|||||||
name: 'Bis',
|
name: 'Bis',
|
||||||
params: {
|
params: {
|
||||||
author: 'Jane',
|
author: 'Jane',
|
||||||
count: undefined,
|
|
||||||
answer: undefined,
|
|
||||||
valid: undefined,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -773,3 +1175,93 @@ it('handles stripping all query params', () => {
|
|||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles stripping all query params with exact', () => {
|
||||||
|
const path = '/bar/sweet/apple/foo/bis/jane';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo',
|
||||||
|
screens: {
|
||||||
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bar: 'bar/:type/:fruit',
|
||||||
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
screens: {
|
||||||
|
Bos: 'bos',
|
||||||
|
Bis: {
|
||||||
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
|
stringify: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
|
},
|
||||||
|
parse: {
|
||||||
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
|
count: Number,
|
||||||
|
valid: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { fruit: 'apple', type: 'sweet' },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bis',
|
||||||
|
params: {
|
||||||
|
author: 'Jane',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('replaces undefined query params', () => {
|
||||||
|
const path = '/bar/undefined/apple';
|
||||||
|
const config = {
|
||||||
|
Bar: 'bar/:type/:fruit',
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { fruit: 'apple' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
|
});
|
||||||
|
|||||||
@@ -147,7 +147,10 @@ it('converts path string to initial state with config with nested screens', () =
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
@@ -213,7 +216,10 @@ it('converts path string to initial state with config with nested screens and un
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Baz: {
|
Baz: {
|
||||||
@@ -268,16 +274,23 @@ it('handles nested object with unused configs and with parse in it', () => {
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz',
|
path: 'baz',
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: {
|
||||||
|
path: 'bos',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
Bis: {
|
Bis: {
|
||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
@@ -348,11 +361,18 @@ it('handles parse in nested object for second route depth', () => {
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
Bar: {
|
Bar: {
|
||||||
path: 'bar',
|
path: 'bar',
|
||||||
|
exact: true,
|
||||||
screens: {
|
screens: {
|
||||||
Baz: 'baz',
|
Baz: {
|
||||||
|
path: 'baz',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -519,16 +539,23 @@ it('handles two initialRouteNames', () => {
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
initialRouteName: 'Bos',
|
initialRouteName: 'Bos',
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: {
|
||||||
|
path: 'bos',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
Bis: {
|
Bis: {
|
||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
@@ -601,16 +628,23 @@ it('accepts initialRouteName without config for it', () => {
|
|||||||
Foo: {
|
Foo: {
|
||||||
path: 'foo',
|
path: 'foo',
|
||||||
screens: {
|
screens: {
|
||||||
Foe: 'foe',
|
Foe: {
|
||||||
|
path: 'foe',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Bar: 'bar/:type/:fruit',
|
Bar: 'bar/:type/:fruit',
|
||||||
Baz: {
|
Baz: {
|
||||||
initialRouteName: 'Bas',
|
initialRouteName: 'Bas',
|
||||||
screens: {
|
screens: {
|
||||||
Bos: 'bos',
|
Bos: {
|
||||||
|
path: 'bos',
|
||||||
|
exact: true,
|
||||||
|
},
|
||||||
Bis: {
|
Bis: {
|
||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
|
exact: true,
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
@@ -984,3 +1018,868 @@ it('handles not taking path with too many segments', () => {
|
|||||||
state
|
state
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles differently ordered params v1', () => {
|
||||||
|
const path = '/foos/5/res/20';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foos/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/res/:pwd',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 20 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles differently ordered params v2', () => {
|
||||||
|
const path = '/5/20/foos/res';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foos/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: ':id/:pwd/foos/res',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 20 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles differently ordered params v3', () => {
|
||||||
|
const path = '/foos/5/20/res';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foos/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:pwd/res',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 20 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles differently ordered params v4', () => {
|
||||||
|
const path = '5/foos/res/20';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foos/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: ':id/foos/res/:pwd',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 20 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles simple optional params', () => {
|
||||||
|
const path = '/foos/5';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle 2 optional params at the end v1', () => {
|
||||||
|
const path = '/foos/5';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd?',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle 2 optional params at the end v2', () => {
|
||||||
|
const path = '/foos/5/10';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd?',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, nip: 10 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle 2 optional params at the end v3', () => {
|
||||||
|
const path = '/foos/5/10/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd?',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, nip: 10, pwd: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the middle v1', () => {
|
||||||
|
const path = '/foos/5/10';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 10 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the middle v2', () => {
|
||||||
|
const path = '/foos/5/10/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, nip: 10, pwd: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the middle v3', () => {
|
||||||
|
const path = '/foos/5/10/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:id/:nip?/:pwd/:smh',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
smh: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { id: 5, pwd: 10, smh: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the middle v4', () => {
|
||||||
|
const path = '/foos/5/10';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:nip?/:pwd/:smh?/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
smh: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { pwd: 5, id: 10 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the middle v5', () => {
|
||||||
|
const path = '/foos/5/10/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: 'foos/:nip?/:pwd/:smh?/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
smh: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { nip: 5, pwd: 10, id: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the beginning v1', () => {
|
||||||
|
const path = '5/10/foos/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: ':nip?/:pwd/foos/:smh?/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
smh: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { nip: 5, pwd: 10, id: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handle optional params in the beginning v2', () => {
|
||||||
|
const path = '5/10/foos/15';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foe: {
|
||||||
|
path: '/',
|
||||||
|
initialRouteName: 'Foo',
|
||||||
|
screens: {
|
||||||
|
Foo: 'foo',
|
||||||
|
Bis: {
|
||||||
|
path: 'foo/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Bas: {
|
||||||
|
path: ':nip?/:smh?/:pwd/foos/:id',
|
||||||
|
parse: {
|
||||||
|
id: Number,
|
||||||
|
nip: Number,
|
||||||
|
pwd: Number,
|
||||||
|
smh: Number,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foe',
|
||||||
|
state: {
|
||||||
|
index: 1,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Bas',
|
||||||
|
params: { nip: 5, pwd: 10, id: 15 },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('merges parent patterns if needed', () => {
|
||||||
|
const path = 'foo/42/baz/babel';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
path: 'foo/:bar',
|
||||||
|
parse: {
|
||||||
|
bar: Number,
|
||||||
|
},
|
||||||
|
screens: {
|
||||||
|
Baz: 'baz/:qux',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
params: { bar: 42 },
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Baz',
|
||||||
|
params: { qux: 'babel' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores extra slashes in the pattern', () => {
|
||||||
|
const path = '/bar/42';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
screens: {
|
||||||
|
Bar: {
|
||||||
|
path: '/bar//:id/',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
params: { id: '42' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getStateFromPath(path, config)).toEqual(state);
|
||||||
|
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
||||||
|
state
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|||||||
@@ -379,6 +379,8 @@ it("doesn't update state if action wasn't handled", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('cleans up state when the navigator unmounts', () => {
|
it('cleans up state when the navigator unmounts', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
const TestNavigator = (props: any) => {
|
const TestNavigator = (props: any) => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
@@ -426,6 +428,8 @@ it('cleans up state when the navigator unmounts', () => {
|
|||||||
<BaseNavigationContainer onStateChange={onStateChange} children={null} />
|
<BaseNavigationContainer onStateChange={onStateChange} children={null} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
act(() => jest.runAllTimers());
|
||||||
|
|
||||||
expect(onStateChange).toBeCalledTimes(2);
|
expect(onStateChange).toBeCalledTimes(2);
|
||||||
expect(onStateChange).lastCalledWith(undefined);
|
expect(onStateChange).lastCalledWith(undefined);
|
||||||
});
|
});
|
||||||
@@ -1486,3 +1490,128 @@ it("doesn't throw if children is null", () => {
|
|||||||
|
|
||||||
expect(() => render(element).update(element)).not.toThrowError();
|
expect(() => render(element).update(element)).not.toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns currently focused route with getCurrentRoute', () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = React.createRef<NavigationContainerRef>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator initialRouteName="bar-a">
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: 'data' }}
|
||||||
|
/>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.current?.getCurrentRoute()).toEqual({
|
||||||
|
key: 'bar-a',
|
||||||
|
name: 'bar-a',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns currently focused route's options with getCurrentOptions", () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = React.createRef<NavigationContainerRef>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator
|
||||||
|
initialRouteName="bar-a"
|
||||||
|
screenOptions={() => ({ sample2: 'data' })}
|
||||||
|
>
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: 'data' }}
|
||||||
|
/>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.current?.getCurrentOptions()).toEqual({
|
||||||
|
sample: 'data',
|
||||||
|
sample2: 'data',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if while getting current options with no options defined', () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = React.createRef<NavigationContainerRef>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator initialRouteName="bar-a">
|
||||||
|
<Screen
|
||||||
|
name="bar-b"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ wrongKey: true }}
|
||||||
|
/>
|
||||||
|
<Screen name="bar-a" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.current?.getCurrentOptions()).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not throw if while getting current options with empty container', () => {
|
||||||
|
const navigation = React.createRef<NavigationContainerRef>();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const container = <BaseNavigationContainer ref={navigation} />;
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.current?.getCurrentOptions()).toEqual(undefined);
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import {
|
|||||||
PartialState,
|
PartialState,
|
||||||
Route,
|
Route,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
|
import { PathConfig } from './types';
|
||||||
|
|
||||||
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
|
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
|
||||||
|
|
||||||
type StringifyConfig = Record<string, (value: any) => string>;
|
type StringifyConfig = Record<string, (value: any) => string>;
|
||||||
|
|
||||||
type Options = {
|
type OptionsItem = PathConfig[string];
|
||||||
[routeName: string]:
|
|
||||||
| string
|
type ConfigItem = {
|
||||||
| {
|
pattern?: string;
|
||||||
path?: string;
|
stringify?: StringifyConfig;
|
||||||
stringify?: StringifyConfig;
|
screens?: Record<string, ConfigItem>;
|
||||||
screens?: Options;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,101 +47,104 @@ type Options = {
|
|||||||
*/
|
*/
|
||||||
export default function getPathFromState(
|
export default function getPathFromState(
|
||||||
state?: State,
|
state?: State,
|
||||||
options: Options = {}
|
options: PathConfig = {}
|
||||||
): string {
|
): string {
|
||||||
if (state === undefined) {
|
if (state === undefined) {
|
||||||
throw Error('NavigationState not passed');
|
throw Error('NavigationState not passed');
|
||||||
}
|
}
|
||||||
let path = '/';
|
|
||||||
|
|
||||||
|
// Create a normalized configs array which will be easier to use
|
||||||
|
const configs = createNormalizedConfigs(options);
|
||||||
|
|
||||||
|
let path = '/';
|
||||||
let current: State | undefined = state;
|
let current: State | undefined = state;
|
||||||
|
|
||||||
|
const allParams: Record<string, any> = {};
|
||||||
|
|
||||||
while (current) {
|
while (current) {
|
||||||
let index = typeof current.index === 'number' ? current.index : 0;
|
let index = typeof current.index === 'number' ? current.index : 0;
|
||||||
let route = current.routes[index] as Route<string> & {
|
let route = current.routes[index] as Route<string> & {
|
||||||
state?: State;
|
state?: State;
|
||||||
};
|
};
|
||||||
let currentOptions = options;
|
|
||||||
let pattern = route.name;
|
|
||||||
// we keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
|
|
||||||
let nestedRouteNames = '';
|
|
||||||
|
|
||||||
while (route.name in currentOptions) {
|
let pattern: string | undefined;
|
||||||
if (typeof currentOptions[route.name] === 'string') {
|
|
||||||
pattern = currentOptions[route.name] as string;
|
let currentParams: Record<string, any> = { ...route.params };
|
||||||
break;
|
let currentOptions = configs;
|
||||||
} else if (typeof currentOptions[route.name] === 'object') {
|
|
||||||
// if there is no `screens` property, we return pattern
|
// Keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
|
||||||
if (
|
let nestedRouteNames = [];
|
||||||
!(currentOptions[route.name] as {
|
|
||||||
screens: Options;
|
let hasNext = true;
|
||||||
}).screens
|
|
||||||
) {
|
while (route.name in currentOptions && hasNext) {
|
||||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
pattern = currentOptions[route.name].pattern;
|
||||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
|
||||||
break;
|
nestedRouteNames.push(route.name);
|
||||||
|
|
||||||
|
if (route.params) {
|
||||||
|
const stringify = currentOptions[route.name]?.stringify;
|
||||||
|
|
||||||
|
currentParams = fromEntries(
|
||||||
|
Object.entries(route.params).map(([key, value]) => [
|
||||||
|
key,
|
||||||
|
stringify?.[key] ? stringify[key](value) : String(value),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pattern) {
|
||||||
|
Object.assign(allParams, currentParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no `screens` property or no nested state, we return pattern
|
||||||
|
if (!currentOptions[route.name].screens || route.state === undefined) {
|
||||||
|
hasNext = false;
|
||||||
|
} else {
|
||||||
|
index =
|
||||||
|
typeof route.state.index === 'number'
|
||||||
|
? route.state.index
|
||||||
|
: route.state.routes.length - 1;
|
||||||
|
|
||||||
|
const nextRoute = route.state.routes[index];
|
||||||
|
const nestedConfig = currentOptions[route.name].screens;
|
||||||
|
|
||||||
|
// if there is config for next route name, we go deeper
|
||||||
|
if (nestedConfig && nextRoute.name in nestedConfig) {
|
||||||
|
route = nextRoute as Route<string> & { state?: State };
|
||||||
|
currentOptions = nestedConfig;
|
||||||
} else {
|
} else {
|
||||||
// if it is the end of state, we return pattern
|
// If not, there is no sense in going deeper in config
|
||||||
if (route.state === undefined) {
|
hasNext = false;
|
||||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
|
||||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
index =
|
|
||||||
typeof route.state.index === 'number' ? route.state.index : 0;
|
|
||||||
const nextRoute = route.state.routes[index];
|
|
||||||
const deeperConfig = (currentOptions[route.name] as {
|
|
||||||
screens: Options;
|
|
||||||
}).screens;
|
|
||||||
// if there is config for next route name, we go deeper
|
|
||||||
if (nextRoute.name in deeperConfig) {
|
|
||||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
|
||||||
route = nextRoute as Route<string> & { state?: State };
|
|
||||||
currentOptions = deeperConfig;
|
|
||||||
} else {
|
|
||||||
// if not, there is no sense in going deeper in config
|
|
||||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
|
||||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pattern === undefined) {
|
if (pattern === undefined) {
|
||||||
// cut the first `/`
|
pattern = nestedRouteNames.join('/');
|
||||||
pattern = nestedRouteNames.substring(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const config =
|
|
||||||
currentOptions[route.name] !== undefined
|
|
||||||
? (currentOptions[route.name] as { stringify?: StringifyConfig })
|
|
||||||
.stringify
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const params = route.params
|
|
||||||
? // Stringify all of the param values before we use them
|
|
||||||
Object.entries(route.params).reduce<{
|
|
||||||
[key: string]: string;
|
|
||||||
}>((acc, [key, value]) => {
|
|
||||||
acc[key] = config?.[key] ? config[key](value) : String(value);
|
|
||||||
return acc;
|
|
||||||
}, {})
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (currentOptions[route.name] !== undefined) {
|
if (currentOptions[route.name] !== undefined) {
|
||||||
path += pattern
|
path += pattern
|
||||||
.split('/')
|
.split('/')
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
const name = p.replace(/^:/, '');
|
const name = p.replace(/^:/, '').replace(/\?$/, '');
|
||||||
|
|
||||||
// If the path has a pattern for a param, put the param in the path
|
// If the path has a pattern for a param, put the param in the path
|
||||||
if (params && name in params && p.startsWith(':')) {
|
if (p.startsWith(':')) {
|
||||||
const value = params[name];
|
const value = allParams[name];
|
||||||
|
|
||||||
// Remove the used value from the params object since we'll use the rest for query string
|
// Remove the used value from the params object since we'll use the rest for query string
|
||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
if (currentParams) {
|
||||||
delete params[name];
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
|
delete currentParams[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === undefined && p.endsWith('?')) {
|
||||||
|
// Optional params without value assigned in route.params should be ignored
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
return encodeURIComponent(value);
|
return encodeURIComponent(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,14 +157,15 @@ export default function getPathFromState(
|
|||||||
|
|
||||||
if (route.state) {
|
if (route.state) {
|
||||||
path += '/';
|
path += '/';
|
||||||
} else if (params) {
|
} else if (currentParams) {
|
||||||
for (let param in params) {
|
for (let param in currentParams) {
|
||||||
if (params[param] === 'undefined') {
|
if (currentParams[param] === 'undefined') {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
delete params[param];
|
delete currentParams[param];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const query = queryString.stringify(params);
|
|
||||||
|
const query = queryString.stringify(currentParams);
|
||||||
|
|
||||||
if (query) {
|
if (query) {
|
||||||
path += `?${query}`;
|
path += `?${query}`;
|
||||||
@@ -173,8 +176,63 @@ export default function getPathFromState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove multiple as well as trailing slashes
|
// Remove multiple as well as trailing slashes
|
||||||
path = path.replace(/\/+/, '/');
|
path = path.replace(/\/+/g, '/');
|
||||||
path = path.length > 1 ? path.replace(/\/$/, '') : path;
|
path = path.length > 1 ? path.replace(/\/$/, '') : path;
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Object.fromEntries is not available in older iOS versions
|
||||||
|
const fromEntries = <K extends string, V>(entries: (readonly [K, V])[]) =>
|
||||||
|
entries.reduce((acc, [k, v]) => {
|
||||||
|
acc[k] = v;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<K, V>);
|
||||||
|
|
||||||
|
const joinPaths = (...paths: string[]): string =>
|
||||||
|
([] as string[])
|
||||||
|
.concat(...paths.map((p) => p.split('/')))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
const createConfigItem = (
|
||||||
|
config: OptionsItem | string,
|
||||||
|
parentPattern?: string
|
||||||
|
): ConfigItem => {
|
||||||
|
if (typeof config === 'string') {
|
||||||
|
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
||||||
|
const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
|
||||||
|
|
||||||
|
return { pattern };
|
||||||
|
}
|
||||||
|
|
||||||
|
// If an object is specified as the value (e.g. Foo: { ... }),
|
||||||
|
// It can have `path` property and `screens` prop which has nested configs
|
||||||
|
const pattern =
|
||||||
|
config.exact !== true && parentPattern && config.path
|
||||||
|
? joinPaths(parentPattern, config.path)
|
||||||
|
: config.path;
|
||||||
|
|
||||||
|
const screens = config.screens
|
||||||
|
? createNormalizedConfigs(config.screens, pattern)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
return {
|
||||||
|
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
|
||||||
|
pattern: pattern?.split('/').filter(Boolean).join('/'),
|
||||||
|
stringify: config.stringify,
|
||||||
|
screens,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const createNormalizedConfigs = (
|
||||||
|
options: PathConfig,
|
||||||
|
pattern?: string
|
||||||
|
): Record<string, ConfigItem> =>
|
||||||
|
fromEntries(
|
||||||
|
Object.entries(options).map(([name, c]) => {
|
||||||
|
const result = createConfigItem(c, pattern);
|
||||||
|
|
||||||
|
return [name, result];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,29 +1,21 @@
|
|||||||
|
import escape from 'escape-string-regexp';
|
||||||
import queryString from 'query-string';
|
import queryString from 'query-string';
|
||||||
import {
|
import {
|
||||||
NavigationState,
|
NavigationState,
|
||||||
PartialState,
|
PartialState,
|
||||||
InitialState,
|
InitialState,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
|
import { PathConfig } from './types';
|
||||||
|
|
||||||
type ParseConfig = Record<string, (value: string) => any>;
|
type ParseConfig = Record<string, (value: string) => any>;
|
||||||
|
|
||||||
type Options = {
|
|
||||||
[routeName: string]:
|
|
||||||
| string
|
|
||||||
| {
|
|
||||||
path?: string;
|
|
||||||
parse?: ParseConfig;
|
|
||||||
screens?: Options;
|
|
||||||
initialRouteName?: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type RouteConfig = {
|
type RouteConfig = {
|
||||||
screen: string;
|
screen: string;
|
||||||
match: string | null;
|
regex?: RegExp;
|
||||||
|
path: string;
|
||||||
pattern: string;
|
pattern: string;
|
||||||
routeNames: string[];
|
routeNames: string[];
|
||||||
parse: ParseConfig | undefined;
|
parse?: ParseConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
type InitialRouteConfig = {
|
type InitialRouteConfig = {
|
||||||
@@ -56,45 +48,53 @@ type ResultState = PartialState<NavigationState> & {
|
|||||||
*/
|
*/
|
||||||
export default function getStateFromPath(
|
export default function getStateFromPath(
|
||||||
path: string,
|
path: string,
|
||||||
options: Options = {}
|
options: PathConfig = {}
|
||||||
): ResultState | undefined {
|
): ResultState | undefined {
|
||||||
let initialRoutes: InitialRouteConfig[] = [];
|
let initialRoutes: InitialRouteConfig[] = [];
|
||||||
|
|
||||||
// Create a normalized configs array which will be easier to use
|
// Create a normalized configs array which will be easier to use
|
||||||
const configs = ([] as RouteConfig[]).concat(
|
const configs = ([] as RouteConfig[])
|
||||||
...Object.keys(options).map((key) =>
|
.concat(
|
||||||
createNormalizedConfigs(key, options, [], initialRoutes)
|
...Object.keys(options).map((key) =>
|
||||||
|
createNormalizedConfigs(key, options, [], initialRoutes)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
// sort configs so the most exhaustive is always first to be chosen
|
// Sort configs so the most exhaustive is always first to be chosen
|
||||||
configs.sort(
|
b.pattern.split('/').length - a.pattern.split('/').length
|
||||||
(config1, config2) =>
|
);
|
||||||
config2.pattern.split('/').length - config1.pattern.split('/').length
|
|
||||||
);
|
|
||||||
|
|
||||||
let remaining = path
|
let remaining = path
|
||||||
.replace(/[/]+/, '/') // Replace multiple slash (//) with single ones
|
.replace(/\/+/g, '/') // Replace multiple slash (//) with single ones
|
||||||
.replace(/^\//, '') // Remove extra leading slash
|
.replace(/^\//, '') // Remove extra leading slash
|
||||||
.replace(/\?.*/, ''); // Remove query params which we will handle later
|
.replace(/\?.*$/, ''); // Remove query params which we will handle later
|
||||||
|
|
||||||
if (remaining === '') {
|
// Make sure there is a trailing slash
|
||||||
|
remaining = remaining.endsWith('/') ? remaining : `${remaining}/`;
|
||||||
|
|
||||||
|
if (remaining === '/') {
|
||||||
// We need to add special handling of empty path so navigation to empty path also works
|
// We need to add special handling of empty path so navigation to empty path also works
|
||||||
// When handling empty path, we should only look at the root level config
|
// When handling empty path, we should only look at the root level config
|
||||||
const match = configs.find(
|
const match = configs.find(
|
||||||
(config) =>
|
(config) =>
|
||||||
config.pattern === '' &&
|
config.path === '' &&
|
||||||
config.routeNames.every(
|
config.routeNames.every(
|
||||||
// make sure that none of the parent configs have a non-empty path defined
|
// Make sure that none of the parent configs have a non-empty path defined
|
||||||
(name) => !configs.find((c) => c.screen === name)?.pattern
|
(name) => !configs.find((c) => c.screen === name)?.path
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
return createNestedStateObject(
|
return createNestedStateObject(
|
||||||
match.routeNames,
|
match.routeNames.map((name, i, self) => {
|
||||||
initialRoutes,
|
if (i === self.length - 1) {
|
||||||
parseQueryParams(path, match.parse)
|
return { name, params: parseQueryParams(path, match.parse) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { name };
|
||||||
|
}),
|
||||||
|
initialRoutes
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,35 +106,18 @@ export default function getStateFromPath(
|
|||||||
|
|
||||||
while (remaining) {
|
while (remaining) {
|
||||||
let routeNames: string[] | undefined;
|
let routeNames: string[] | undefined;
|
||||||
let params: Record<string, any> | undefined;
|
let allParams: Record<string, any> | undefined;
|
||||||
|
|
||||||
// Go through all configs, and see if the next path segment matches our regex
|
// Go through all configs, and see if the next path segment matches our regex
|
||||||
for (const config of configs) {
|
for (const config of configs) {
|
||||||
if (!config.match) {
|
if (!config.regex) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let didMatch = true;
|
const match = remaining.match(config.regex);
|
||||||
const matchParts = config.match.split('/');
|
|
||||||
const remainingParts = remaining.split('/');
|
|
||||||
|
|
||||||
// we check if remaining path has enough segments to be handled with this pattern
|
// If our regex matches, we need to extract params from the path
|
||||||
if (config.pattern.split('/').length > remainingParts.length) {
|
if (match) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we keep info about the index of segment on which the params start
|
|
||||||
let paramsIndex = 0;
|
|
||||||
// the beginning of the remaining path should be the same as the part of config before params
|
|
||||||
for (paramsIndex; paramsIndex < matchParts.length; paramsIndex++) {
|
|
||||||
if (matchParts[paramsIndex] !== remainingParts[paramsIndex]) {
|
|
||||||
didMatch = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the first part of the path matches, we need to extract params from the path
|
|
||||||
if (didMatch) {
|
|
||||||
routeNames = [...config.routeNames];
|
routeNames = [...config.routeNames];
|
||||||
|
|
||||||
const paramPatterns = config.pattern
|
const paramPatterns = config.pattern
|
||||||
@@ -142,28 +125,16 @@ export default function getStateFromPath(
|
|||||||
.filter((p) => p.startsWith(':'));
|
.filter((p) => p.startsWith(':'));
|
||||||
|
|
||||||
if (paramPatterns.length) {
|
if (paramPatterns.length) {
|
||||||
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
allParams = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
||||||
const key = p.replace(/^:/, '');
|
const value = match![(i + 1) * 2].replace(/\//, ''); // The param segments appear every second item starting from 2 in the regex match result
|
||||||
const value = remainingParts[i + paramsIndex]; // The param segments start from the end of matched part
|
|
||||||
acc[key] =
|
acc[p] = value;
|
||||||
config.parse && config.parse[key]
|
|
||||||
? config.parse[key](value)
|
|
||||||
: value;
|
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// if pattern and remaining path have same amount of segments, there should be nothing left
|
remaining = remaining.replace(match[1], '');
|
||||||
if (config.pattern.split('/').length === remainingParts.length) {
|
|
||||||
remaining = '';
|
|
||||||
} else {
|
|
||||||
// For each segment of the pattern, remove one segment from remaining path
|
|
||||||
let i = config.pattern.split('/').length;
|
|
||||||
while (i--) {
|
|
||||||
remaining = remaining.substr(remaining.indexOf('/') + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -178,7 +149,46 @@ export default function getStateFromPath(
|
|||||||
remaining = segments.join('/');
|
remaining = segments.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = createNestedStateObject(routeNames, initialRoutes, params);
|
const state = createNestedStateObject(
|
||||||
|
routeNames.map((name) => {
|
||||||
|
const config = configs.find((c) => c.screen === name);
|
||||||
|
|
||||||
|
let params: object | undefined;
|
||||||
|
|
||||||
|
if (allParams && config?.path) {
|
||||||
|
const pattern = config.path;
|
||||||
|
|
||||||
|
if (pattern) {
|
||||||
|
const paramPatterns = pattern
|
||||||
|
.split('/')
|
||||||
|
.filter((p) => p.startsWith(':'));
|
||||||
|
|
||||||
|
if (paramPatterns.length) {
|
||||||
|
params = paramPatterns.reduce<Record<string, any>>((acc, p) => {
|
||||||
|
const key = p.replace(/^:/, '').replace(/\?$/, '');
|
||||||
|
const value = allParams![p];
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
acc[key] =
|
||||||
|
config.parse && config.parse[key]
|
||||||
|
? config.parse[key](value)
|
||||||
|
: value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params && Object.keys(params).length) {
|
||||||
|
return { name, params };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { name };
|
||||||
|
}),
|
||||||
|
initialRoutes
|
||||||
|
);
|
||||||
|
|
||||||
if (current) {
|
if (current) {
|
||||||
// The state should be nested inside the deepest route we parsed before
|
// The state should be nested inside the deepest route we parsed before
|
||||||
@@ -213,44 +223,65 @@ export default function getStateFromPath(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNormalizedConfigs(
|
const joinPaths = (...paths: string[]): string =>
|
||||||
key: string,
|
([] as string[])
|
||||||
routeConfig: Options,
|
.concat(...paths.map((p) => p.split('/')))
|
||||||
|
.filter(Boolean)
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
const createNormalizedConfigs = (
|
||||||
|
screen: string,
|
||||||
|
routeConfig: PathConfig,
|
||||||
routeNames: string[] = [],
|
routeNames: string[] = [],
|
||||||
initials: InitialRouteConfig[]
|
initials: InitialRouteConfig[],
|
||||||
): RouteConfig[] {
|
parentPattern?: string
|
||||||
|
): RouteConfig[] => {
|
||||||
const configs: RouteConfig[] = [];
|
const configs: RouteConfig[] = [];
|
||||||
|
|
||||||
routeNames.push(key);
|
routeNames.push(screen);
|
||||||
|
|
||||||
const value = routeConfig[key];
|
const config = routeConfig[screen];
|
||||||
|
|
||||||
if (typeof value === 'string') {
|
if (typeof config === 'string') {
|
||||||
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
||||||
configs.push(createConfigItem(key, routeNames, value));
|
const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
|
||||||
} else if (typeof value === 'object') {
|
|
||||||
|
configs.push(createConfigItem(screen, routeNames, pattern, config));
|
||||||
|
} else if (typeof config === 'object') {
|
||||||
|
let pattern: string | undefined;
|
||||||
|
|
||||||
// if an object is specified as the value (e.g. Foo: { ... }),
|
// if an object is specified as the value (e.g. Foo: { ... }),
|
||||||
// it can have `path` property and
|
// it can have `path` property and
|
||||||
// it could have `screens` prop which has nested configs
|
// it could have `screens` prop which has nested configs
|
||||||
if (typeof value.path === 'string') {
|
if (typeof config.path === 'string') {
|
||||||
configs.push(createConfigItem(key, routeNames, value.path, value.parse));
|
pattern =
|
||||||
|
config.exact !== true && parentPattern
|
||||||
|
? joinPaths(parentPattern, config.path)
|
||||||
|
: config.path;
|
||||||
|
|
||||||
|
configs.push(
|
||||||
|
createConfigItem(screen, routeNames, pattern, config.path, config.parse)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.screens) {
|
if (config.screens) {
|
||||||
// property `initialRouteName` without `screens` has no purpose
|
// property `initialRouteName` without `screens` has no purpose
|
||||||
if (value.initialRouteName) {
|
if (config.initialRouteName) {
|
||||||
initials.push({
|
initials.push({
|
||||||
initialRouteName: value.initialRouteName,
|
initialRouteName: config.initialRouteName,
|
||||||
connectedRoutes: Object.keys(value.screens),
|
connectedRoutes: Object.keys(config.screens),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Object.keys(value.screens).forEach((nestedConfig) => {
|
|
||||||
|
Object.keys(config.screens).forEach((nestedConfig) => {
|
||||||
const result = createNormalizedConfigs(
|
const result = createNormalizedConfigs(
|
||||||
nestedConfig,
|
nestedConfig,
|
||||||
value.screens as Options,
|
config.screens as PathConfig,
|
||||||
routeNames,
|
routeNames,
|
||||||
initials
|
initials,
|
||||||
|
pattern
|
||||||
);
|
);
|
||||||
|
|
||||||
configs.push(...result);
|
configs.push(...result);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -259,44 +290,62 @@ function createNormalizedConfigs(
|
|||||||
routeNames.pop();
|
routeNames.pop();
|
||||||
|
|
||||||
return configs;
|
return configs;
|
||||||
}
|
};
|
||||||
|
|
||||||
function createConfigItem(
|
const createConfigItem = (
|
||||||
screen: string,
|
screen: string,
|
||||||
routeNames: string[],
|
routeNames: string[],
|
||||||
pattern: string,
|
pattern: string,
|
||||||
|
path: string,
|
||||||
parse?: ParseConfig
|
parse?: ParseConfig
|
||||||
): RouteConfig {
|
): RouteConfig => {
|
||||||
// part being matched ends on the first param
|
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
|
||||||
const match = pattern !== '' ? pattern.split('/:')[0] : null;
|
pattern = pattern.split('/').filter(Boolean).join('/');
|
||||||
|
|
||||||
|
const regex = pattern
|
||||||
|
? new RegExp(
|
||||||
|
`^(${pattern
|
||||||
|
.split('/')
|
||||||
|
.map((it) => {
|
||||||
|
if (it.startsWith(':')) {
|
||||||
|
return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${escape(it)}\\/`;
|
||||||
|
})
|
||||||
|
.join('')})`
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
screen,
|
screen,
|
||||||
match,
|
regex,
|
||||||
pattern,
|
pattern,
|
||||||
|
path,
|
||||||
// The routeNames array is mutated, so copy it to keep the current state
|
// The routeNames array is mutated, so copy it to keep the current state
|
||||||
routeNames: [...routeNames],
|
routeNames: [...routeNames],
|
||||||
parse,
|
parse,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
function findParseConfigForRoute(
|
const findParseConfigForRoute = (
|
||||||
routeName: string,
|
routeName: string,
|
||||||
flatConfig: RouteConfig[]
|
flatConfig: RouteConfig[]
|
||||||
): ParseConfig | undefined {
|
): ParseConfig | undefined => {
|
||||||
for (const config of flatConfig) {
|
for (const config of flatConfig) {
|
||||||
if (routeName === config.routeNames[config.routeNames.length - 1]) {
|
if (routeName === config.routeNames[config.routeNames.length - 1]) {
|
||||||
return config.parse;
|
return config.parse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tries to find an initial route connected with the one passed
|
return undefined;
|
||||||
function findInitialRoute(
|
};
|
||||||
|
|
||||||
|
// Try to find an initial route connected with the one passed
|
||||||
|
const findInitialRoute = (
|
||||||
routeName: string,
|
routeName: string,
|
||||||
initialRoutes: InitialRouteConfig[]
|
initialRoutes: InitialRouteConfig[]
|
||||||
): string | undefined {
|
): string | undefined => {
|
||||||
for (const config of initialRoutes) {
|
for (const config of initialRoutes) {
|
||||||
if (config.connectedRoutes.includes(routeName)) {
|
if (config.connectedRoutes.includes(routeName)) {
|
||||||
return config.initialRouteName === routeName
|
return config.initialRouteName === routeName
|
||||||
@@ -305,28 +354,25 @@ function findInitialRoute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
// returns state object with values depending on whether
|
// returns state object with values depending on whether
|
||||||
// it is the end of state and if there is initialRoute for this level
|
// it is the end of state and if there is initialRoute for this level
|
||||||
function createStateObject(
|
const createStateObject = (
|
||||||
initialRoute: string | undefined,
|
initialRoute: string | undefined,
|
||||||
routeName: string,
|
routeName: string,
|
||||||
isEmpty: boolean,
|
params: Record<string, any> | undefined,
|
||||||
params?: Record<string, any> | undefined
|
isEmpty: boolean
|
||||||
): InitialState {
|
): InitialState => {
|
||||||
if (isEmpty) {
|
if (isEmpty) {
|
||||||
if (initialRoute) {
|
if (initialRoute) {
|
||||||
return {
|
return {
|
||||||
index: 1,
|
index: 1,
|
||||||
routes: [
|
routes: [{ name: initialRoute }, { name: routeName as string, params }],
|
||||||
{ name: initialRoute },
|
|
||||||
{ name: routeName as string, ...(params && { params }) },
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
routes: [{ name: routeName as string, ...(params && { params }) }],
|
routes: [{ name: routeName as string, params }],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -335,53 +381,59 @@ function createStateObject(
|
|||||||
index: 1,
|
index: 1,
|
||||||
routes: [
|
routes: [
|
||||||
{ name: initialRoute },
|
{ name: initialRoute },
|
||||||
{ name: routeName as string, state: { routes: [] } },
|
{ name: routeName as string, params, state: { routes: [] } },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return { routes: [{ name: routeName as string, state: { routes: [] } }] };
|
return {
|
||||||
|
routes: [{ name: routeName as string, params, state: { routes: [] } }],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function createNestedStateObject(
|
const createNestedStateObject = (
|
||||||
routeNames: string[],
|
routes: { name: string; params?: object }[],
|
||||||
initialRoutes: InitialRouteConfig[],
|
initialRoutes: InitialRouteConfig[]
|
||||||
params: object | undefined
|
) => {
|
||||||
) {
|
|
||||||
let state: InitialState;
|
let state: InitialState;
|
||||||
let routeName = routeNames.shift() as string;
|
let route = routes.shift() as { name: string; params?: object };
|
||||||
let initialRoute = findInitialRoute(routeName, initialRoutes);
|
let initialRoute = findInitialRoute(route.name, initialRoutes);
|
||||||
|
|
||||||
state = createStateObject(
|
state = createStateObject(
|
||||||
initialRoute,
|
initialRoute,
|
||||||
routeName,
|
route.name,
|
||||||
routeNames.length === 0,
|
route.params,
|
||||||
params
|
routes.length === 0
|
||||||
);
|
);
|
||||||
|
|
||||||
if (routeNames.length > 0) {
|
if (routes.length > 0) {
|
||||||
let nestedState = state;
|
let nestedState = state;
|
||||||
|
|
||||||
while ((routeName = routeNames.shift() as string)) {
|
while ((route = routes.shift() as { name: string; params?: object })) {
|
||||||
initialRoute = findInitialRoute(routeName, initialRoutes);
|
initialRoute = findInitialRoute(route.name, initialRoutes);
|
||||||
nestedState.routes[nestedState.index || 0].state = createStateObject(
|
|
||||||
|
const nestedStateIndex =
|
||||||
|
nestedState.index || nestedState.routes.length - 1;
|
||||||
|
|
||||||
|
nestedState.routes[nestedStateIndex].state = createStateObject(
|
||||||
initialRoute,
|
initialRoute,
|
||||||
routeName,
|
route.name,
|
||||||
routeNames.length === 0,
|
route.params,
|
||||||
params
|
routes.length === 0
|
||||||
);
|
);
|
||||||
if (routeNames.length > 0) {
|
|
||||||
nestedState = nestedState.routes[nestedState.index || 0]
|
if (routes.length > 0) {
|
||||||
|
nestedState = nestedState.routes[nestedStateIndex]
|
||||||
.state as InitialState;
|
.state as InitialState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
};
|
||||||
|
|
||||||
function findFocusedRoute(state: InitialState) {
|
const findFocusedRoute = (state: InitialState) => {
|
||||||
let current: InitialState | undefined = state;
|
let current: InitialState | undefined = state;
|
||||||
|
|
||||||
while (current?.routes[current.index || 0].state) {
|
while (current?.routes[current.index || 0].state) {
|
||||||
@@ -394,12 +446,12 @@ function findFocusedRoute(state: InitialState) {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return route;
|
return route;
|
||||||
}
|
};
|
||||||
|
|
||||||
function parseQueryParams(
|
const parseQueryParams = (
|
||||||
path: string,
|
path: string,
|
||||||
parseConfig?: Record<string, (value: string) => any>
|
parseConfig?: Record<string, (value: string) => any>
|
||||||
) {
|
) => {
|
||||||
const query = path.split('?')[1];
|
const query = path.split('?')[1];
|
||||||
const params = queryString.parse(query);
|
const params = queryString.parse(query);
|
||||||
|
|
||||||
@@ -412,4 +464,4 @@ function parseQueryParams(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(params).length ? params : undefined;
|
return Object.keys(params).length ? params : undefined;
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -422,6 +422,14 @@ export type NavigationContainerRef = NavigationHelpers<ParamListBase> &
|
|||||||
* Get the rehydrated navigation state of the navigation tree.
|
* Get the rehydrated navigation state of the navigation tree.
|
||||||
*/
|
*/
|
||||||
getRootState(): NavigationState;
|
getRootState(): NavigationState;
|
||||||
|
/**
|
||||||
|
* Get the currently focused navigation route.
|
||||||
|
*/
|
||||||
|
getCurrentRoute(): Route<string> | undefined;
|
||||||
|
/**
|
||||||
|
* Get the currently focused route's options.
|
||||||
|
*/
|
||||||
|
getCurrentOptions(): object | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TypedNavigator<
|
export type TypedNavigator<
|
||||||
@@ -462,3 +470,16 @@ export type TypedNavigator<
|
|||||||
_: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap>
|
_: RouteConfig<ParamList, RouteName, State, ScreenOptions, EventMap>
|
||||||
) => null;
|
) => null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PathConfig = {
|
||||||
|
[routeName: string]:
|
||||||
|
| string
|
||||||
|
| {
|
||||||
|
path?: string;
|
||||||
|
exact?: boolean;
|
||||||
|
parse?: Record<string, (value: string) => any>;
|
||||||
|
stringify?: Record<string, (value: any) => string>;
|
||||||
|
screens?: PathConfig;
|
||||||
|
initialRouteName?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -117,6 +117,28 @@ export default function useDescriptors<
|
|||||||
const screen = screens[route.name];
|
const screen = screens[route.name];
|
||||||
const navigation = navigations[route.key];
|
const navigation = navigations[route.key];
|
||||||
|
|
||||||
|
const routeOptions = {
|
||||||
|
// The default `screenOptions` passed to the navigator
|
||||||
|
...(typeof screenOptions === 'object' || screenOptions == null
|
||||||
|
? screenOptions
|
||||||
|
: screenOptions({
|
||||||
|
// @ts-ignore
|
||||||
|
route,
|
||||||
|
navigation,
|
||||||
|
})),
|
||||||
|
// The `options` prop passed to `Screen` elements
|
||||||
|
...(typeof screen.options === 'object' || screen.options == null
|
||||||
|
? screen.options
|
||||||
|
: screen.options({
|
||||||
|
// @ts-ignore
|
||||||
|
route,
|
||||||
|
// @ts-ignore
|
||||||
|
navigation,
|
||||||
|
})),
|
||||||
|
// The options set via `navigation.setOptions`
|
||||||
|
...options[route.key],
|
||||||
|
};
|
||||||
|
|
||||||
acc[route.key] = {
|
acc[route.key] = {
|
||||||
navigation,
|
navigation,
|
||||||
render() {
|
render() {
|
||||||
@@ -128,31 +150,12 @@ export default function useDescriptors<
|
|||||||
screen={screen}
|
screen={screen}
|
||||||
getState={getState}
|
getState={getState}
|
||||||
setState={setState}
|
setState={setState}
|
||||||
|
options={routeOptions}
|
||||||
/>
|
/>
|
||||||
</NavigationBuilderContext.Provider>
|
</NavigationBuilderContext.Provider>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
options: {
|
options: routeOptions,
|
||||||
// The default `screenOptions` passed to the navigator
|
|
||||||
...(typeof screenOptions === 'object' || screenOptions == null
|
|
||||||
? screenOptions
|
|
||||||
: screenOptions({
|
|
||||||
// @ts-ignore
|
|
||||||
route,
|
|
||||||
navigation,
|
|
||||||
})),
|
|
||||||
// The `options` prop passed to `Screen` elements
|
|
||||||
...(typeof screen.options === 'object' || screen.options == null
|
|
||||||
? screen.options
|
|
||||||
: screen.options({
|
|
||||||
// @ts-ignore
|
|
||||||
route,
|
|
||||||
// @ts-ignore
|
|
||||||
navigation,
|
|
||||||
})),
|
|
||||||
// The options set via `navigation.setOptions`
|
|
||||||
...options[route.key],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import useNavigation from './useNavigation';
|
|||||||
*/
|
*/
|
||||||
export default function useIsFocused(): boolean {
|
export default function useIsFocused(): boolean {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const getCurrentValue = React.useCallback(navigation.isFocused, [navigation]);
|
const getCurrentValue = React.useCallback(navigation.isFocused, [navigation]);
|
||||||
const subscribe = React.useCallback(
|
const subscribe = React.useCallback(
|
||||||
(callback: (value: boolean) => void) => {
|
(callback: (value: boolean) => void) => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
NavigationAction,
|
NavigationAction,
|
||||||
Route,
|
Route,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
import NavigationRouteContext from './NavigationRouteContext';
|
import NavigationRouteContext from './NavigationRouteContext';
|
||||||
import Screen from './Screen';
|
import Screen from './Screen';
|
||||||
import useEventEmitter from './useEventEmitter';
|
import useEventEmitter from './useEventEmitter';
|
||||||
@@ -264,41 +264,36 @@ export default function useNavigationBuilder<
|
|||||||
getKey,
|
getKey,
|
||||||
} = React.useContext(NavigationStateContext);
|
} = React.useContext(NavigationStateContext);
|
||||||
|
|
||||||
const previousStateRef = React.useRef<
|
const [initializedState, isFirstStateInitialization] = React.useMemo(() => {
|
||||||
NavigationState | PartialState<NavigationState> | undefined
|
|
||||||
>();
|
|
||||||
const initializedStateRef = React.useRef<State>();
|
|
||||||
|
|
||||||
let isFirstStateInitialization = false;
|
|
||||||
|
|
||||||
if (
|
|
||||||
initializedStateRef.current === undefined ||
|
|
||||||
currentState !== previousStateRef.current
|
|
||||||
) {
|
|
||||||
// If the current state isn't initialized on first render, we initialize it
|
// If the current state isn't initialized on first render, we initialize it
|
||||||
// We also need to re-initialize it if the state passed from parent was changed (maybe due to reset)
|
// We also need to re-initialize it if the state passed from parent was changed (maybe due to reset)
|
||||||
// Otherwise assume that the state was provided as initial state
|
// Otherwise assume that the state was provided as initial state
|
||||||
// So we need to rehydrate it to make it usable
|
// So we need to rehydrate it to make it usable
|
||||||
if (currentState === undefined || !isStateValid(currentState)) {
|
if (currentState === undefined || !isStateValid(currentState)) {
|
||||||
isFirstStateInitialization = true;
|
return [
|
||||||
initializedStateRef.current = router.getInitialState({
|
router.getInitialState({
|
||||||
routeNames,
|
|
||||||
routeParamList,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
initializedStateRef.current = router.getRehydratedState(
|
|
||||||
currentState as PartialState<State>,
|
|
||||||
{
|
|
||||||
routeNames,
|
routeNames,
|
||||||
routeParamList,
|
routeParamList,
|
||||||
}
|
}),
|
||||||
);
|
true,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
router.getRehydratedState(currentState as PartialState<State>, {
|
||||||
|
routeNames,
|
||||||
|
routeParamList,
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
// We explicitly don't include routeNames/routeParamList in the dep list
|
||||||
|
// below. We want to avoid forcing a new state to be calculated in cases
|
||||||
React.useEffect(() => {
|
// where routeConfigs change without affecting routeNames/routeParamList.
|
||||||
previousStateRef.current = currentState;
|
// Instead, we handle changes to these in the nextState code below. Note
|
||||||
}, [currentState]);
|
// that some changes to routeConfigs are explicitly ignored, such as changes
|
||||||
|
// to initialParams
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [currentState, router, isStateValid]);
|
||||||
|
|
||||||
let state =
|
let state =
|
||||||
// If the state isn't initialized, or stale, use the state we initialized instead
|
// If the state isn't initialized, or stale, use the state we initialized instead
|
||||||
@@ -306,7 +301,7 @@ export default function useNavigationBuilder<
|
|||||||
// So it'll be `undefined` or stale untill the first navigation event happens
|
// So it'll be `undefined` or stale untill the first navigation event happens
|
||||||
isStateInitialized(currentState)
|
isStateInitialized(currentState)
|
||||||
? (currentState as State)
|
? (currentState as State)
|
||||||
: (initializedStateRef.current as State);
|
: (initializedState as State);
|
||||||
|
|
||||||
let nextState: State = state;
|
let nextState: State = state;
|
||||||
|
|
||||||
@@ -362,13 +357,24 @@ export default function useNavigationBuilder<
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// We need to clean up state for this navigator on unmount
|
// We need to clean up state for this navigator on unmount
|
||||||
if (getCurrentState() !== undefined && getKey() === navigatorKey) {
|
// We do it in a timeout because we need to detect if another navigator mounted in the meantime
|
||||||
setState(undefined);
|
// For example, if another navigator has started rendering, we should skip cleanup
|
||||||
}
|
// Otherwise, our cleanup step will cleanup state for the other navigator and re-initialize it
|
||||||
|
setTimeout(() => {
|
||||||
|
if (getCurrentState() !== undefined && getKey() === navigatorKey) {
|
||||||
|
setState(undefined);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// We initialize this ref here to avoid a new getState getting initialized
|
||||||
|
// whenever initializedState changes. We want getState to have access to the
|
||||||
|
// latest initializedState, but don't need it to change when that happens
|
||||||
|
const initializedStateRef = React.useRef<State>();
|
||||||
|
initializedStateRef.current = initializedState;
|
||||||
|
|
||||||
const getState = React.useCallback((): State => {
|
const getState = React.useCallback((): State => {
|
||||||
const currentState = getCurrentState();
|
const currentState = getCurrentState();
|
||||||
|
|
||||||
|
|||||||
70
packages/core/src/useOptionsGetters.tsx
Normal file
70
packages/core/src/useOptionsGetters.tsx
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
|
import { NavigationState } from '@react-navigation/routers';
|
||||||
|
|
||||||
|
export default function useOptionsGetters({
|
||||||
|
key,
|
||||||
|
getOptions,
|
||||||
|
getState,
|
||||||
|
}: {
|
||||||
|
key?: string;
|
||||||
|
getOptions?: () => object | undefined;
|
||||||
|
getState?: () => NavigationState;
|
||||||
|
}) {
|
||||||
|
const optionsGettersFromChild = React.useRef<
|
||||||
|
Record<string, (() => object | undefined | null) | undefined>
|
||||||
|
>({});
|
||||||
|
|
||||||
|
const { addOptionsGetter: parentAddOptionsGetter } = React.useContext(
|
||||||
|
NavigationStateContext
|
||||||
|
);
|
||||||
|
|
||||||
|
const getOptionsFromListener = React.useCallback(() => {
|
||||||
|
for (let key in optionsGettersFromChild.current) {
|
||||||
|
if (optionsGettersFromChild.current.hasOwnProperty(key)) {
|
||||||
|
const result = optionsGettersFromChild.current[key]?.();
|
||||||
|
// null means unfocused route
|
||||||
|
if (result !== null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getCurrentOptions = React.useCallback(() => {
|
||||||
|
if (getState) {
|
||||||
|
const state = getState();
|
||||||
|
if (state.routes[state.index].key !== key) {
|
||||||
|
// null means unfocused route
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const optionsFromListener = getOptionsFromListener();
|
||||||
|
if (optionsFromListener !== null) {
|
||||||
|
return optionsFromListener;
|
||||||
|
}
|
||||||
|
return getOptions?.() ?? undefined;
|
||||||
|
}, [getState, getOptionsFromListener, getOptions, key]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
return parentAddOptionsGetter?.(key!, getCurrentOptions);
|
||||||
|
}, [getCurrentOptions, parentAddOptionsGetter, key]);
|
||||||
|
|
||||||
|
const addOptionsGetter = React.useCallback(
|
||||||
|
(key: string, getter: () => object | undefined | null) => {
|
||||||
|
optionsGettersFromChild.current[key] = getter;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
optionsGettersFromChild.current[key] = undefined;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
addOptionsGetter,
|
||||||
|
getCurrentOptions,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -8,6 +8,15 @@ const UNINTIALIZED_STATE = {};
|
|||||||
export default function useSyncState<T>(initialState?: (() => T) | T) {
|
export default function useSyncState<T>(initialState?: (() => T) | T) {
|
||||||
const stateRef = React.useRef<T>(UNINTIALIZED_STATE as any);
|
const stateRef = React.useRef<T>(UNINTIALIZED_STATE as any);
|
||||||
const isSchedulingRef = React.useRef(false);
|
const isSchedulingRef = React.useRef(false);
|
||||||
|
const isMountedRef = React.useRef(true);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
isMountedRef.current = true;
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
isMountedRef.current = false;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (stateRef.current === UNINTIALIZED_STATE) {
|
if (stateRef.current === UNINTIALIZED_STATE) {
|
||||||
stateRef.current =
|
stateRef.current =
|
||||||
@@ -20,7 +29,7 @@ export default function useSyncState<T>(initialState?: (() => T) | T) {
|
|||||||
const getState = React.useCallback(() => stateRef.current, []);
|
const getState = React.useCallback(() => stateRef.current, []);
|
||||||
|
|
||||||
const setState = React.useCallback((state: T) => {
|
const setState = React.useCallback((state: T) => {
|
||||||
if (state === stateRef.current) {
|
if (state === stateRef.current || !isMountedRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,6 +51,10 @@ export default function useSyncState<T>(initialState?: (() => T) | T) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const flushUpdates = React.useCallback(() => {
|
const flushUpdates = React.useCallback(() => {
|
||||||
|
if (!isMountedRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure that the tracking state is up-to-date.
|
// Make sure that the tracking state is up-to-date.
|
||||||
// We call it unconditionally, but React should skip the update if state is unchanged.
|
// We call it unconditionally, but React should skip the update if state is unchanged.
|
||||||
setTrackingState(stateRef.current);
|
setTrackingState(stateRef.current);
|
||||||
|
|||||||
@@ -3,6 +3,95 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.8.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.7...@react-navigation/drawer@5.8.0) (2020-05-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* update react-native-safe-area-context to 1.0.0 ([#8182](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/8182)) ([d62fbfe](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/d62fbfe255140f16b182e8b54b276a7c96f2aec6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.7](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.6...@react-navigation/drawer@5.7.7) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.6](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.5...@react-navigation/drawer@5.7.6) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.5](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.4...@react-navigation/drawer@5.7.5) (2020-05-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.4](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.3...@react-navigation/drawer@5.7.4) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.2...@react-navigation/drawer@5.7.3) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.1...@react-navigation/drawer@5.7.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.0...@react-navigation/drawer@5.7.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.7.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.4...@react-navigation/drawer@5.7.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.4](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.3...@react-navigation/drawer@5.6.4) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.6.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.2...@react-navigation/drawer@5.6.3) (2020-05-01)
|
## [5.6.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.2...@react-navigation/drawer@5.6.3) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/drawer
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|||||||
@@ -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": "5.6.3",
|
"version": "5.8.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,11 +20,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/drawer-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/drawer-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -39,17 +41,17 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^1.0.0",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export { default as useIsDrawerOpen } from './utils/useIsDrawerOpen';
|
|||||||
export type {
|
export type {
|
||||||
DrawerNavigationOptions,
|
DrawerNavigationOptions,
|
||||||
DrawerNavigationProp,
|
DrawerNavigationProp,
|
||||||
|
DrawerScreenProps,
|
||||||
DrawerContentOptions,
|
DrawerContentOptions,
|
||||||
DrawerContentComponentProps,
|
DrawerContentComponentProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
DrawerNavigationState,
|
DrawerNavigationState,
|
||||||
DrawerActionHelpers,
|
DrawerActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import type { PanGestureHandlerProperties } from 'react-native-gesture-handler';
|
import type { PanGestureHandlerProperties } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
@@ -208,6 +209,14 @@ export type DrawerNavigationProp<
|
|||||||
> &
|
> &
|
||||||
DrawerActionHelpers<ParamList>;
|
DrawerActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type DrawerScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: DrawerNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type DrawerDescriptor = Descriptor<
|
export type DrawerDescriptor = Descriptor<
|
||||||
ParamListBase,
|
ParamListBase,
|
||||||
string,
|
string,
|
||||||
|
|||||||
@@ -655,14 +655,14 @@ export default class DrawerView extends React.Component<Props> {
|
|||||||
gestureEnabled ? () => this.toggleDrawer(false) : undefined
|
gestureEnabled ? () => this.toggleDrawer(false) : undefined
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Overlay progress={progress} style={overlayStyle} />
|
<Overlay progress={progress} style={overlayStyle as any} />
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
) : (
|
) : (
|
||||||
<TapGestureHandler
|
<TapGestureHandler
|
||||||
enabled={gestureEnabled}
|
enabled={gestureEnabled}
|
||||||
onHandlerStateChange={this.handleTapStateChange}
|
onHandlerStateChange={this.handleTapStateChange}
|
||||||
>
|
>
|
||||||
<Overlay progress={progress} style={overlayStyle} />
|
<Overlay progress={progress} style={overlayStyle as any} />
|
||||||
</TapGestureHandler>
|
</TapGestureHandler>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,96 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.2.8](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.7...@react-navigation/material-bottom-tabs@5.2.8) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.7](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.6...@react-navigation/material-bottom-tabs@5.2.7) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.5...@react-navigation/material-bottom-tabs@5.2.6) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.4...@react-navigation/material-bottom-tabs@5.2.5) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* center icons in material tab bar. fixes [#8248](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/issues/8248) ([51b4087](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/51b40879bdb9cea5462a2291955513a88eb87340))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.3...@react-navigation/material-bottom-tabs@5.2.4) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.2...@react-navigation/material-bottom-tabs@5.2.3) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.1...@react-navigation/material-bottom-tabs@5.2.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.0...@react-navigation/material-bottom-tabs@5.2.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.15...@react-navigation/material-bottom-tabs@5.2.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/issues/7971)
|
||||||
|
* use links in bottom navigation tabs ([f384706](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/f384706741f7e2422c284b65da10425f7af680c0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.14...@react-navigation/material-bottom-tabs@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.13...@react-navigation/material-bottom-tabs@5.1.14) (2020-05-01)
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.13...@react-navigation/material-bottom-tabs@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|||||||
@@ -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": "5.1.14",
|
"version": "5.2.8",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,11 +20,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/material-bottom-tab-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/material-bottom-tab-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -35,15 +37,15 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"@types/react-native-vector-icons": "^6.4.5",
|
"@types/react-native-vector-icons": "^6.4.5",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-paper": "^3.7.0",
|
"react-native-paper": "^3.10.1",
|
||||||
"react-native-vector-icons": "^6.6.0",
|
"react-native-vector-icons": "^6.6.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ export { default as MaterialBottomTabView } from './views/MaterialBottomTabView'
|
|||||||
export type {
|
export type {
|
||||||
MaterialBottomTabNavigationOptions,
|
MaterialBottomTabNavigationOptions,
|
||||||
MaterialBottomTabNavigationProp,
|
MaterialBottomTabNavigationProp,
|
||||||
|
MaterialBottomTabScreenProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type MaterialBottomTabNavigationEventMap = {
|
export type MaterialBottomTabNavigationEventMap = {
|
||||||
@@ -32,6 +33,14 @@ export type MaterialBottomTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type MaterialBottomTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: MaterialBottomTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type MaterialBottomTabNavigationOptions = {
|
export type MaterialBottomTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet, Platform } from 'react-native';
|
||||||
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
import {
|
import {
|
||||||
@@ -8,6 +8,8 @@ import {
|
|||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActions,
|
TabActions,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
useLinkBuilder,
|
||||||
|
Link,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -24,13 +26,14 @@ type Props = MaterialBottomTabNavigationConfig & {
|
|||||||
|
|
||||||
type Scene = { route: { key: string } };
|
type Scene = { route: { key: string } };
|
||||||
|
|
||||||
export default function MaterialBottomTabView({
|
function MaterialBottomTabViewInner({
|
||||||
state,
|
state,
|
||||||
navigation,
|
navigation,
|
||||||
descriptors,
|
descriptors,
|
||||||
...rest
|
...rest
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { dark, colors } = useTheme();
|
const { dark, colors } = useTheme();
|
||||||
|
const buildLink = useLinkBuilder();
|
||||||
|
|
||||||
const theme = React.useMemo(() => {
|
const theme = React.useMemo(() => {
|
||||||
const t = dark ? DarkTheme : DefaultTheme;
|
const t = dark ? DarkTheme : DefaultTheme;
|
||||||
@@ -46,67 +49,104 @@ export default function MaterialBottomTabView({
|
|||||||
}, [colors, dark]);
|
}, [colors, dark]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationHelpersContext.Provider value={navigation}>
|
<BottomNavigation
|
||||||
<BottomNavigation
|
{...rest}
|
||||||
{...rest}
|
theme={theme}
|
||||||
theme={theme}
|
navigationState={state}
|
||||||
navigationState={state}
|
onIndexChange={(index: number) =>
|
||||||
onIndexChange={(index: number) =>
|
navigation.dispatch({
|
||||||
navigation.dispatch({
|
...TabActions.jumpTo(state.routes[index].name),
|
||||||
...TabActions.jumpTo(state.routes[index].name),
|
target: state.key,
|
||||||
target: state.key,
|
})
|
||||||
})
|
}
|
||||||
|
renderScene={({ route }) => descriptors[route.key].render()}
|
||||||
|
renderTouchable={
|
||||||
|
Platform.OS === 'web'
|
||||||
|
? ({
|
||||||
|
onPress,
|
||||||
|
route,
|
||||||
|
accessibilityRole: _0,
|
||||||
|
borderless: _1,
|
||||||
|
centered: _2,
|
||||||
|
rippleColor: _3,
|
||||||
|
style,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
{...rest}
|
||||||
|
// @ts-ignore
|
||||||
|
to={buildLink(route.name, route.params)}
|
||||||
|
accessibilityRole="link"
|
||||||
|
onPress={(e: any) => {
|
||||||
|
if (
|
||||||
|
!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) && // ignore clicks with modifier keys
|
||||||
|
(e.button == null || e.button === 0) // ignore everything but left clicks
|
||||||
|
) {
|
||||||
|
e.preventDefault();
|
||||||
|
onPress?.(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={[styles.touchable, style]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
renderIcon={({ route, focused, color }) => {
|
||||||
|
const { options } = descriptors[route.key];
|
||||||
|
|
||||||
|
if (typeof options.tabBarIcon === 'string') {
|
||||||
|
return (
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={options.tabBarIcon}
|
||||||
|
color={color}
|
||||||
|
size={24}
|
||||||
|
style={styles.icon}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
renderScene={({ route }) => descriptors[route.key].render()}
|
|
||||||
renderIcon={({ route, focused, color }) => {
|
|
||||||
const { options } = descriptors[route.key];
|
|
||||||
|
|
||||||
if (typeof options.tabBarIcon === 'string') {
|
if (typeof options.tabBarIcon === 'function') {
|
||||||
return (
|
return options.tabBarIcon({ focused, color });
|
||||||
<MaterialCommunityIcons
|
|
||||||
name={options.tabBarIcon}
|
|
||||||
color={color}
|
|
||||||
size={24}
|
|
||||||
style={styles.icon}
|
|
||||||
importantForAccessibility="no-hide-descendants"
|
|
||||||
accessibilityElementsHidden
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof options.tabBarIcon === 'function') {
|
|
||||||
return options.tabBarIcon({ focused, color });
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}}
|
|
||||||
getLabelText={({ route }: Scene) => {
|
|
||||||
const { options } = descriptors[route.key];
|
|
||||||
|
|
||||||
return options.tabBarLabel !== undefined
|
|
||||||
? options.tabBarLabel
|
|
||||||
: options.title !== undefined
|
|
||||||
? options.title
|
|
||||||
: (route as Route<string>).name;
|
|
||||||
}}
|
|
||||||
getColor={({ route }) => descriptors[route.key].options.tabBarColor}
|
|
||||||
getBadge={({ route }) => descriptors[route.key].options.tabBarBadge}
|
|
||||||
getAccessibilityLabel={({ route }) =>
|
|
||||||
descriptors[route.key].options.tabBarAccessibilityLabel
|
|
||||||
}
|
}
|
||||||
getTestID={({ route }) => descriptors[route.key].options.tabBarTestID}
|
|
||||||
onTabPress={({ route, preventDefault }) => {
|
|
||||||
const event = navigation.emit({
|
|
||||||
type: 'tabPress',
|
|
||||||
target: route.key,
|
|
||||||
canPreventDefault: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (event.defaultPrevented) {
|
return null;
|
||||||
preventDefault();
|
}}
|
||||||
}
|
getLabelText={({ route }: Scene) => {
|
||||||
}}
|
const { options } = descriptors[route.key];
|
||||||
/>
|
|
||||||
|
return options.tabBarLabel !== undefined
|
||||||
|
? options.tabBarLabel
|
||||||
|
: options.title !== undefined
|
||||||
|
? options.title
|
||||||
|
: (route as Route<string>).name;
|
||||||
|
}}
|
||||||
|
getColor={({ route }) => descriptors[route.key].options.tabBarColor}
|
||||||
|
getBadge={({ route }) => descriptors[route.key].options.tabBarBadge}
|
||||||
|
getAccessibilityLabel={({ route }) =>
|
||||||
|
descriptors[route.key].options.tabBarAccessibilityLabel
|
||||||
|
}
|
||||||
|
getTestID={({ route }) => descriptors[route.key].options.tabBarTestID}
|
||||||
|
onTabPress={({ route, preventDefault }) => {
|
||||||
|
const event = navigation.emit({
|
||||||
|
type: 'tabPress',
|
||||||
|
target: route.key,
|
||||||
|
canPreventDefault: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
preventDefault();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MaterialBottomTabView(props: Props) {
|
||||||
|
return (
|
||||||
|
<NavigationHelpersContext.Provider value={props.navigation}>
|
||||||
|
<MaterialBottomTabViewInner {...props} />
|
||||||
</NavigationHelpersContext.Provider>
|
</NavigationHelpersContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -115,4 +155,8 @@ const styles = StyleSheet.create({
|
|||||||
icon: {
|
icon: {
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
},
|
},
|
||||||
|
touchable: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,92 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.2.8](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.7...@react-navigation/material-top-tabs@5.2.8) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.7](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.6...@react-navigation/material-top-tabs@5.2.7) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.5...@react-navigation/material-top-tabs@5.2.6) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.4...@react-navigation/material-top-tabs@5.2.5) (2020-05-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.3...@react-navigation/material-top-tabs@5.2.4) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.2...@react-navigation/material-top-tabs@5.2.3) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.1...@react-navigation/material-top-tabs@5.2.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.0...@react-navigation/material-top-tabs@5.2.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.15...@react-navigation/material-top-tabs@5.2.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.14...@react-navigation/material-top-tabs@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.13...@react-navigation/material-top-tabs@5.1.14) (2020-05-01)
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.13...@react-navigation/material-top-tabs@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|||||||
@@ -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": "5.1.14",
|
"version": "5.2.8",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,11 +20,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/material-top-tab-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/material-top-tab-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -38,15 +40,15 @@
|
|||||||
"color": "^3.1.2"
|
"color": "^3.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-tab-view": "^2.14.0",
|
"react-native-tab-view": "^2.14.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export { default as MaterialTopTabBar } from './views/MaterialTopTabBar';
|
|||||||
export type {
|
export type {
|
||||||
MaterialTopTabNavigationOptions,
|
MaterialTopTabNavigationOptions,
|
||||||
MaterialTopTabNavigationProp,
|
MaterialTopTabNavigationProp,
|
||||||
|
MaterialTopTabScreenProps,
|
||||||
MaterialTopTabBarProps,
|
MaterialTopTabBarProps,
|
||||||
MaterialTopTabBarOptions,
|
MaterialTopTabBarOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
NavigationProp,
|
NavigationProp,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type MaterialTopTabNavigationEventMap = {
|
export type MaterialTopTabNavigationEventMap = {
|
||||||
@@ -46,6 +47,14 @@ export type MaterialTopTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type MaterialTopTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: MaterialTopTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type MaterialTopTabNavigationOptions = {
|
export type MaterialTopTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -3,6 +3,106 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.4.3](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.4.2...@react-navigation/native@5.4.3) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.4.1...@react-navigation/native@5.4.2) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.4.0...@react-navigation/native@5.4.1) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.3.2...@react-navigation/native@5.4.0) (2020-05-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix types for linking options ([d14f38b](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/d14f38b80ad569d5828c1919cea426c659173924))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add a PathConfig type ([60cb3c9](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/60cb3c9ba76d7ef166c9fe8b55f23728975b5b6e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.3.1...@react-navigation/native@5.3.2) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.3.0...@react-navigation/native@5.3.1) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.6...@react-navigation/native@5.3.0) (2020-05-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* initialState should take priority over deep link ([039017b](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/039017bc2af69120d2d10e8f2c8a62919c37eb65))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.5...@react-navigation/native@5.2.6) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.4...@react-navigation/native@5.2.5) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* return a promise-like from getInitialState ([#8210](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8210)) ([85ae378](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/85ae378d8cb1073895b281e13ebccee881d4c062))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.3...@react-navigation/native@5.2.4) (2020-05-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* return undefined for buildLink if linking is not enabled ([9fd2635](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/9fd2635756362c8da79656b4d9b101bebaaf7003))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.2...@react-navigation/native@5.2.3) (2020-05-01)
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.2...@react-navigation/native@5.2.3) (2020-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "5.2.3",
|
"version": "5.4.3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation",
|
"react-navigation",
|
||||||
@@ -16,11 +16,13 @@
|
|||||||
"homepage": "https://reactnavigation.org",
|
"homepage": "https://reactnavigation.org",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -31,16 +33,16 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^5.4.0"
|
"@react-navigation/core": "^5.8.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-testing-library": "^1.12.0",
|
"react-native-testing-library": "^1.13.2",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type Props = NavigationContainerProps & {
|
|||||||
* Container component which holds the navigation state designed for React Native apps.
|
* Container component which holds the navigation state designed for React Native apps.
|
||||||
* This should be rendered at the root wrapping the whole app.
|
* This should be rendered at the root wrapping the whole app.
|
||||||
*
|
*
|
||||||
* @param props.initialState Initial state object for the navigation tree. When deep link handling is enabled, this will be ignored if there's an incoming link.
|
* @param props.initialState Initial state object for the navigation tree. When deep link handling is enabled, this will override deep links when specified. Make sure that you don't specify an `initialState` when there's a deep link (`Linking.getInitialURL()`).
|
||||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||||
* @param props.theme Theme object for the navigators.
|
* @param props.theme Theme object for the navigators.
|
||||||
* @param props.linking Options for deep linking. Deep link handling is enabled when this prop is provided, unless `linking.enabled` is `false`.
|
* @param props.linking Options for deep linking. Deep link handling is enabled when this prop is provided, unless `linking.enabled` is `false`.
|
||||||
@@ -46,15 +46,13 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
...linking,
|
...linking,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isReady, initialState = rest.initialState] = useThenable(
|
const [isReady, initialState] = useThenable(getInitialState);
|
||||||
getInitialState
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => refContainer.current);
|
React.useImperativeHandle(ref, () => refContainer.current);
|
||||||
|
|
||||||
const linkingContext = React.useMemo(() => ({ options: linking }), [linking]);
|
const linkingContext = React.useMemo(() => ({ options: linking }), [linking]);
|
||||||
|
|
||||||
if (isLinkingEnabled && !isReady) {
|
if (rest.initialState == null && isLinkingEnabled && !isReady) {
|
||||||
// This is temporary until we have Suspense for data-fetching
|
// This is temporary until we have Suspense for data-fetching
|
||||||
// Then the fallback will be handled by a parent `Suspense` component
|
// Then the fallback will be handled by a parent `Suspense` component
|
||||||
return fallback as React.ReactElement;
|
return fallback as React.ReactElement;
|
||||||
@@ -65,7 +63,9 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
<ThemeProvider value={theme}>
|
<ThemeProvider value={theme}>
|
||||||
<BaseNavigationContainer
|
<BaseNavigationContainer
|
||||||
{...rest}
|
{...rest}
|
||||||
initialState={initialState}
|
initialState={
|
||||||
|
rest.initialState == null ? initialState : rest.initialState
|
||||||
|
}
|
||||||
ref={refContainer}
|
ref={refContainer}
|
||||||
/>
|
/>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
getStateFromPath as getStateFromPathDefault,
|
getStateFromPath as getStateFromPathDefault,
|
||||||
getPathFromState as getPathFromStateDefault,
|
getPathFromState as getPathFromStateDefault,
|
||||||
|
PathConfig,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
|
|
||||||
export type Theme = {
|
export type Theme = {
|
||||||
@@ -39,7 +40,7 @@ export type LinkingOptions = {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
config?: Parameters<typeof getStateFromPathDefault>[1];
|
config?: PathConfig;
|
||||||
/**
|
/**
|
||||||
* Custom function to parse the URL to a valid navigation state (advanced).
|
* Custom function to parse the URL to a valid navigation state (advanced).
|
||||||
* Only applicable on Web.
|
* Only applicable on Web.
|
||||||
|
|||||||
@@ -52,14 +52,18 @@ export default function useLinkBuilder() {
|
|||||||
(name: string, params?: object) => {
|
(name: string, params?: object) => {
|
||||||
const { options } = linking;
|
const { options } = linking;
|
||||||
|
|
||||||
// If we couldn't find a navigation object in context, we're at root
|
if (options?.enabled === false) {
|
||||||
// So we'll construct a basic state object to use
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const state = navigation
|
const state = navigation
|
||||||
? getRootStateForNavigate(navigation, {
|
? getRootStateForNavigate(navigation, {
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{ name, params }],
|
routes: [{ name, params }],
|
||||||
})
|
})
|
||||||
: {
|
: // If we couldn't find a navigation object in context, we're at root
|
||||||
|
// So we'll construct a basic state object to use
|
||||||
|
{
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{ name, params }],
|
routes: [{ name, params }],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ export default function useLinkProps({ to, action }: Props) {
|
|||||||
throw new Error("Couldn't find a navigation object.");
|
throw new Error("Couldn't find a navigation object.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (typeof to !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
`To 'to' option is invalid (found '${String(
|
||||||
|
to
|
||||||
|
)}'. It must be a valid string for navigation.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
linkTo(to);
|
linkTo(to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,18 +95,17 @@ export default function useLinking(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const then = (callback: (state: ResultState | undefined) => void) =>
|
|
||||||
Promise.resolve(callback(value));
|
|
||||||
|
|
||||||
// Make it a thenable to keep consistent with the native impl
|
// Make it a thenable to keep consistent with the native impl
|
||||||
const thenable = {
|
const thenable = {
|
||||||
then,
|
then(onfulfilled?: (state: ResultState | undefined) => void) {
|
||||||
|
return Promise.resolve(onfulfilled ? onfulfilled(value) : value);
|
||||||
|
},
|
||||||
catch() {
|
catch() {
|
||||||
return thenable;
|
return thenable;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return thenable;
|
return thenable as PromiseLike<ResultState | undefined>;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const previousStateLengthRef = React.useRef<number | undefined>(undefined);
|
const previousStateLengthRef = React.useRef<number | undefined>(undefined);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
type Thenable<T> = { then(cb: (result: T) => void): void };
|
export default function useThenable<T>(create: () => PromiseLike<T>) {
|
||||||
|
|
||||||
export default function useThenable<T>(create: () => Thenable<T>) {
|
|
||||||
const [promise] = React.useState(create);
|
const [promise] = React.useState(create);
|
||||||
|
|
||||||
// Check if our thenable is synchronous
|
// Check if our thenable is synchronous
|
||||||
|
|||||||
@@ -3,6 +3,49 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.4.7](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.6...@react-navigation/routers@5.4.7) (2020-05-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.6](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.5...@react-navigation/routers@5.4.6) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.5](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.4...@react-navigation/routers@5.4.5) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.4](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.3...@react-navigation/routers@5.4.4) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.3](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.2...@react-navigation/routers@5.4.3) (2020-05-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.1...@react-navigation/routers@5.4.2) (2020-04-30)
|
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.1...@react-navigation/routers@5.4.2) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/routers",
|
"name": "@react-navigation/routers",
|
||||||
"description": "Routers to help build custom navigators",
|
"description": "Routers to help build custom navigators",
|
||||||
"version": "5.4.2",
|
"version": "5.4.7",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -15,11 +15,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/custom-routers.html",
|
"homepage": "https://reactnavigation.org/docs/custom-routers.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -30,10 +32,10 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.0.2"
|
"nanoid": "^3.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,129 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.9...@react-navigation/stack@5.4.0) (2020-05-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* allow HeaderBackground's subViews to be touchable ([#8314](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8314)) ([021a911](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/021a9111d76b9b0d940c8829f7caebeb292fec2a))
|
||||||
|
* don't ignore previous header heights on layout update ([6dd45fc](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/6dd45fcff98a0c222d120d6f76a37130de45b92f))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* update react-native-safe-area-context to 1.0.0 ([#8182](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8182)) ([d62fbfe](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/d62fbfe255140f16b182e8b54b276a7c96f2aec6))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.9](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.8...@react-navigation/stack@5.3.9) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.8](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.7...@react-navigation/stack@5.3.8) (2020-05-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.7](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.6...@react-navigation/stack@5.3.7) (2020-05-16)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.6](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.5...@react-navigation/stack@5.3.6) (2020-05-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* reduce header title margin. fixes [#8267](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8267) ([d45dbe9](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/d45dbe97dc6625c6a8e80b5e658ab5a95045e5e8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.5](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.4...@react-navigation/stack@5.3.5) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.3...@react-navigation/stack@5.3.4) (2020-05-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.2...@react-navigation/stack@5.3.3) (2020-05-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix ios transitionspec settle time ([#8028](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8028)) ([dd7cff2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/dd7cff201608365a80f1d50a006df3e0d18e94a1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.1...@react-navigation/stack@5.3.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.0...@react-navigation/stack@5.3.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.19...@react-navigation/stack@5.3.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add proper margins to the header title ([f07cd13](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/f07cd135619d635e8841aa0df0b6e687636e7408))
|
||||||
|
* include safe are insets in title's margins ([4d1e102](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/4d1e102f8c3ffab116d0195fbab3086f6345a077))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.19](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.18...@react-navigation/stack@5.2.19) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.18](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.17...@react-navigation/stack@5.2.18) (2020-05-01)
|
## [5.2.18](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.17...@react-navigation/stack@5.2.18) (2020-05-01)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/stack
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/stack",
|
"name": "@react-navigation/stack",
|
||||||
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
||||||
"version": "5.2.18",
|
"version": "5.4.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -19,11 +19,13 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/stack-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/stack-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"src",
|
"src",
|
||||||
"lib"
|
"lib",
|
||||||
|
"!**/__tests__"
|
||||||
],
|
],
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
@@ -38,18 +40,18 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.14.3",
|
||||||
"@react-native-community/masked-view": "^0.1.7",
|
"@react-native-community/masked-view": "^0.1.10",
|
||||||
"@react-navigation/native": "^5.2.3",
|
"@react-navigation/native": "^5.4.3",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^1.0.0",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ export const TransitionIOSSpec: TransitionSpec = {
|
|||||||
damping: 500,
|
damping: 500,
|
||||||
mass: 3,
|
mass: 3,
|
||||||
overshootClamping: true,
|
overshootClamping: true,
|
||||||
restDisplacementThreshold: 0.01,
|
restDisplacementThreshold: 10,
|
||||||
restSpeedThreshold: 0.01,
|
restSpeedThreshold: 10,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export { default as useGestureHandlerRef } from './utils/useGestureHandlerRef';
|
|||||||
export type {
|
export type {
|
||||||
StackNavigationOptions,
|
StackNavigationOptions,
|
||||||
StackNavigationProp,
|
StackNavigationProp,
|
||||||
|
StackScreenProps,
|
||||||
StackHeaderProps,
|
StackHeaderProps,
|
||||||
StackHeaderLeftButtonProps,
|
StackHeaderLeftButtonProps,
|
||||||
StackHeaderTitleProps,
|
StackHeaderTitleProps,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
StackNavigationState,
|
StackNavigationState,
|
||||||
StackActionHelpers,
|
StackActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type StackNavigationEventMap = {
|
export type StackNavigationEventMap = {
|
||||||
@@ -45,6 +46,14 @@ export type StackNavigationProp<
|
|||||||
> &
|
> &
|
||||||
StackActionHelpers<ParamList>;
|
StackActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type StackScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: StackNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type Layout = { width: number; height: number };
|
export type Layout = { width: number; height: number };
|
||||||
|
|
||||||
export type GestureDirection =
|
export type GestureDirection =
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export default React.memo(function Header(props: StackHeaderProps) {
|
|||||||
: previous.route.name;
|
: previous.route.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const goBack = React.useCallback(
|
const goBack = React.useCallback(
|
||||||
debounce(() => {
|
debounce(() => {
|
||||||
if (navigation.isFocused() && navigation.canGoBack()) {
|
if (navigation.isFocused() && navigation.canGoBack()) {
|
||||||
|
|||||||
@@ -307,6 +307,8 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const rightButton = right ? right({ tintColor: headerTintColor }) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
@@ -345,8 +347,19 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
style={[
|
style={[
|
||||||
headerTitleAlign === 'left'
|
headerTitleAlign === 'left'
|
||||||
? { position: 'absolute', left: leftButton ? 72 : 16 }
|
? {
|
||||||
: { marginHorizontal: 18 },
|
position: 'absolute',
|
||||||
|
left: (leftButton ? 72 : 16) + insets.left,
|
||||||
|
right: (rightButton ? 72 : 16) + insets.right,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
marginHorizontal:
|
||||||
|
(leftButton ? 32 : 16) +
|
||||||
|
(leftButton && headerBackTitleVisible !== false
|
||||||
|
? 40
|
||||||
|
: 0) +
|
||||||
|
Math.max(insets.left, insets.right),
|
||||||
|
},
|
||||||
titleStyle,
|
titleStyle,
|
||||||
titleContainerStyle,
|
titleContainerStyle,
|
||||||
]}
|
]}
|
||||||
@@ -359,7 +372,7 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
style: customTitleStyle,
|
style: customTitleStyle,
|
||||||
})}
|
})}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
{right ? (
|
{rightButton ? (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
style={[
|
style={[
|
||||||
@@ -369,7 +382,7 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
rightContainerStyle,
|
rightContainerStyle,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{right({ tintColor: headerTintColor })}
|
{rightButton}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|||||||
import { Animated, StyleSheet, Platform } from 'react-native';
|
import { Animated, StyleSheet, Platform } from 'react-native';
|
||||||
import { useTheme } from '@react-navigation/native';
|
import { useTheme } from '@react-navigation/native';
|
||||||
|
|
||||||
type Props = React.ComponentProps<typeof Animated.Text> & {
|
type Props = Omit<React.ComponentProps<typeof Animated.Text>, 'key'> & {
|
||||||
tintColor?: string;
|
tintColor?: string;
|
||||||
children?: string;
|
children?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
props.insets,
|
props.insets,
|
||||||
state.descriptors,
|
state.descriptors,
|
||||||
layout,
|
layout,
|
||||||
{}
|
state.headerHeights
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user