mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-14 17:42:29 +08:00
Compare commits
19 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
853740bfaf | ||
|
|
179b6312fe | ||
|
|
043924ca48 | ||
|
|
813a5903b5 | ||
|
|
3709e652f4 | ||
|
|
5b15c7164f | ||
|
|
e030932497 | ||
|
|
adbfedcd58 | ||
|
|
bc9b044fb3 | ||
|
|
f24d3a3461 | ||
|
|
3df65e2819 | ||
|
|
5c4afc5cb4 | ||
|
|
d5bb357053 | ||
|
|
b1fe73097f | ||
|
|
49f6fed6d3 | ||
|
|
b1a65fc73e | ||
|
|
3ea8eec432 | ||
|
|
00e0f05190 | ||
|
|
193c344ba5 |
@@ -1,4 +1,4 @@
|
|||||||
module.exports = function(api) {
|
module.exports = function (api) {
|
||||||
api.cache(true);
|
api.cache(true);
|
||||||
return {
|
return {
|
||||||
presets: ['babel-preset-expo'],
|
presets: ['babel-preset-expo'],
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ const modules = ['@expo/vector-icons']
|
|||||||
// List all packages under `packages/`
|
// List all packages under `packages/`
|
||||||
.readdirSync(packages)
|
.readdirSync(packages)
|
||||||
// Ignore hidden files such as .DS_Store
|
// Ignore hidden files such as .DS_Store
|
||||||
.filter(p => !p.startsWith('.'))
|
.filter((p) => !p.startsWith('.'))
|
||||||
.map(p => {
|
.map((p) => {
|
||||||
const pak = JSON.parse(
|
const pak = JSON.parse(
|
||||||
fs.readFileSync(path.join(packages, p, 'package.json'), 'utf8')
|
fs.readFileSync(path.join(packages, p, 'package.json'), 'utf8')
|
||||||
);
|
);
|
||||||
@@ -50,9 +50,9 @@ module.exports = {
|
|||||||
blacklistRE: blacklist(
|
blacklistRE: blacklist(
|
||||||
fs
|
fs
|
||||||
.readdirSync(packages)
|
.readdirSync(packages)
|
||||||
.map(p => path.join(packages, p))
|
.map((p) => path.join(packages, p))
|
||||||
.map(
|
.map(
|
||||||
it => new RegExp(`^${escape(path.join(it, 'node_modules'))}\\/.*$`)
|
(it) => new RegExp(`^${escape(path.join(it, 'node_modules'))}\\/.*$`)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
enhanceMiddleware: middleware => {
|
enhanceMiddleware: (middleware) => {
|
||||||
return (req, res, next) => {
|
return (req, res, next) => {
|
||||||
// When an asset is imported outside the project root, it has wrong path on Android
|
// When an asset is imported outside the project root, it has wrong path on Android
|
||||||
// This happens for the back button in stack, so we fix the path to correct one
|
// This happens for the back button in stack, so we fix the path to correct one
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function BottomTabsScreen() {
|
|||||||
return (
|
return (
|
||||||
<BottomTabs.Navigator
|
<BottomTabs.Navigator
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
tabBarButton: props => <TouchableBounce {...props} />,
|
tabBarButton: (props) => <TouchableBounce {...props} />,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BottomTabs.Screen
|
<BottomTabs.Screen
|
||||||
@@ -38,7 +38,7 @@ export default function BottomTabsScreen() {
|
|||||||
tabBarIcon: getTabBarIcon('file-document-box'),
|
tabBarIcon: getTabBarIcon('file-document-box'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props => <SimpleStackScreen {...props} headerMode="none" />}
|
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
|
||||||
</BottomTabs.Screen>
|
</BottomTabs.Screen>
|
||||||
<BottomTabs.Screen
|
<BottomTabs.Screen
|
||||||
name="Chat"
|
name="Chat"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default function BottomTabsScreen() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BottomTabs.Navigator>
|
<BottomTabs.Navigator>
|
||||||
{tabs.map(i => (
|
{tabs.map((i) => (
|
||||||
<BottomTabs.Screen
|
<BottomTabs.Screen
|
||||||
key={i}
|
key={i}
|
||||||
name={`tab-${i}`}
|
name={`tab-${i}`}
|
||||||
@@ -29,12 +29,14 @@ export default function BottomTabsScreen() {
|
|||||||
{() => (
|
{() => (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Title>Tab {i}</Title>
|
<Title>Tab {i}</Title>
|
||||||
<Button onPress={() => setTabs(tabs => [...tabs, tabs.length])}>
|
<Button onPress={() => setTabs((tabs) => [...tabs, tabs.length])}>
|
||||||
Add a tab
|
Add a tab
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
setTabs(tabs => (tabs.length > 1 ? tabs.slice(0, -1) : tabs))
|
setTabs((tabs) =>
|
||||||
|
tabs.length > 1 ? tabs.slice(0, -1) : tabs
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Remove a tab
|
Remove a tab
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export default function MaterialBottomTabsScreen() {
|
|||||||
tabBarColor: '#C9E7F8',
|
tabBarColor: '#C9E7F8',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props => <SimpleStackScreen {...props} headerMode="none" />}
|
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
|
||||||
</MaterialBottomTabs.Screen>
|
</MaterialBottomTabs.Screen>
|
||||||
<MaterialBottomTabs.Screen
|
<MaterialBottomTabs.Screen
|
||||||
name="Chat"
|
name="Chat"
|
||||||
|
|||||||
@@ -68,10 +68,7 @@ export default function Chat(props: Partial<ScrollViewProps>) {
|
|||||||
styles.input,
|
styles.input,
|
||||||
{ backgroundColor: colors.card, color: colors.text },
|
{ backgroundColor: colors.card, color: colors.text },
|
||||||
]}
|
]}
|
||||||
placeholderTextColor={Color(colors.text)
|
placeholderTextColor={Color(colors.text).alpha(0.5).rgb().string()}
|
||||||
.alpha(0.5)
|
|
||||||
.rgb()
|
|
||||||
.string()}
|
|
||||||
placeholder="Write a message"
|
placeholder="Write a message"
|
||||||
underlineColorAndroid="transparent"
|
underlineColorAndroid="transparent"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ export default function NewsFeed(props: Props) {
|
|||||||
<Card style={styles.card}>
|
<Card style={styles.card}>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="What's on your mind?"
|
placeholder="What's on your mind?"
|
||||||
placeholderTextColor={Color(colors.text)
|
placeholderTextColor={Color(colors.text).alpha(0.5).rgb().string()}
|
||||||
.alpha(0.5)
|
|
||||||
.rgb()
|
|
||||||
.string()}
|
|
||||||
style={styles.input}
|
style={styles.input}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ export default function App() {
|
|||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
initialState={initialState}
|
initialState={initialState}
|
||||||
onStateChange={state =>
|
onStateChange={(state) =>
|
||||||
AsyncStorage.setItem(
|
AsyncStorage.setItem(
|
||||||
NAVIGATION_PERSISTENCE_KEY,
|
NAVIGATION_PERSISTENCE_KEY,
|
||||||
JSON.stringify(state)
|
JSON.stringify(state)
|
||||||
@@ -298,12 +298,12 @@ export default function App() {
|
|||||||
theme.dark ? 'light' : 'dark'
|
theme.dark ? 'light' : 'dark'
|
||||||
);
|
);
|
||||||
|
|
||||||
setTheme(t => (t.dark ? DefaultTheme : DarkTheme));
|
setTheme((t) => (t.dark ? DefaultTheme : DarkTheme));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<Divider />
|
||||||
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
||||||
name => (
|
(name) => (
|
||||||
<List.Item
|
<List.Item
|
||||||
key={name}
|
key={name}
|
||||||
title={SCREENS[name].title}
|
title={SCREENS[name].title}
|
||||||
@@ -315,7 +315,7 @@ export default function App() {
|
|||||||
)}
|
)}
|
||||||
</Stack.Screen>
|
</Stack.Screen>
|
||||||
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
||||||
name => (
|
(name) => (
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
key={name}
|
key={name}
|
||||||
name={name}
|
name={name}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
|||||||
const node_modules = path.resolve(__dirname, '..', 'node_modules');
|
const node_modules = path.resolve(__dirname, '..', 'node_modules');
|
||||||
const packages = path.resolve(__dirname, '..', 'packages');
|
const packages = path.resolve(__dirname, '..', 'packages');
|
||||||
|
|
||||||
module.exports = async function(env, argv) {
|
module.exports = async function (env, argv) {
|
||||||
const config = await createExpoWebpackConfigAsync(env, argv);
|
const config = await createExpoWebpackConfigAsync(env, argv);
|
||||||
|
|
||||||
config.context = path.resolve(__dirname, '..');
|
config.context = path.resolve(__dirname, '..');
|
||||||
@@ -20,7 +20,7 @@ module.exports = async function(env, argv) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
config.resolve.plugins = config.resolve.plugins.filter(
|
config.resolve.plugins = config.resolve.plugins.filter(
|
||||||
p => !(p instanceof ModuleScopePlugin)
|
(p) => !(p instanceof ModuleScopePlugin)
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.assign(config.resolve.alias, {
|
Object.assign(config.resolve.alias, {
|
||||||
@@ -30,7 +30,7 @@ module.exports = async function(env, argv) {
|
|||||||
'@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).forEach((name) => {
|
||||||
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
||||||
packages,
|
packages,
|
||||||
name,
|
name,
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
"husky": "^4.2.3",
|
"husky": "^4.2.3",
|
||||||
"jest": "^25.1.0",
|
"jest": "^25.1.0",
|
||||||
"lerna": "^3.20.2",
|
"lerna": "^3.20.2",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^2.0.1",
|
||||||
"typescript": "^3.7.5"
|
"typescript": "^3.7.5"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
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.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.2...@react-navigation/bottom-tabs@5.2.3) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.1...@react-navigation/bottom-tabs@5.2.2) (2020-03-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/7485)
|
||||||
|
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6789)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.0...@react-navigation/bottom-tabs@5.2.1) (2020-03-17)
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.0...@react-navigation/bottom-tabs@5.2.1) (2020-03-17)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
**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.2.1",
|
"version": "5.2.3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.61.22",
|
||||||
|
|||||||
@@ -51,7 +51,12 @@ export default function BottomTabBar({
|
|||||||
}: Props) {
|
}: Props) {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
|
const [dimensions, setDimensions] = React.useState(() => {
|
||||||
|
const { height = 0, width = 0 } = Dimensions.get('window');
|
||||||
|
|
||||||
|
return { height, width };
|
||||||
|
});
|
||||||
|
|
||||||
const [layout, setLayout] = React.useState({
|
const [layout, setLayout] = React.useState({
|
||||||
height: 0,
|
height: 0,
|
||||||
width: dimensions.width,
|
width: dimensions.width,
|
||||||
@@ -116,7 +121,7 @@ export default function BottomTabBar({
|
|||||||
const handleLayout = (e: LayoutChangeEvent) => {
|
const handleLayout = (e: LayoutChangeEvent) => {
|
||||||
const { height, width } = e.nativeEvent.layout;
|
const { height, width } = e.nativeEvent.layout;
|
||||||
|
|
||||||
setLayout(layout => {
|
setLayout((layout) => {
|
||||||
if (height === layout.height && width === layout.width) {
|
if (height === layout.height && width === layout.width) {
|
||||||
return layout;
|
return layout;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -133,9 +133,7 @@ export default function BottomTabBarItem({
|
|||||||
|
|
||||||
const inactiveTintColor =
|
const inactiveTintColor =
|
||||||
customInactiveTintColor === undefined
|
customInactiveTintColor === undefined
|
||||||
? Color(colors.text)
|
? Color(colors.text).mix(Color(colors.card), 0.5).hex()
|
||||||
.mix(Color(colors.card), 0.5)
|
|
||||||
.hex()
|
|
||||||
: customInactiveTintColor;
|
: customInactiveTintColor;
|
||||||
|
|
||||||
const renderLabel = ({ focused }: { focused: boolean }) => {
|
const renderLabel = ({ focused }: { focused: boolean }) => {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform, StyleSheet, View } from 'react-native';
|
import { Platform, StyleSheet, View } from 'react-native';
|
||||||
|
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { Screen, screensEnabled } from 'react-native-screens';
|
import { Screen, screensEnabled } from 'react-native-screens';
|
||||||
|
|
||||||
@@ -10,12 +9,14 @@ type Props = {
|
|||||||
style?: any;
|
style?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container
|
const FAR_FAR_AWAY = 30000; // this should be big enough to move the whole view out of its container
|
||||||
|
|
||||||
export default class ResourceSavingScene extends React.Component<Props> {
|
export default class ResourceSavingScene extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
if (screensEnabled?.()) {
|
// react-native-screens is buggy on web
|
||||||
|
if (screensEnabled?.() && Platform.OS !== 'web') {
|
||||||
const { isVisible, ...rest } = this.props;
|
const { isVisible, ...rest } = this.props;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return <Screen active={isVisible ? 1 : 0} {...rest} />;
|
return <Screen active={isVisible ? 1 : 0} {...rest} />;
|
||||||
}
|
}
|
||||||
@@ -24,7 +25,13 @@ export default class ResourceSavingScene extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[styles.container, style, { opacity: isVisible ? 1 : 0 }]}
|
style={[
|
||||||
|
styles.container,
|
||||||
|
Platform.OS === 'web'
|
||||||
|
? { display: isVisible ? 'flex' : 'none' }
|
||||||
|
: null,
|
||||||
|
style,
|
||||||
|
]}
|
||||||
collapsable={false}
|
collapsable={false}
|
||||||
removeClippedSubviews={
|
removeClippedSubviews={
|
||||||
// On iOS, set removeClippedSubviews to true only when not focused
|
// On iOS, set removeClippedSubviews to true only when not focused
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type Props = {
|
|||||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||||
return (
|
return (
|
||||||
<SafeAreaConsumer>
|
<SafeAreaConsumer>
|
||||||
{insets => {
|
{(insets) => {
|
||||||
if (insets) {
|
if (insets) {
|
||||||
// If we already have insets, don't wrap the stack in another safe area provider
|
// If we already have insets, don't wrap the stack in another safe area provider
|
||||||
// This avoids an issue with updates at the cost of potentially incorrect values
|
// This avoids an issue with updates at the cost of potentially incorrect values
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.5](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.4...@react-navigation/compat@5.1.5) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.3...@react-navigation/compat@5.1.4) (2020-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.2...@react-navigation/compat@5.1.3) (2020-03-17)
|
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.2...@react-navigation/compat@5.1.3) (2020-03-17)
|
||||||
|
|
||||||
**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.3",
|
"version": "5.1.5",
|
||||||
"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": {
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"typescript": "^3.7.5"
|
"typescript": "^3.7.5"
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default function createCompatNavigatorFactory<
|
|||||||
function Navigator({ screenProps }: { screenProps?: unknown }) {
|
function Navigator({ screenProps }: { screenProps?: unknown }) {
|
||||||
const screens = React.useMemo(
|
const screens = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
routeNames.map(name => {
|
routeNames.map((name) => {
|
||||||
let getScreenComponent: () => CompatScreenType<NavigationPropType>;
|
let getScreenComponent: () => CompatScreenType<NavigationPropType>;
|
||||||
|
|
||||||
let initialParams;
|
let initialParams;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function useCompatNavigation<
|
|||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
const isFirstRouteInParent = useNavigationState(
|
const isFirstRouteInParent = useNavigationState(
|
||||||
state => state.routes[0].key === route.key
|
(state) => state.routes[0].key === route.key
|
||||||
);
|
);
|
||||||
|
|
||||||
const context = React.useRef<Record<string, any>>({});
|
const context = React.useRef<Record<string, any>>({});
|
||||||
|
|||||||
@@ -26,8 +26,9 @@ export default function withNavigation<
|
|||||||
return <Comp ref={onRef} navigation={navigation} {...rest} />;
|
return <Comp ref={onRef} navigation={navigation} {...rest} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
WrappedComponent.displayName = `withNavigation(${Comp.displayName ||
|
WrappedComponent.displayName = `withNavigation(${
|
||||||
Comp.name})`;
|
Comp.displayName || Comp.name
|
||||||
|
})`;
|
||||||
|
|
||||||
return WrappedComponent;
|
return WrappedComponent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ export default function withNavigationFocus<
|
|||||||
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
|
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
WrappedComponent.displayName = `withNavigationFocus(${Comp.displayName ||
|
WrappedComponent.displayName = `withNavigationFocus(${
|
||||||
Comp.name})`;
|
Comp.displayName || Comp.name
|
||||||
|
})`;
|
||||||
|
|
||||||
return WrappedComponent;
|
return WrappedComponent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,30 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.3...@react-navigation/core@5.3.0) (2020-03-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* return correct value for isFocused after changing screens ([5b15c71](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/5b15c7164f5503f2f0d51006a3f23bd0c58fd9b7)), closes [#7843](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/7843)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* support function in listeners prop ([3709e65](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3709e652f41a16c2c2b05d5dbbe1da2017ba2c3f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.2...@react-navigation/core@5.2.3) (2020-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/core
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.1...@react-navigation/core@5.2.2) (2020-03-16)
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.1...@react-navigation/core@5.2.2) (2020-03-16)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/core
|
**Note:** Version bump only for package @react-navigation/core
|
||||||
|
|||||||
@@ -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.2.2",
|
"version": "5.3.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.1.1",
|
"@react-navigation/routers": "^5.2.0",
|
||||||
"escape-string-regexp": "^2.0.0",
|
"escape-string-regexp": "^2.0.0",
|
||||||
"query-string": "^6.11.1",
|
"query-string": "^6.11.1",
|
||||||
"react-is": "^16.13.0",
|
"react-is": "^16.13.0",
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const getPartialState = (
|
|||||||
return {
|
return {
|
||||||
...partialState,
|
...partialState,
|
||||||
stale: true,
|
stale: true,
|
||||||
routes: state.routes.map(route => {
|
routes: state.routes.map((route) => {
|
||||||
if (route.state === undefined) {
|
if (route.state === undefined) {
|
||||||
return route as Route<string> & {
|
return route as Route<string> & {
|
||||||
state?: PartialState<NavigationState>;
|
state?: PartialState<NavigationState>;
|
||||||
@@ -136,6 +136,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { trackState, trackAction } = useDevTools({
|
const { trackState, trackAction } = useDevTools({
|
||||||
|
enabled: false,
|
||||||
name: '@react-navigation',
|
name: '@react-navigation',
|
||||||
reset,
|
reset,
|
||||||
state,
|
state,
|
||||||
@@ -155,7 +156,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
throw new Error(NOT_INITIALIZED_ERROR);
|
throw new Error(NOT_INITIALIZED_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
listeners[0](navigation => navigation.dispatch(action));
|
listeners[0]((navigation) => navigation.dispatch(action));
|
||||||
};
|
};
|
||||||
|
|
||||||
const canGoBack = () => {
|
const canGoBack = () => {
|
||||||
@@ -163,7 +164,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { result, handled } = listeners[0](navigation =>
|
const { result, handled } = listeners[0]((navigation) =>
|
||||||
navigation.canGoBack()
|
navigation.canGoBack()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default function SceneView<
|
|||||||
|
|
||||||
const getCurrentState = React.useCallback(() => {
|
const getCurrentState = React.useCallback(() => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const currentRoute = state.routes.find(r => r.key === route.key);
|
const currentRoute = state.routes.find((r) => r.key === route.key);
|
||||||
|
|
||||||
return currentRoute ? currentRoute.state : undefined;
|
return currentRoute ? currentRoute.state : undefined;
|
||||||
}, [getState, route.key]);
|
}, [getState, route.key]);
|
||||||
@@ -62,7 +62,7 @@ export default function SceneView<
|
|||||||
|
|
||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
routes: state.routes.map(r =>
|
routes: state.routes.map((r) =>
|
||||||
r.key === route.key ? { ...r, state: child } : r
|
r.key === route.key ? { ...r, state: child } : r
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ it('handle dispatching with ref', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -220,7 +220,7 @@ it('handle resetting state with ref', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -371,7 +371,7 @@ it('emits state events when the state changes', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
|||||||
key: String(MockRouterKey.current++),
|
key: String(MockRouterKey.current++),
|
||||||
index,
|
index,
|
||||||
routeNames,
|
routeNames,
|
||||||
routes: routeNames.map(name => ({
|
routes: routeNames.map((name) => ({
|
||||||
name,
|
name,
|
||||||
key: name,
|
key: name,
|
||||||
params: routeParamList[name],
|
params: routeParamList[name],
|
||||||
@@ -43,9 +43,9 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const routes = state.routes
|
const routes = state.routes
|
||||||
.filter(route => routeNames.includes(route.name))
|
.filter((route) => routeNames.includes(route.name))
|
||||||
.map(
|
.map(
|
||||||
route =>
|
(route) =>
|
||||||
({
|
({
|
||||||
...route,
|
...route,
|
||||||
key: route.key || `${route.name}-${MockRouterKey.current++}`,
|
key: route.key || `${route.name}-${MockRouterKey.current++}`,
|
||||||
@@ -73,7 +73,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getStateForRouteNamesChange(state, { routeNames }) {
|
getStateForRouteNamesChange(state, { routeNames }) {
|
||||||
const routes = state.routes.filter(route =>
|
const routes = state.routes.filter((route) =>
|
||||||
routeNames.includes(route.name)
|
routeNames.includes(route.name)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getStateForRouteFocus(state, key) {
|
getStateForRouteFocus(state, key) {
|
||||||
const index = state.routes.findIndex(r => r.key === key);
|
const index = state.routes.findIndex((r) => r.key === key);
|
||||||
|
|
||||||
if (index === -1 || index === state.index) {
|
if (index === -1 || index === state.index) {
|
||||||
return state;
|
return state;
|
||||||
@@ -105,7 +105,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
|||||||
|
|
||||||
case 'NAVIGATE': {
|
case 'NAVIGATE': {
|
||||||
const index = state.routes.findIndex(
|
const index = state.routes.findIndex(
|
||||||
route => route.name === action.payload.name
|
(route) => route.name === action.payload.name
|
||||||
);
|
);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ it('converts state to path string with config', () => {
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
id: (id: string) => Number(id.replace(/^x/, '')),
|
id: (id: string) => Number(id.replace(/^x/, '')),
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -128,7 +129,8 @@ it('handles state with config with nested screens', () => {
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -192,12 +194,14 @@ it('handles state with config with nested screens and unused configs', () => {
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toLowerCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
unknown: (_: unknown) => 'x',
|
unknown: (_: unknown) => 'x',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -255,11 +259,11 @@ it('handles nested object with stringify in it', () => {
|
|||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
},
|
},
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toUpperCase()),
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ it('converts path string to initial state with config', () => {
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -153,7 +154,8 @@ it('converts path string to initial state with config with nested screens', () =
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -217,7 +219,8 @@ it('converts path string to initial state with config with nested screens and un
|
|||||||
Baz: {
|
Baz: {
|
||||||
path: 'baz/:author',
|
path: 'baz/:author',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
author: (author: string) =>
|
||||||
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
id: Boolean,
|
id: Boolean,
|
||||||
@@ -277,11 +280,11 @@ it('handles nested object with unused configs and with parse in it', () => {
|
|||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
},
|
},
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toUpperCase()),
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -528,11 +531,11 @@ it('handles two initialRouteNames', () => {
|
|||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
},
|
},
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toUpperCase()),
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
@@ -610,11 +613,11 @@ it('accepts initialRouteName without config for it', () => {
|
|||||||
path: 'bis/:author',
|
path: 'bis/:author',
|
||||||
stringify: {
|
stringify: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toLowerCase()),
|
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||||
},
|
},
|
||||||
parse: {
|
parse: {
|
||||||
author: (author: string) =>
|
author: (author: string) =>
|
||||||
author.replace(/^\w/, c => c.toUpperCase()),
|
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||||
count: Number,
|
count: Number,
|
||||||
valid: Boolean,
|
valid: Boolean,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ it('sets options with screenOptions prop as an object', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{state.routes.map(route => {
|
{state.routes.map((route) => {
|
||||||
const { render, options } = descriptors[route.key];
|
const { render, options } = descriptors[route.key];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -179,7 +179,7 @@ it('sets options with screenOptions prop as a fuction', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{state.routes.map(route => {
|
{state.routes.map((route) => {
|
||||||
const { render, options } = descriptors[route.key];
|
const { render, options } = descriptors[route.key];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -273,7 +273,7 @@ it('sets initial options with setOptions', () => {
|
|||||||
<BaseNavigationContainer>
|
<BaseNavigationContainer>
|
||||||
<TestNavigator>
|
<TestNavigator>
|
||||||
<Screen name="foo" options={{ color: 'blue' }}>
|
<Screen name="foo" options={{ color: 'blue' }}>
|
||||||
{props => <TestScreen {...props} />}
|
{(props) => <TestScreen {...props} />}
|
||||||
</Screen>
|
</Screen>
|
||||||
<Screen name="bar" component={jest.fn()} />
|
<Screen name="bar" component={jest.fn()} />
|
||||||
</TestNavigator>
|
</TestNavigator>
|
||||||
@@ -338,7 +338,7 @@ it('updates options with setOptions', () => {
|
|||||||
<BaseNavigationContainer>
|
<BaseNavigationContainer>
|
||||||
<TestNavigator>
|
<TestNavigator>
|
||||||
<Screen name="foo" options={{ color: 'blue' }}>
|
<Screen name="foo" options={{ color: 'blue' }}>
|
||||||
{props => <TestScreen {...props} />}
|
{(props) => <TestScreen {...props} />}
|
||||||
</Screen>
|
</Screen>
|
||||||
<Screen name="bar" component={jest.fn()} />
|
<Screen name="bar" component={jest.fn()} />
|
||||||
</TestNavigator>
|
</TestNavigator>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ it('fires focus and blur events in root navigator', () => {
|
|||||||
|
|
||||||
React.useImperativeHandle(ref, () => navigation, [navigation]);
|
React.useImperativeHandle(ref, () => navigation, [navigation]);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
});
|
});
|
||||||
|
|
||||||
const firstFocusCallback = jest.fn();
|
const firstFocusCallback = jest.fn();
|
||||||
@@ -106,7 +106,7 @@ it('fires focus and blur events in nested navigator', () => {
|
|||||||
|
|
||||||
React.useImperativeHandle(ref, () => navigation, [navigation]);
|
React.useImperativeHandle(ref, () => navigation, [navigation]);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
});
|
});
|
||||||
|
|
||||||
const firstFocusCallback = jest.fn();
|
const firstFocusCallback = jest.fn();
|
||||||
@@ -376,7 +376,7 @@ it('fires custom events added with addListener', () => {
|
|||||||
state,
|
state,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
});
|
});
|
||||||
|
|
||||||
const firstCallback = jest.fn();
|
const firstCallback = jest.fn();
|
||||||
@@ -456,7 +456,7 @@ it("doesn't call same listener multiple times with addListener", () => {
|
|||||||
state,
|
state,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
});
|
});
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
@@ -640,7 +640,7 @@ it('has option to prevent default', () => {
|
|||||||
state,
|
state,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
});
|
});
|
||||||
|
|
||||||
const callback = (e: any) => {
|
const callback = (e: any) => {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ it('runs focus effect on focus change', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const focusEffect = jest.fn();
|
const focusEffect = jest.fn();
|
||||||
@@ -107,7 +107,7 @@ it('runs focus effect when initial state is given', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const focusEffect = jest.fn();
|
const focusEffect = jest.fn();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ it('renders correct focus state', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ it('gets navigation prop from context', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
@@ -38,7 +38,7 @@ it("gets navigation's parent from context", () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
@@ -70,7 +70,7 @@ it("gets navigation's parent's parent from context", () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { render } from 'react-native-testing-library';
|
import { render, act } from 'react-native-testing-library';
|
||||||
import useEventEmitter from '../useEventEmitter';
|
import useEventEmitter from '../useEventEmitter';
|
||||||
import useNavigationCache from '../useNavigationCache';
|
import useNavigationCache from '../useNavigationCache';
|
||||||
|
import useNavigationBuilder from '../useNavigationBuilder';
|
||||||
|
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||||
|
import Screen from '../Screen';
|
||||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||||
|
|
||||||
beforeEach(() => (MockRouterKey.current = 0));
|
beforeEach(() => (MockRouterKey.current = 0));
|
||||||
@@ -40,7 +43,7 @@ it('preserves reference for navigation objects', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (previous.current) {
|
if (previous.current) {
|
||||||
Object.keys(navigations).forEach(key => {
|
Object.keys(navigations).forEach((key) => {
|
||||||
expect(navigations[key]).toBe(previous.current[key]);
|
expect(navigations[key]).toBe(previous.current[key]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -56,3 +59,136 @@ it('preserves reference for navigation objects', () => {
|
|||||||
|
|
||||||
root.update(<Test />);
|
root.update(<Test />);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns correct value for isFocused', () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
|
};
|
||||||
|
|
||||||
|
let navigation: any;
|
||||||
|
|
||||||
|
const Test = (props: any) => {
|
||||||
|
navigation = props.navigation;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
render(
|
||||||
|
<BaseNavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="first">{() => null}</Screen>
|
||||||
|
<Screen name="second" component={Test} />
|
||||||
|
<Screen name="third">{() => null}</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(false);
|
||||||
|
|
||||||
|
act(() => navigation.navigate('second'));
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(true);
|
||||||
|
|
||||||
|
act(() => navigation.navigate('third'));
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(false);
|
||||||
|
|
||||||
|
act(() => navigation.navigate('second'));
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns correct value for isFocused after changing screens', () => {
|
||||||
|
const TestRouter = (
|
||||||
|
options: Parameters<typeof MockRouter>[0]
|
||||||
|
): ReturnType<typeof MockRouter> => {
|
||||||
|
const router = MockRouter(options);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...router,
|
||||||
|
|
||||||
|
getStateForRouteNamesChange(state, { routeNames }) {
|
||||||
|
const routes = routeNames.map(
|
||||||
|
(name) =>
|
||||||
|
state.routes.find((r) => r.name === name) || {
|
||||||
|
name,
|
||||||
|
key: name,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
routeNames,
|
||||||
|
routes,
|
||||||
|
index: routes.length - 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(TestRouter, props);
|
||||||
|
|
||||||
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
|
};
|
||||||
|
|
||||||
|
let navigation: any;
|
||||||
|
|
||||||
|
const Test = (props: any) => {
|
||||||
|
navigation = props.navigation;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const root = render(
|
||||||
|
<BaseNavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="first">{() => null}</Screen>
|
||||||
|
<Screen name="second" component={Test} />
|
||||||
|
<Screen name="third">{() => null}</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(false);
|
||||||
|
|
||||||
|
root.update(
|
||||||
|
<BaseNavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="first">{() => null}</Screen>
|
||||||
|
<Screen name="third">{() => null}</Screen>
|
||||||
|
<Screen name="second" component={Test} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(true);
|
||||||
|
|
||||||
|
root.update(
|
||||||
|
<BaseNavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="first">{() => null}</Screen>
|
||||||
|
<Screen name="third">{() => null}</Screen>
|
||||||
|
<Screen name="fourth">{() => null}</Screen>
|
||||||
|
<Screen name="second" component={Test} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(true);
|
||||||
|
|
||||||
|
root.update(
|
||||||
|
<BaseNavigationContainer>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="first">{() => null}</Screen>
|
||||||
|
<Screen name="third">{() => null}</Screen>
|
||||||
|
<Screen name="second" component={Test} />
|
||||||
|
<Screen name="fourth">{() => null}</Screen>
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(navigation.isFocused()).toBe(false);
|
||||||
|
});
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ it('gets the current navigation state', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
const state = useNavigationState(state => state);
|
const state = useNavigationState((state) => state);
|
||||||
|
|
||||||
callback(state);
|
callback(state);
|
||||||
|
|
||||||
@@ -62,13 +62,13 @@ it('gets the current navigation state with selector', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
const index = useNavigationState(state => state.index);
|
const index = useNavigationState((state) => state.index);
|
||||||
|
|
||||||
callback(index);
|
callback(index);
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ it('gets the correct value if selector changes', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
@@ -144,12 +144,12 @@ it('gets the correct value if selector changes', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const root = render(<App selector={state => state.index} />);
|
const root = render(<App selector={(state) => state.index} />);
|
||||||
|
|
||||||
expect(callback).toBeCalledTimes(1);
|
expect(callback).toBeCalledTimes(1);
|
||||||
expect(callback.mock.calls[0][0]).toBe(0);
|
expect(callback.mock.calls[0][0]).toBe(0);
|
||||||
|
|
||||||
root.update(<App selector={state => state.routes[state.index].name} />);
|
root.update(<App selector={(state) => state.routes[state.index].name} />);
|
||||||
|
|
||||||
expect(callback).toBeCalledTimes(2);
|
expect(callback).toBeCalledTimes(2);
|
||||||
expect(callback.mock.calls[1][0]).toBe('first');
|
expect(callback.mock.calls[1][0]).toBe('first');
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ it("lets children handle the action if parent didn't", () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -270,7 +270,7 @@ it("action doesn't bubble if target is specified", () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -317,7 +317,7 @@ it('logs error if no navigator handled the action', () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{state.routes.map(route => descriptors[route.key].render())}
|
{state.routes.map((route) => descriptors[route.key].render())}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ it('gets route prop from context', () => {
|
|||||||
const TestNavigator = (props: any): any => {
|
const TestNavigator = (props: any): any => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
return state.routes.map(route => descriptors[route.key].render());
|
return state.routes.map((route) => descriptors[route.key].render());
|
||||||
};
|
};
|
||||||
|
|
||||||
const Test = () => {
|
const Test = () => {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default function createNavigatorFactory<
|
|||||||
EventMap extends EventMapBase,
|
EventMap extends EventMapBase,
|
||||||
NavigatorComponent extends React.ComponentType<any>
|
NavigatorComponent extends React.ComponentType<any>
|
||||||
>(Navigator: NavigatorComponent) {
|
>(Navigator: NavigatorComponent) {
|
||||||
return function<ParamList extends ParamListBase>(): TypedNavigator<
|
return function <ParamList extends ParamListBase>(): TypedNavigator<
|
||||||
ParamList,
|
ParamList,
|
||||||
State,
|
State,
|
||||||
ScreenOptions,
|
ScreenOptions,
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export default function getPathFromState(
|
|||||||
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(/^:/, '');
|
||||||
|
|
||||||
// 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
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default function getStateFromPath(
|
|||||||
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[]).concat(
|
||||||
...Object.keys(options).map(key =>
|
...Object.keys(options).map((key) =>
|
||||||
createNormalizedConfigs(key, options, [], initialRoutes)
|
createNormalizedConfigs(key, options, [], initialRoutes)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -91,7 +91,7 @@ export default function getStateFromPath(
|
|||||||
|
|
||||||
const paramPatterns = config.pattern
|
const paramPatterns = config.pattern
|
||||||
.split('/')
|
.split('/')
|
||||||
.filter(p => p.startsWith(':'));
|
.filter((p) => p.startsWith(':'));
|
||||||
|
|
||||||
if (paramPatterns.length) {
|
if (paramPatterns.length) {
|
||||||
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
||||||
@@ -188,7 +188,7 @@ export default function getStateFromPath(
|
|||||||
const parseFunction = findParseConfigForRoute(route.name, configs);
|
const parseFunction = findParseConfigForRoute(route.name, configs);
|
||||||
|
|
||||||
if (parseFunction) {
|
if (parseFunction) {
|
||||||
Object.keys(params).forEach(name => {
|
Object.keys(params).forEach((name) => {
|
||||||
if (parseFunction[name] && typeof params[name] === 'string') {
|
if (parseFunction[name] && typeof params[name] === 'string') {
|
||||||
params[name] = parseFunction[name](params[name] as string);
|
params[name] = parseFunction[name](params[name] as string);
|
||||||
}
|
}
|
||||||
@@ -233,7 +233,7 @@ function createNormalizedConfigs(
|
|||||||
connectedRoutes: Object.keys(value.screens),
|
connectedRoutes: Object.keys(value.screens),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Object.keys(value.screens).forEach(nestedConfig => {
|
Object.keys(value.screens).forEach((nestedConfig) => {
|
||||||
const result = createNormalizedConfigs(
|
const result = createNormalizedConfigs(
|
||||||
nestedConfig,
|
nestedConfig,
|
||||||
value.screens as Options,
|
value.screens as Options,
|
||||||
|
|||||||
@@ -346,6 +346,16 @@ export type Descriptor<
|
|||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ScreenListeners<
|
||||||
|
State extends NavigationState,
|
||||||
|
EventMap extends EventMapBase
|
||||||
|
> = Partial<
|
||||||
|
{
|
||||||
|
[EventName in keyof (EventMap &
|
||||||
|
EventMapCore<State>)]: EventListenerCallback<EventMap, EventName>;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type RouteConfig<
|
export type RouteConfig<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList,
|
RouteName extends keyof ParamList,
|
||||||
@@ -371,12 +381,12 @@ export type RouteConfig<
|
|||||||
/**
|
/**
|
||||||
* Event listeners for this screen.
|
* Event listeners for this screen.
|
||||||
*/
|
*/
|
||||||
listeners?: Partial<
|
listeners?:
|
||||||
{
|
| ScreenListeners<State, EventMap>
|
||||||
[EventName in keyof (EventMap &
|
| ((props: {
|
||||||
EventMapCore<State>)]: EventListenerCallback<EventMap, EventName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
}
|
navigation: any;
|
||||||
>;
|
}) => ScreenListeners<State, EventMap>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial params object for the route.
|
* Initial params object for the route.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
|
enabled: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
reset: (state: NavigationState) => void;
|
reset: (state: NavigationState) => void;
|
||||||
state: State;
|
state: State;
|
||||||
@@ -35,10 +36,11 @@ declare global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useDevTools({ name, reset, state }: Options) {
|
export default function useDevTools({ name, reset, state, enabled }: Options) {
|
||||||
const devToolsRef = React.useRef<DevTools>();
|
const devToolsRef = React.useRef<DevTools>();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
enabled &&
|
||||||
process.env.NODE_ENV !== 'production' &&
|
process.env.NODE_ENV !== 'production' &&
|
||||||
global.__REDUX_DEVTOOLS_EXTENSION__ &&
|
global.__REDUX_DEVTOOLS_EXTENSION__ &&
|
||||||
devToolsRef.current === undefined
|
devToolsRef.current === undefined
|
||||||
@@ -56,7 +58,7 @@ export default function useDevTools({ name, reset, state }: Options) {
|
|||||||
|
|
||||||
React.useEffect(
|
React.useEffect(
|
||||||
() =>
|
() =>
|
||||||
devTools?.subscribe(message => {
|
devTools?.subscribe((message) => {
|
||||||
if (message.type === 'DISPATCH' && message.state) {
|
if (message.type === 'DISPATCH' && message.state) {
|
||||||
reset(JSON.parse(message.state));
|
reset(JSON.parse(message.state));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default function useEventEmitter(
|
|||||||
target !== undefined
|
target !== undefined
|
||||||
? items[target] && items[target].slice()
|
? items[target] && items[target].slice()
|
||||||
: ([] as Listeners)
|
: ([] as Listeners)
|
||||||
.concat(...Object.keys(items).map(t => items[t]))
|
.concat(...Object.keys(items).map((t) => items[t]))
|
||||||
.filter((cb, i, self) => self.lastIndexOf(cb) === i);
|
.filter((cb, i, self) => self.lastIndexOf(cb) === i);
|
||||||
|
|
||||||
const event: EventArg<any, any, any> = {
|
const event: EventArg<any, any, any> = {
|
||||||
@@ -117,7 +117,7 @@ export default function useEventEmitter(
|
|||||||
|
|
||||||
listenRef.current?.(event);
|
listenRef.current?.(event);
|
||||||
|
|
||||||
callbacks?.forEach(cb => cb(event));
|
callbacks?.forEach((cb) => cb(event));
|
||||||
|
|
||||||
return event as any;
|
return event as any;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
RouterFactory,
|
RouterFactory,
|
||||||
PartialState,
|
PartialState,
|
||||||
NavigationAction,
|
NavigationAction,
|
||||||
|
Route,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
import { NavigationStateContext } from './BaseNavigationContainer';
|
||||||
import NavigationRouteContext from './NavigationRouteContext';
|
import NavigationRouteContext from './NavigationRouteContext';
|
||||||
@@ -103,7 +104,7 @@ const getRouteConfigsFromChildren = <
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
configs.forEach(config => {
|
configs.forEach((config) => {
|
||||||
const { name, children, component } = config as any;
|
const { name, children, component } = config as any;
|
||||||
|
|
||||||
if (typeof name !== 'string' || !name) {
|
if (typeof name !== 'string' || !name) {
|
||||||
@@ -212,7 +213,7 @@ export default function useNavigationBuilder<
|
|||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const routeNames = routeConfigs.map(config => config.name);
|
const routeNames = routeConfigs.map((config) => config.name);
|
||||||
const routeParamList = routeNames.reduce<Record<string, object | undefined>>(
|
const routeParamList = routeNames.reduce<Record<string, object | undefined>>(
|
||||||
(acc, curr) => {
|
(acc, curr) => {
|
||||||
const { initialParams } = screens[curr];
|
const { initialParams } = screens[curr];
|
||||||
@@ -241,12 +242,12 @@ export default function useNavigationBuilder<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isStateValid = React.useCallback(
|
const isStateValid = React.useCallback(
|
||||||
state => state.type === undefined || state.type === router.type,
|
(state) => state.type === undefined || state.type === router.type,
|
||||||
[router.type]
|
[router.type]
|
||||||
);
|
);
|
||||||
|
|
||||||
const isStateInitialized = React.useCallback(
|
const isStateInitialized = React.useCallback(
|
||||||
state =>
|
(state) =>
|
||||||
state !== undefined && state.stale === false && isStateValid(state),
|
state !== undefined && state.stale === false && isStateValid(state),
|
||||||
[isStateValid]
|
[isStateValid]
|
||||||
);
|
);
|
||||||
@@ -367,14 +368,16 @@ export default function useNavigationBuilder<
|
|||||||
: (initializedStateRef.current as State);
|
: (initializedStateRef.current as State);
|
||||||
}, [getCurrentState, isStateInitialized]);
|
}, [getCurrentState, isStateInitialized]);
|
||||||
|
|
||||||
const emitter = useEventEmitter(e => {
|
const emitter = useEventEmitter((e) => {
|
||||||
let routeNames = [];
|
let routeNames = [];
|
||||||
|
|
||||||
if (e.target) {
|
let target: Route<string> | undefined;
|
||||||
const name = state.routes.find(route => route.key === e.target)?.name;
|
|
||||||
|
|
||||||
if (name) {
|
if (e.target) {
|
||||||
routeNames.push(name);
|
target = state.routes.find((route) => route.key === e.target);
|
||||||
|
|
||||||
|
if (target?.name) {
|
||||||
|
routeNames.push(target.name);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
routeNames.push(...Object.keys(screens));
|
routeNames.push(...Object.keys(screens));
|
||||||
@@ -382,19 +385,28 @@ export default function useNavigationBuilder<
|
|||||||
|
|
||||||
const listeners = ([] as (((e: any) => void) | undefined)[])
|
const listeners = ([] as (((e: any) => void) | undefined)[])
|
||||||
.concat(
|
.concat(
|
||||||
...routeNames.map(name => {
|
...routeNames.map((name) => {
|
||||||
const { listeners } = screens[name];
|
const { listeners } = screens[name];
|
||||||
|
|
||||||
return listeners
|
return listeners
|
||||||
? Object.keys(listeners)
|
? Object.keys(listeners)
|
||||||
.filter(type => type === e.type)
|
.filter((type) => type === e.type)
|
||||||
.map(type => listeners[type])
|
.map((type) => {
|
||||||
|
if (typeof listeners === 'function') {
|
||||||
|
const route = target ?? state.routes[state.index];
|
||||||
|
const navigation = descriptors[route.key].navigation;
|
||||||
|
|
||||||
|
return listeners({ route: route as any, navigation })[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
return listeners[type];
|
||||||
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
|
.filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
|
||||||
|
|
||||||
listeners.forEach(listener => listener?.(e));
|
listeners.forEach((listener) => listener?.(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
useFocusEvents({ state, emitter });
|
useFocusEvents({ state, emitter });
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export default function useNavigationCache<
|
|||||||
};
|
};
|
||||||
|
|
||||||
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
|
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
|
||||||
(acc, route, index) => {
|
(acc, route) => {
|
||||||
const previous = cache.current[route.key];
|
const previous = cache.current[route.key];
|
||||||
|
|
||||||
if (previous) {
|
if (previous) {
|
||||||
@@ -103,14 +103,14 @@ export default function useNavigationCache<
|
|||||||
dangerouslyGetState: getState,
|
dangerouslyGetState: getState,
|
||||||
dispatch,
|
dispatch,
|
||||||
setOptions: (options: object) =>
|
setOptions: (options: object) =>
|
||||||
setOptions(o => ({
|
setOptions((o) => ({
|
||||||
...o,
|
...o,
|
||||||
[route.key]: { ...o[route.key], ...options },
|
[route.key]: { ...o[route.key], ...options },
|
||||||
})),
|
})),
|
||||||
isFocused: () => {
|
isFocused: () => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
||||||
if (index !== state.index) {
|
if (state.routes[state.index].key !== route.key) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function useNavigationState<T>(selector: Selector<T>): T {
|
|||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const unsubscribe = navigation.addListener('state', e => {
|
const unsubscribe = navigation.addListener('state', (e) => {
|
||||||
setResult(selectorRef.current(e.data.state));
|
setResult(selectorRef.current(e.data.state));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ export default function useOnGetState({
|
|||||||
const state = getState();
|
const state = getState();
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
routes: state.routes.map(route => ({
|
routes: state.routes.map((route) => ({
|
||||||
...route,
|
...route,
|
||||||
state: getStateForRoute(route.key),
|
state: getStateForRoute(route.key),
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.2...@react-navigation/drawer@5.3.3) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.1...@react-navigation/drawer@5.3.2) (2020-03-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* close drawer on pressing Esc on web ([5c4afc5](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/5c4afc5cb40c1206a9d8c40efe3cf947030da48e)), closes [#6745](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/6745)
|
||||||
|
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7485)
|
||||||
|
* fix permanent sidebar position ([#7830](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7830)) ([3ea8eec](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/3ea8eec4324ea82f0ed427f4662e68e1115e60ab))
|
||||||
|
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/6789)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.0...@react-navigation/drawer@5.3.1) (2020-03-17)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.2.0...@react-navigation/drawer@5.3.0) (2020-03-17)
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.2.0...@react-navigation/drawer@5.3.0) (2020-03-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.3.0",
|
"version": "5.3.3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.61.22",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
|
|||||||
@@ -1,44 +1,16 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useNavigation, ParamListBase } from '@react-navigation/native';
|
import DrawerOpenContext from './DrawerOpenContext';
|
||||||
import { DrawerNavigationProp } from '../types';
|
|
||||||
import DrawerOpenContext from '../views/DrawerOpenContext';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook to detect if the drawer is open in a parent navigator.
|
* Hook to detect if the drawer is open in a parent navigator.
|
||||||
*/
|
*/
|
||||||
export default function useIsDrawerOpen() {
|
export default function useIsDrawerOpen() {
|
||||||
const navigation = useNavigation();
|
const isDrawerOpen = React.useContext(DrawerOpenContext);
|
||||||
|
|
||||||
let drawer = navigation as DrawerNavigationProp<ParamListBase>;
|
if (typeof isDrawerOpen !== 'boolean') {
|
||||||
|
throw new Error(
|
||||||
const drawerOpenContext = React.useContext(DrawerOpenContext);
|
"Couldn't find a drawer. Is your component inside a drawer navigator?"
|
||||||
|
);
|
||||||
// The screen might be inside another navigator such as stack nested in drawer
|
|
||||||
// We need to find the closest drawer navigator and add the listener there
|
|
||||||
while (drawer && drawer.dangerouslyGetState().type !== 'drawer') {
|
|
||||||
drawer = drawer.dangerouslyGetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
const [isDrawerOpen, setIsDrawerOpen] = React.useState(() =>
|
|
||||||
drawer
|
|
||||||
? Boolean(
|
|
||||||
drawer.dangerouslyGetState().history.find(it => it.type === 'drawer')
|
|
||||||
)
|
|
||||||
: false
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const unsubscribe = drawer.addListener('state', e => {
|
|
||||||
setIsDrawerOpen(
|
|
||||||
Boolean(e.data.state.history.find(it => it.type === 'drawer'))
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return unsubscribe;
|
|
||||||
}, [drawer, isDrawerOpen]);
|
|
||||||
|
|
||||||
if (drawerOpenContext !== null) {
|
|
||||||
return drawerOpenContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return isDrawerOpen;
|
return isDrawerOpen;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import {
|
|||||||
} from 'react-native-gesture-handler';
|
} from 'react-native-gesture-handler';
|
||||||
import Animated from 'react-native-reanimated';
|
import Animated from 'react-native-reanimated';
|
||||||
import Overlay from './Overlay';
|
import Overlay from './Overlay';
|
||||||
import DrawerOpenContext from './DrawerOpenContext';
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Clock,
|
Clock,
|
||||||
@@ -128,6 +127,12 @@ export default class DrawerView extends React.PureComponent<Props> {
|
|||||||
statusBarAnimation: 'slide',
|
statusBarAnimation: 'slide',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (Platform.OS === 'web') {
|
||||||
|
document?.body?.addEventListener?.('keyup', this.handleEscape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps: Props) {
|
componentDidUpdate(prevProps: Props) {
|
||||||
const {
|
const {
|
||||||
open,
|
open,
|
||||||
@@ -183,8 +188,22 @@ export default class DrawerView extends React.PureComponent<Props> {
|
|||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
this.toggleStatusBar(false);
|
this.toggleStatusBar(false);
|
||||||
this.handleEndInteraction();
|
this.handleEndInteraction();
|
||||||
|
|
||||||
|
if (Platform.OS === 'web') {
|
||||||
|
document?.body?.removeEventListener?.('keyup', this.handleEscape);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleEscape = (e: KeyboardEvent) => {
|
||||||
|
const { open, onClose } = this.props;
|
||||||
|
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
if (open) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private handleEndInteraction = () => {
|
private handleEndInteraction = () => {
|
||||||
if (this.interactionHandle !== undefined) {
|
if (this.interactionHandle !== undefined) {
|
||||||
InteractionManager.clearInteractionHandle(this.interactionHandle);
|
InteractionManager.clearInteractionHandle(this.interactionHandle);
|
||||||
@@ -593,8 +612,9 @@ export default class DrawerView extends React.PureComponent<Props> {
|
|||||||
onLayout={this.handleContainerLayout}
|
onLayout={this.handleContainerLayout}
|
||||||
style={[
|
style={[
|
||||||
styles.main,
|
styles.main,
|
||||||
drawerType === 'permanent' && {
|
{
|
||||||
flexDirection: 'row-reverse',
|
flexDirection:
|
||||||
|
drawerType === 'permanent' && !isRight ? 'row-reverse' : 'row',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@@ -661,9 +681,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
|||||||
drawerStyle as any,
|
drawerStyle as any,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<DrawerOpenContext.Provider value={isOpen}>
|
{renderDrawerContent({ progress })}
|
||||||
{renderDrawerContent({ progress })}
|
|
||||||
</DrawerOpenContext.Provider>
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</PanGestureHandler>
|
</PanGestureHandler>
|
||||||
|
|||||||
@@ -72,14 +72,8 @@ export default function DrawerItem(props: Props) {
|
|||||||
labelStyle,
|
labelStyle,
|
||||||
focused = false,
|
focused = false,
|
||||||
activeTintColor = colors.primary,
|
activeTintColor = colors.primary,
|
||||||
inactiveTintColor = Color(colors.text)
|
inactiveTintColor = Color(colors.text).alpha(0.68).rgb().string(),
|
||||||
.alpha(0.68)
|
activeBackgroundColor = Color(activeTintColor).alpha(0.12).rgb().string(),
|
||||||
.rgb()
|
|
||||||
.string(),
|
|
||||||
activeBackgroundColor = Color(activeTintColor)
|
|
||||||
.alpha(0.12)
|
|
||||||
.rgb()
|
|
||||||
.string(),
|
|
||||||
inactiveBackgroundColor = 'transparent',
|
inactiveBackgroundColor = 'transparent',
|
||||||
style,
|
style,
|
||||||
onPress,
|
onPress,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import {
|
|||||||
DrawerNavigationHelpers,
|
DrawerNavigationHelpers,
|
||||||
DrawerContentComponentProps,
|
DrawerContentComponentProps,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
import DrawerOpenContext from '../utils/DrawerOpenContext';
|
||||||
import DrawerPositionContext from '../utils/DrawerPositionContext';
|
import DrawerPositionContext from '../utils/DrawerPositionContext';
|
||||||
|
|
||||||
type Props = DrawerNavigationConfig & {
|
type Props = DrawerNavigationConfig & {
|
||||||
@@ -88,15 +89,17 @@ export default function DrawerView({
|
|||||||
sceneContainerStyle,
|
sceneContainerStyle,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const [loaded, setLoaded] = React.useState([state.index]);
|
const [loaded, setLoaded] = React.useState([state.index]);
|
||||||
const [drawerWidth, setDrawerWidth] = React.useState(() =>
|
const [drawerWidth, setDrawerWidth] = React.useState(() => {
|
||||||
getDefaultDrawerWidth(Dimensions.get('window'))
|
const { height = 0, width = 0 } = Dimensions.get('window');
|
||||||
);
|
|
||||||
|
return getDefaultDrawerWidth({ height, width });
|
||||||
|
});
|
||||||
|
|
||||||
const drawerGestureRef = React.useRef<PanGestureHandler>(null);
|
const drawerGestureRef = React.useRef<PanGestureHandler>(null);
|
||||||
|
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
const isDrawerOpen = Boolean(state.history.find(it => it.type === 'drawer'));
|
const isDrawerOpen = state.history.some((it) => it.type === 'drawer');
|
||||||
|
|
||||||
const handleDrawerOpen = React.useCallback(() => {
|
const handleDrawerOpen = React.useCallback(() => {
|
||||||
navigation.dispatch({
|
navigation.dispatch({
|
||||||
@@ -203,40 +206,48 @@ export default function DrawerView({
|
|||||||
<GestureHandlerWrapper style={styles.content}>
|
<GestureHandlerWrapper style={styles.content}>
|
||||||
<SafeAreaProviderCompat>
|
<SafeAreaProviderCompat>
|
||||||
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
||||||
<Drawer
|
<DrawerOpenContext.Provider value={isDrawerOpen}>
|
||||||
open={isDrawerOpen}
|
<Drawer
|
||||||
gestureEnabled={gestureEnabled}
|
open={isDrawerOpen}
|
||||||
onOpen={handleDrawerOpen}
|
gestureEnabled={gestureEnabled}
|
||||||
onClose={handleDrawerClose}
|
onOpen={handleDrawerOpen}
|
||||||
onGestureRef={ref => {
|
onClose={handleDrawerClose}
|
||||||
// @ts-ignore
|
onGestureRef={(ref) => {
|
||||||
drawerGestureRef.current = ref;
|
// @ts-ignore
|
||||||
}}
|
drawerGestureRef.current = ref;
|
||||||
gestureHandlerProps={gestureHandlerProps}
|
}}
|
||||||
drawerType={drawerType}
|
gestureHandlerProps={gestureHandlerProps}
|
||||||
drawerPosition={drawerPosition}
|
drawerType={drawerType}
|
||||||
sceneContainerStyle={[
|
drawerPosition={drawerPosition}
|
||||||
{ backgroundColor: colors.background },
|
sceneContainerStyle={[
|
||||||
sceneContainerStyle,
|
{ backgroundColor: colors.background },
|
||||||
]}
|
sceneContainerStyle,
|
||||||
drawerStyle={[
|
]}
|
||||||
{ width: drawerWidth, backgroundColor: colors.card },
|
drawerStyle={[
|
||||||
drawerType === 'permanent' && {
|
{ width: drawerWidth, backgroundColor: colors.card },
|
||||||
borderRightColor: colors.border,
|
drawerType === 'permanent' &&
|
||||||
borderRightWidth: StyleSheet.hairlineWidth,
|
(drawerPosition === 'left'
|
||||||
},
|
? {
|
||||||
drawerStyle,
|
borderRightColor: colors.border,
|
||||||
]}
|
borderRightWidth: StyleSheet.hairlineWidth,
|
||||||
overlayStyle={{ backgroundColor: overlayColor }}
|
}
|
||||||
swipeEdgeWidth={edgeWidth}
|
: {
|
||||||
swipeDistanceThreshold={minSwipeDistance}
|
borderLeftColor: colors.border,
|
||||||
hideStatusBar={hideStatusBar}
|
borderLeftWidth: StyleSheet.hairlineWidth,
|
||||||
statusBarAnimation={statusBarAnimation}
|
}),
|
||||||
renderDrawerContent={renderNavigationView}
|
drawerStyle,
|
||||||
renderSceneContent={renderContent}
|
]}
|
||||||
keyboardDismissMode={keyboardDismissMode}
|
overlayStyle={{ backgroundColor: overlayColor }}
|
||||||
drawerPostion={drawerPosition}
|
swipeEdgeWidth={edgeWidth}
|
||||||
/>
|
swipeDistanceThreshold={minSwipeDistance}
|
||||||
|
hideStatusBar={hideStatusBar}
|
||||||
|
statusBarAnimation={statusBarAnimation}
|
||||||
|
renderDrawerContent={renderNavigationView}
|
||||||
|
renderSceneContent={renderContent}
|
||||||
|
keyboardDismissMode={keyboardDismissMode}
|
||||||
|
drawerPostion={drawerPosition}
|
||||||
|
/>
|
||||||
|
</DrawerOpenContext.Provider>
|
||||||
</DrawerGestureContext.Provider>
|
</DrawerGestureContext.Provider>
|
||||||
</SafeAreaProviderCompat>
|
</SafeAreaProviderCompat>
|
||||||
</GestureHandlerWrapper>
|
</GestureHandlerWrapper>
|
||||||
|
|||||||
@@ -9,21 +9,29 @@ type Props = {
|
|||||||
style?: any;
|
style?: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container
|
const FAR_FAR_AWAY = 30000; // this should be big enough to move the whole view out of its container
|
||||||
|
|
||||||
export default class ResourceSavingScene extends React.Component<Props> {
|
export default class ResourceSavingScene extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
if (screensEnabled?.()) {
|
// react-native-screens is buggy on web
|
||||||
|
if (screensEnabled?.() && Platform.OS !== 'web') {
|
||||||
const { isVisible, ...rest } = this.props;
|
const { isVisible, ...rest } = this.props;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return <Screen active={isVisible ? 1 : 0} {...rest} />;
|
return <Screen active={isVisible ? 1 : 0} {...rest} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { isVisible, children, style, ...rest } = this.props;
|
const { isVisible, children, style, ...rest } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[styles.container, style]}
|
style={[
|
||||||
|
styles.container,
|
||||||
|
Platform.OS === 'web'
|
||||||
|
? { display: isVisible ? 'flex' : 'none' }
|
||||||
|
: null,
|
||||||
|
style,
|
||||||
|
]}
|
||||||
collapsable={false}
|
collapsable={false}
|
||||||
removeClippedSubviews={
|
removeClippedSubviews={
|
||||||
// On iOS, set removeClippedSubviews to true only when not focused
|
// On iOS, set removeClippedSubviews to true only when not focused
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type Props = {
|
|||||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||||
return (
|
return (
|
||||||
<SafeAreaConsumer>
|
<SafeAreaConsumer>
|
||||||
{insets => {
|
{(insets) => {
|
||||||
if (insets) {
|
if (insets) {
|
||||||
// If we already have insets, don't wrap the stack in another safe area provider
|
// If we already have insets, don't wrap the stack in another safe area provider
|
||||||
// This avoids an issue with updates at the cost of potentially incorrect values
|
// This avoids an issue with updates at the cost of potentially incorrect values
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.4...@react-navigation/material-bottom-tabs@5.1.5) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.3...@react-navigation/material-bottom-tabs@5.1.4) (2020-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.2...@react-navigation/material-bottom-tabs@5.1.3) (2020-03-17)
|
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.2...@react-navigation/material-bottom-tabs@5.1.3) (2020-03-17)
|
||||||
|
|
||||||
**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.3",
|
"version": "5.1.5",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.61.22",
|
||||||
"@types/react-native-vector-icons": "^6.4.5",
|
"@types/react-native-vector-icons": "^6.4.5",
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.4...@react-navigation/material-top-tabs@5.1.5) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.3...@react-navigation/material-top-tabs@5.1.4) (2020-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.2...@react-navigation/material-top-tabs@5.1.3) (2020-03-17)
|
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.2...@react-navigation/material-top-tabs@5.1.3) (2020-03-17)
|
||||||
|
|
||||||
**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.3",
|
"version": "5.1.5",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.61.22",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
|
|||||||
@@ -14,17 +14,11 @@ export default function TabBarTop(props: MaterialTopTabBarProps) {
|
|||||||
navigation,
|
navigation,
|
||||||
descriptors,
|
descriptors,
|
||||||
activeTintColor = colors.text,
|
activeTintColor = colors.text,
|
||||||
inactiveTintColor = Color(activeTintColor)
|
inactiveTintColor = Color(activeTintColor).alpha(0.5).rgb().string(),
|
||||||
.alpha(0.5)
|
|
||||||
.rgb()
|
|
||||||
.string(),
|
|
||||||
allowFontScaling = true,
|
allowFontScaling = true,
|
||||||
showIcon = false,
|
showIcon = false,
|
||||||
showLabel = true,
|
showLabel = true,
|
||||||
pressColor = Color(activeTintColor)
|
pressColor = Color(activeTintColor).alpha(0.08).rgb().string(),
|
||||||
.alpha(0.08)
|
|
||||||
.rgb()
|
|
||||||
.string(),
|
|
||||||
iconStyle,
|
iconStyle,
|
||||||
labelStyle,
|
labelStyle,
|
||||||
indicatorStyle,
|
indicatorStyle,
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export default function MaterialTopTabView({
|
|||||||
return (
|
return (
|
||||||
<TabView
|
<TabView
|
||||||
{...rest}
|
{...rest}
|
||||||
onIndexChange={index =>
|
onIndexChange={(index) =>
|
||||||
navigation.dispatch({
|
navigation.dispatch({
|
||||||
...TabActions.jumpTo(state.routes[index].name),
|
...TabActions.jumpTo(state.routes[index].name),
|
||||||
target: state.key,
|
target: state.key,
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.2](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.1...@react-navigation/native@5.1.2) (2020-03-22)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.0...@react-navigation/native@5.1.1) (2020-03-19)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.10...@react-navigation/native@5.1.0) (2020-03-17)
|
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.10...@react-navigation/native@5.1.0) (2020-03-17)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.1.0",
|
"version": "5.1.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation",
|
"react-navigation",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^5.2.2"
|
"@react-navigation/core": "^5.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default function() {
|
export default function () {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"'NavigationNativeContainer' has been renamed to 'NavigationContainer"
|
"'NavigationNativeContainer' has been renamed to 'NavigationContainer"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.1.1...@react-navigation/routers@5.2.0) (2020-03-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add keys to routes missing keys during reset ([813a590](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/813a5903b5f44506b9097538ed85229e565b855e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.1.0...@react-navigation/routers@5.1.1) (2020-03-16)
|
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.1.0...@react-navigation/routers@5.1.1) (2020-03-16)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.1.1",
|
"version": "5.2.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import shortid from 'shortid';
|
||||||
import { CommonNavigationAction, NavigationState, PartialState } from './types';
|
import { CommonNavigationAction, NavigationState, PartialState } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,7 +13,7 @@ const BaseRouter = {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SET_PARAMS': {
|
case 'SET_PARAMS': {
|
||||||
const index = action.source
|
const index = action.source
|
||||||
? state.routes.findIndex(r => r.key === action.source)
|
? state.routes.findIndex((r) => r.key === action.source)
|
||||||
: state.index;
|
: state.index;
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
@@ -32,15 +33,6 @@ const BaseRouter = {
|
|||||||
case 'RESET': {
|
case 'RESET': {
|
||||||
const nextState = action.payload as State | PartialState<State>;
|
const nextState = action.payload as State | PartialState<State>;
|
||||||
|
|
||||||
if (nextState.stale === false) {
|
|
||||||
if (
|
|
||||||
state.routeNames.length !== nextState.routeNames.length ||
|
|
||||||
nextState.routeNames.some(name => !state.routeNames.includes(name))
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
nextState.routes.length === 0 ||
|
nextState.routes.length === 0 ||
|
||||||
nextState.routes.some(
|
nextState.routes.some(
|
||||||
@@ -50,6 +42,26 @@ const BaseRouter = {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nextState.stale === false) {
|
||||||
|
if (
|
||||||
|
state.routeNames.length !== nextState.routeNames.length ||
|
||||||
|
nextState.routeNames.some(
|
||||||
|
(name) => !state.routeNames.includes(name)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...nextState,
|
||||||
|
routes: nextState.routes.map((route) =>
|
||||||
|
route.key
|
||||||
|
? route
|
||||||
|
: { ...route, key: `${route.name}-${shortid()}` }
|
||||||
|
),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return nextState;
|
return nextState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export const DrawerActions = {
|
|||||||
|
|
||||||
const isDrawerOpen = (
|
const isDrawerOpen = (
|
||||||
state: DrawerNavigationState | PartialState<DrawerNavigationState>
|
state: DrawerNavigationState | PartialState<DrawerNavigationState>
|
||||||
) => Boolean(state.history?.find(it => it.type === 'drawer'));
|
) => Boolean(state.history?.find((it) => it.type === 'drawer'));
|
||||||
|
|
||||||
const openDrawer = (state: DrawerNavigationState): DrawerNavigationState => {
|
const openDrawer = (state: DrawerNavigationState): DrawerNavigationState => {
|
||||||
if (isDrawerOpen(state)) {
|
if (isDrawerOpen(state)) {
|
||||||
@@ -91,7 +91,7 @@ const closeDrawer = (state: DrawerNavigationState): DrawerNavigationState => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
history: state.history.filter(it => it.type !== 'drawer'),
|
history: state.history.filter((it) => it.type !== 'drawer'),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -134,9 +134,9 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const routes = state.routes
|
const routes = state.routes
|
||||||
.filter(route => routeNames.includes(route.name))
|
.filter((route) => routeNames.includes(route.name))
|
||||||
.map(
|
.map(
|
||||||
route =>
|
(route) =>
|
||||||
({
|
({
|
||||||
...route,
|
...route,
|
||||||
key: route.key || `${route.name}-${shortid()}`,
|
key: route.key || `${route.name}-${shortid()}`,
|
||||||
@@ -174,7 +174,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
||||||
const routes = state.routes.filter(route =>
|
const routes = state.routes.filter((route) =>
|
||||||
routeNames.includes(route.name)
|
routeNames.includes(route.name)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getStateForRouteFocus(state, key) {
|
getStateForRouteFocus(state, key) {
|
||||||
const index = state.routes.findIndex(r => r.key === key);
|
const index = state.routes.findIndex((r) => r.key === key);
|
||||||
|
|
||||||
if (index === -1 || index === state.index) {
|
if (index === -1 || index === state.index) {
|
||||||
return state;
|
return state;
|
||||||
@@ -220,7 +220,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'REPLACE': {
|
case 'REPLACE': {
|
||||||
const index = action.source
|
const index = action.source
|
||||||
? state.routes.findIndex(r => r.key === action.source)
|
? state.routes.findIndex((r) => r.key === action.source)
|
||||||
: state.index;
|
: state.index;
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
@@ -283,7 +283,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
|||||||
case 'POP': {
|
case 'POP': {
|
||||||
const index =
|
const index =
|
||||||
action.target === state.key && action.source
|
action.target === state.key && action.source
|
||||||
? state.routes.findIndex(r => r.key === action.source)
|
? state.routes.findIndex((r) => r.key === action.source)
|
||||||
: state.index;
|
: state.index;
|
||||||
|
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ const changeIndex = (
|
|||||||
const currentKey = state.routes[index].key;
|
const currentKey = state.routes[index].key;
|
||||||
|
|
||||||
history = state.history
|
history = state.history
|
||||||
.filter(it => (it.type === 'route' ? it.key !== currentKey : false))
|
.filter((it) => (it.type === 'route' ? it.key !== currentKey : false))
|
||||||
.concat({ type: TYPE_ROUTE, key: currentKey });
|
.concat({ type: TYPE_ROUTE, key: currentKey });
|
||||||
} else {
|
} else {
|
||||||
history = getRouteHistory(state.routes, index, backBehavior);
|
history = getRouteHistory(state.routes, index, backBehavior);
|
||||||
@@ -124,7 +124,7 @@ export default function TabRouter({
|
|||||||
? routeNames.indexOf(initialRouteName)
|
? routeNames.indexOf(initialRouteName)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
const routes = routeNames.map(name => ({
|
const routes = routeNames.map((name) => ({
|
||||||
name,
|
name,
|
||||||
key: `${name}-${shortid()}`,
|
key: `${name}-${shortid()}`,
|
||||||
params: routeParamList[name],
|
params: routeParamList[name],
|
||||||
@@ -150,9 +150,9 @@ export default function TabRouter({
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
const routes = routeNames.map(name => {
|
const routes = routeNames.map((name) => {
|
||||||
const route = (state as PartialState<TabNavigationState>).routes.find(
|
const route = (state as PartialState<TabNavigationState>).routes.find(
|
||||||
r => r.name === name
|
(r) => r.name === name
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -184,8 +184,8 @@ export default function TabRouter({
|
|||||||
routes.length - 1
|
routes.length - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
let history = state.history?.filter(it =>
|
let history = state.history?.filter((it) =>
|
||||||
routes.find(r => r.key === it.key)
|
routes.find((r) => r.key === it.key)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!history?.length) {
|
if (!history?.length) {
|
||||||
@@ -205,8 +205,8 @@ export default function TabRouter({
|
|||||||
|
|
||||||
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
||||||
const routes = routeNames.map(
|
const routes = routeNames.map(
|
||||||
name =>
|
(name) =>
|
||||||
state.routes.find(r => r.name === name) || {
|
state.routes.find((r) => r.name === name) || {
|
||||||
name,
|
name,
|
||||||
key: `${name}-${shortid()}`,
|
key: `${name}-${shortid()}`,
|
||||||
params: routeParamList[name],
|
params: routeParamList[name],
|
||||||
@@ -218,8 +218,8 @@ export default function TabRouter({
|
|||||||
routeNames.indexOf(state.routes[state.index].name)
|
routeNames.indexOf(state.routes[state.index].name)
|
||||||
);
|
);
|
||||||
|
|
||||||
let history = state.history.filter(it =>
|
let history = state.history.filter((it) =>
|
||||||
routes.find(r => r.key === it.key)
|
routes.find((r) => r.key === it.key)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!history.length) {
|
if (!history.length) {
|
||||||
@@ -236,7 +236,7 @@ export default function TabRouter({
|
|||||||
},
|
},
|
||||||
|
|
||||||
getStateForRouteFocus(state, key) {
|
getStateForRouteFocus(state, key) {
|
||||||
const index = state.routes.findIndex(r => r.key === key);
|
const index = state.routes.findIndex((r) => r.key === key);
|
||||||
|
|
||||||
if (index === -1 || index === state.index) {
|
if (index === -1 || index === state.index) {
|
||||||
return state;
|
return state;
|
||||||
@@ -253,11 +253,11 @@ export default function TabRouter({
|
|||||||
|
|
||||||
if (action.type === 'NAVIGATE' && action.payload.key) {
|
if (action.type === 'NAVIGATE' && action.payload.key) {
|
||||||
index = state.routes.findIndex(
|
index = state.routes.findIndex(
|
||||||
route => route.key === action.payload.key
|
(route) => route.key === action.payload.key
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
index = state.routes.findIndex(
|
index = state.routes.findIndex(
|
||||||
route => route.name === action.payload.name
|
(route) => route.name === action.payload.name
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ export default function TabRouter({
|
|||||||
|
|
||||||
const previousKey = state.history[state.history.length - 2].key;
|
const previousKey = state.history[state.history.length - 2].key;
|
||||||
const index = state.routes.findIndex(
|
const index = state.routes.findIndex(
|
||||||
route => route.key === previousKey
|
(route) => route.key === previousKey
|
||||||
);
|
);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
|
|||||||
@@ -84,6 +84,22 @@ it('resets state to new state with RESET', () => {
|
|||||||
expect(result).toEqual({ index: 0, routes });
|
expect(result).toEqual({ index: 0, routes });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('adds keys to routes missing keys during RESET', () => {
|
||||||
|
const result = BaseRouter.getStateForAction(
|
||||||
|
STATE,
|
||||||
|
// @ts-ignore
|
||||||
|
CommonActions.reset({
|
||||||
|
...STATE,
|
||||||
|
routes: [...STATE.routes, { name: 'qux' }],
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
...STATE,
|
||||||
|
routes: [...STATE.routes, { key: 'qux-test', name: 'qux' }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("doesn't handle RESET if routes don't match routeNames", () => {
|
it("doesn't handle RESET if routes don't match routeNames", () => {
|
||||||
const routes = [
|
const routes = [
|
||||||
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||||
|
|||||||
@@ -3,6 +3,43 @@
|
|||||||
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.4](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.3...@react-navigation/stack@5.2.4) (2020-03-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix swipe not dismissing card in RTL ([043924c](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/043924ca4843b6f02626532cbf4aafc7cad9fab1)), closes [#7841](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7841)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.2...@react-navigation/stack@5.2.3) (2020-03-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use the correct velocity value in closing animation ([#7836](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7836)) ([adbfedc](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/adbfedcd58d4e3d358c6c9691710bb8e4e0d8afb))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.1...@react-navigation/stack@5.2.2) (2020-03-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7485)
|
||||||
|
* fix blank page if stack was inside display: none before ([49f6fed](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/49f6fed6d3da878e02a9fe9115c05bcf84e332bf))
|
||||||
|
* fix closing stack using inverted gesture. ([#7824](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7824)) ([f24d3a3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/f24d3a3461ee8a566c25ce7d13f31035b4be2691))
|
||||||
|
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/6789)
|
||||||
|
* only dismiss previously focused input on page change. closes [#6918](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/6918) ([b1fe730](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/b1fe73097f3ad58d3ba4a8a9b875276d1d8d220c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.0...@react-navigation/stack@5.2.1) (2020-03-17)
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.0...@react-navigation/stack@5.2.1) (2020-03-17)
|
||||||
|
|
||||||
**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.1",
|
"version": "5.2.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.10.0",
|
||||||
"@react-native-community/masked-view": "^0.1.7",
|
"@react-native-community/masked-view": "^0.1.7",
|
||||||
"@react-navigation/native": "^5.1.0",
|
"@react-navigation/native": "^5.1.2",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.23",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.61.22",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ function StackNavigator({
|
|||||||
React.useEffect(
|
React.useEffect(
|
||||||
() =>
|
() =>
|
||||||
navigation.addListener &&
|
navigation.addListener &&
|
||||||
navigation.addListener('tabPress', e => {
|
navigation.addListener('tabPress', (e) => {
|
||||||
const isFocused = navigation.isFocused();
|
const isFocused = navigation.isFocused();
|
||||||
|
|
||||||
// Run the operation in the next frame so we're sure all listeners have been run
|
// Run the operation in the next frame so we're sure all listeners have been run
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export default function debounce<T extends (...args: any[]) => void>(
|
|||||||
): T {
|
): T {
|
||||||
let timeout: NodeJS.Timeout | number | undefined;
|
let timeout: NodeJS.Timeout | number | undefined;
|
||||||
|
|
||||||
return function(this: any, ...args) {
|
return function (this: any, ...args) {
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
// eslint-disable-next-line babel/no-invalid-this
|
// eslint-disable-next-line babel/no-invalid-this
|
||||||
func.apply(this, args);
|
func.apply(this, args);
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export default function HeaderContainer({
|
|||||||
<View
|
<View
|
||||||
onLayout={
|
onLayout={
|
||||||
onContentHeightChange
|
onContentHeightChange
|
||||||
? e =>
|
? (e) =>
|
||||||
onContentHeightChange({
|
onContentHeightChange({
|
||||||
route: scene.route,
|
route: scene.route,
|
||||||
height: e.nativeEvent.layout.height,
|
height: e.nativeEvent.layout.height,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type State = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const warnIfHeaderStylesDefined = (styles: Record<string, any>) => {
|
const warnIfHeaderStylesDefined = (styles: Record<string, any>) => {
|
||||||
Object.keys(styles).forEach(styleProp => {
|
Object.keys(styles).forEach((styleProp) => {
|
||||||
const value = styles[styleProp];
|
const value = styles[styleProp];
|
||||||
|
|
||||||
if (styleProp === 'position' && value === 'absolute') {
|
if (styleProp === 'position' && value === 'absolute') {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { TextInput, Keyboard } from 'react-native';
|
import { TextInput } from 'react-native';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
@@ -54,7 +54,11 @@ export default class KeyboardManager extends React.Component<Props> {
|
|||||||
|
|
||||||
this.clearKeyboardTimeout();
|
this.clearKeyboardTimeout();
|
||||||
|
|
||||||
Keyboard.dismiss();
|
const input = this.previouslyFocusedTextInput;
|
||||||
|
|
||||||
|
if (input) {
|
||||||
|
TextInput.State.blurTextInput(input);
|
||||||
|
}
|
||||||
|
|
||||||
// Cleanup the ID on successful page change
|
// Cleanup the ID on successful page change
|
||||||
this.previouslyFocusedTextInput = null;
|
this.previouslyFocusedTextInput = null;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ type Props = {
|
|||||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||||
return (
|
return (
|
||||||
<SafeAreaConsumer>
|
<SafeAreaConsumer>
|
||||||
{insets => {
|
{(insets) => {
|
||||||
if (insets) {
|
if (insets) {
|
||||||
// If we already have insets, don't wrap the stack in another safe area provider
|
// If we already have insets, don't wrap the stack in another safe area provider
|
||||||
// This avoids an issue with updates at the cost of potentially incorrect values
|
// This avoids an issue with updates at the cost of potentially incorrect values
|
||||||
|
|||||||
@@ -272,7 +272,10 @@ export default class Card extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const closing =
|
const closing =
|
||||||
translation + velocity * gestureVelocityImpact > distance / 2
|
(translation + velocity) *
|
||||||
|
gestureVelocityImpact *
|
||||||
|
getInvertedMultiplier(gestureDirection) >
|
||||||
|
distance / 2
|
||||||
? velocity !== 0 || translation !== 0
|
? velocity !== 0 || translation !== 0
|
||||||
: false;
|
: false;
|
||||||
|
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ type State = {
|
|||||||
|
|
||||||
const EPSILON = 0.01;
|
const EPSILON = 0.01;
|
||||||
|
|
||||||
const dimensions = Dimensions.get('window');
|
|
||||||
const layout = { width: dimensions.width, height: dimensions.height };
|
|
||||||
|
|
||||||
const MaybeScreenContainer = ({
|
const MaybeScreenContainer = ({
|
||||||
enabled,
|
enabled,
|
||||||
...rest
|
...rest
|
||||||
@@ -160,7 +157,16 @@ const getProgressFromGesture = (
|
|||||||
layout: Layout,
|
layout: Layout,
|
||||||
descriptor?: StackDescriptor
|
descriptor?: StackDescriptor
|
||||||
) => {
|
) => {
|
||||||
const distance = getDistanceFromOptions(mode, layout, descriptor);
|
const distance = getDistanceFromOptions(
|
||||||
|
mode,
|
||||||
|
{
|
||||||
|
// Make sure that we have a non-zero distance, otherwise there will be incorrect progress
|
||||||
|
// This causes blank screen on web if it was previously inside container with display: none
|
||||||
|
width: Math.max(1, layout.width),
|
||||||
|
height: Math.max(1, layout.height),
|
||||||
|
},
|
||||||
|
descriptor
|
||||||
|
);
|
||||||
|
|
||||||
if (distance > 0) {
|
if (distance > 0) {
|
||||||
return gesture.interpolate({
|
return gesture.interpolate({
|
||||||
@@ -290,19 +296,25 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
state: State = {
|
constructor(props: Props) {
|
||||||
routes: [],
|
super(props);
|
||||||
scenes: [],
|
|
||||||
gestures: {},
|
const { height = 0, width = 0 } = Dimensions.get('window');
|
||||||
layout,
|
|
||||||
descriptors: this.props.descriptors,
|
this.state = {
|
||||||
// Used when card's header is null and mode is float to make transition
|
routes: [],
|
||||||
// between screens with headers and those without headers smooth.
|
scenes: [],
|
||||||
// This is not a great heuristic here. We don't know synchronously
|
gestures: {},
|
||||||
// on mount what the header height is so we have just used the most
|
layout: { height, width },
|
||||||
// common cases here.
|
descriptors: this.props.descriptors,
|
||||||
headerHeights: {},
|
// Used when card's header is null and mode is float to make transition
|
||||||
};
|
// between screens with headers and those without headers smooth.
|
||||||
|
// This is not a great heuristic here. We don't know synchronously
|
||||||
|
// on mount what the header height is so we have just used the most
|
||||||
|
// common cases here.
|
||||||
|
headerHeights: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private handleLayout = (e: LayoutChangeEvent) => {
|
private handleLayout = (e: LayoutChangeEvent) => {
|
||||||
const { height, width } = e.nativeEvent.layout;
|
const { height, width } = e.nativeEvent.layout;
|
||||||
@@ -401,9 +413,9 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
left = insets.left,
|
left = insets.left,
|
||||||
} = focusedOptions.safeAreaInsets || {};
|
} = focusedOptions.safeAreaInsets || {};
|
||||||
|
|
||||||
// Screens is buggy on iOS, so we don't enable it there
|
// Screens is buggy on iOS and web, so we only enable it on Android
|
||||||
// For modals, usually we want the screen underneath to be visible, so also disable it there
|
// For modals, usually we want the screen underneath to be visible, so also disable it there
|
||||||
const isScreensEnabled = Platform.OS !== 'ios' && mode !== 'modal';
|
const isScreensEnabled = Platform.OS === 'android' && mode !== 'modal';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
// We only need to animate routes if the focused route changed
|
// We only need to animate routes if the focused route changed
|
||||||
// Animating previous routes won't be visible coz the focused route is on top of everything
|
// Animating previous routes won't be visible coz the focused route is on top of everything
|
||||||
|
|
||||||
if (!previousRoutes.find(r => r.key === nextFocusedRoute.key)) {
|
if (!previousRoutes.find((r) => r.key === nextFocusedRoute.key)) {
|
||||||
// A new route has come to the focus, we treat this as a push
|
// A new route has come to the focus, we treat this as a push
|
||||||
// A replace can also trigger this, the animation should look like push
|
// A replace can also trigger this, the animation should look like push
|
||||||
|
|
||||||
@@ -128,17 +128,17 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
openingRouteKeys = [...openingRouteKeys, nextFocusedRoute.key];
|
openingRouteKeys = [...openingRouteKeys, nextFocusedRoute.key];
|
||||||
|
|
||||||
closingRouteKeys = closingRouteKeys.filter(
|
closingRouteKeys = closingRouteKeys.filter(
|
||||||
key => key !== nextFocusedRoute.key
|
(key) => key !== nextFocusedRoute.key
|
||||||
);
|
);
|
||||||
replacingRouteKeys = replacingRouteKeys.filter(
|
replacingRouteKeys = replacingRouteKeys.filter(
|
||||||
key => key !== nextFocusedRoute.key
|
(key) => key !== nextFocusedRoute.key
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!routes.find(r => r.key === previousFocusedRoute.key)) {
|
if (!routes.find((r) => r.key === previousFocusedRoute.key)) {
|
||||||
// The previous focused route isn't present in state, we treat this as a replace
|
// The previous focused route isn't present in state, we treat this as a replace
|
||||||
|
|
||||||
openingRouteKeys = openingRouteKeys.filter(
|
openingRouteKeys = openingRouteKeys.filter(
|
||||||
key => key !== previousFocusedRoute.key
|
(key) => key !== previousFocusedRoute.key
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getAnimationTypeForReplace(nextFocusedRoute.key) === 'pop') {
|
if (getAnimationTypeForReplace(nextFocusedRoute.key) === 'pop') {
|
||||||
@@ -151,7 +151,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
// But since user configured it to animate the old screen like a pop, we need to add this without animation
|
// But since user configured it to animate the old screen like a pop, we need to add this without animation
|
||||||
// So remove it from `openingRouteKeys` which will remove the animation
|
// So remove it from `openingRouteKeys` which will remove the animation
|
||||||
openingRouteKeys = openingRouteKeys.filter(
|
openingRouteKeys = openingRouteKeys.filter(
|
||||||
key => key !== nextFocusedRoute.key
|
(key) => key !== nextFocusedRoute.key
|
||||||
);
|
);
|
||||||
|
|
||||||
// Keep the route being removed at the end to animate it out
|
// Keep the route being removed at the end to animate it out
|
||||||
@@ -163,7 +163,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
closingRouteKeys = closingRouteKeys.filter(
|
closingRouteKeys = closingRouteKeys.filter(
|
||||||
key => key !== previousFocusedRoute.key
|
(key) => key !== previousFocusedRoute.key
|
||||||
);
|
);
|
||||||
|
|
||||||
// Keep the old route in the state because it's visible under the new route, and removing it will feel abrupt
|
// Keep the old route in the state because it's visible under the new route, and removing it will feel abrupt
|
||||||
@@ -174,7 +174,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!routes.find(r => r.key === previousFocusedRoute.key)) {
|
} else if (!routes.find((r) => r.key === previousFocusedRoute.key)) {
|
||||||
// The previously focused route was removed, we treat this as a pop
|
// The previously focused route was removed, we treat this as a pop
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -186,10 +186,10 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
// Sometimes a route can be closed before the opening animation finishes
|
// Sometimes a route can be closed before the opening animation finishes
|
||||||
// So we also need to remove it from the opening list
|
// So we also need to remove it from the opening list
|
||||||
openingRouteKeys = openingRouteKeys.filter(
|
openingRouteKeys = openingRouteKeys.filter(
|
||||||
key => key !== previousFocusedRoute.key
|
(key) => key !== previousFocusedRoute.key
|
||||||
);
|
);
|
||||||
replacingRouteKeys = replacingRouteKeys.filter(
|
replacingRouteKeys = replacingRouteKeys.filter(
|
||||||
key => key !== previousFocusedRoute.key
|
(key) => key !== previousFocusedRoute.key
|
||||||
);
|
);
|
||||||
|
|
||||||
// Keep a copy of route being removed in the state to be able to animate it
|
// Keep a copy of route being removed in the state to be able to animate it
|
||||||
@@ -271,13 +271,13 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
private getPreviousRoute = ({ route }: { route: Route<string> }) => {
|
private getPreviousRoute = ({ route }: { route: Route<string> }) => {
|
||||||
const { closingRouteKeys, replacingRouteKeys } = this.state;
|
const { closingRouteKeys, replacingRouteKeys } = this.state;
|
||||||
const routes = this.state.routes.filter(
|
const routes = this.state.routes.filter(
|
||||||
r =>
|
(r) =>
|
||||||
r.key === route.key ||
|
r.key === route.key ||
|
||||||
(!closingRouteKeys.includes(r.key) &&
|
(!closingRouteKeys.includes(r.key) &&
|
||||||
!replacingRouteKeys.includes(r.key))
|
!replacingRouteKeys.includes(r.key))
|
||||||
);
|
);
|
||||||
|
|
||||||
const index = routes.findIndex(r => r.key === route.key);
|
const index = routes.findIndex((r) => r.key === route.key);
|
||||||
|
|
||||||
return routes[index - 1];
|
return routes[index - 1];
|
||||||
};
|
};
|
||||||
@@ -298,12 +298,16 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private handleOpenRoute = ({ route }: { route: Route<string> }) => {
|
private handleOpenRoute = ({ route }: { route: Route<string> }) => {
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
routes: state.replacingRouteKeys.length
|
routes: state.replacingRouteKeys.length
|
||||||
? state.routes.filter(r => !state.replacingRouteKeys.includes(r.key))
|
? state.routes.filter((r) => !state.replacingRouteKeys.includes(r.key))
|
||||||
: state.routes,
|
: state.routes,
|
||||||
openingRouteKeys: state.openingRouteKeys.filter(key => key !== route.key),
|
openingRouteKeys: state.openingRouteKeys.filter(
|
||||||
closingRouteKeys: state.closingRouteKeys.filter(key => key !== route.key),
|
(key) => key !== route.key
|
||||||
|
),
|
||||||
|
closingRouteKeys: state.closingRouteKeys.filter(
|
||||||
|
(key) => key !== route.key
|
||||||
|
),
|
||||||
replacingRouteKeys: [],
|
replacingRouteKeys: [],
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
@@ -311,7 +315,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
private handleCloseRoute = ({ route }: { route: Route<string> }) => {
|
private handleCloseRoute = ({ route }: { route: Route<string> }) => {
|
||||||
const { state, navigation } = this.props;
|
const { state, navigation } = this.props;
|
||||||
|
|
||||||
if (state.routes.find(r => r.key === route.key)) {
|
if (state.routes.find((r) => r.key === route.key)) {
|
||||||
// If a route exists in state, trigger a pop
|
// If a route exists in state, trigger a pop
|
||||||
// This will happen in when the route was closed from the card component
|
// This will happen in when the route was closed from the card component
|
||||||
// e.g. When the close animation triggered from a gesture ends
|
// e.g. When the close animation triggered from a gesture ends
|
||||||
@@ -322,13 +326,13 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// We need to clean up any state tracking the route and pop it immediately
|
// We need to clean up any state tracking the route and pop it immediately
|
||||||
this.setState(state => ({
|
this.setState((state) => ({
|
||||||
routes: state.routes.filter(r => r.key !== route.key),
|
routes: state.routes.filter((r) => r.key !== route.key),
|
||||||
openingRouteKeys: state.openingRouteKeys.filter(
|
openingRouteKeys: state.openingRouteKeys.filter(
|
||||||
key => key !== route.key
|
(key) => key !== route.key
|
||||||
),
|
),
|
||||||
closingRouteKeys: state.closingRouteKeys.filter(
|
closingRouteKeys: state.closingRouteKeys.filter(
|
||||||
key => key !== route.key
|
(key) => key !== route.key
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -378,9 +382,9 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
<GestureHandlerWrapper style={styles.container}>
|
<GestureHandlerWrapper style={styles.container}>
|
||||||
<SafeAreaProviderCompat>
|
<SafeAreaProviderCompat>
|
||||||
<SafeAreaConsumer>
|
<SafeAreaConsumer>
|
||||||
{insets => (
|
{(insets) => (
|
||||||
<KeyboardManager enabled={keyboardHandlingEnabled !== false}>
|
<KeyboardManager enabled={keyboardHandlingEnabled !== false}>
|
||||||
{props => (
|
{(props) => (
|
||||||
<CardStack
|
<CardStack
|
||||||
mode={mode}
|
mode={mode}
|
||||||
insets={insets as EdgeInsets}
|
insets={insets as EdgeInsets}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const packages = path.join(__dirname, '..', 'packages');
|
|||||||
|
|
||||||
const invalid = [];
|
const invalid = [];
|
||||||
|
|
||||||
fs.readdirSync(packages).forEach(name => {
|
fs.readdirSync(packages).forEach((name) => {
|
||||||
const dir = path.join(packages, name);
|
const dir = path.join(packages, name);
|
||||||
|
|
||||||
if (fs.statSync(path.join(packages, name)).isDirectory()) {
|
if (fs.statSync(path.join(packages, name)).isDirectory()) {
|
||||||
@@ -26,6 +26,6 @@ fs.readdirSync(packages).forEach(name => {
|
|||||||
if (invalid.length) {
|
if (invalid.length) {
|
||||||
console.log(
|
console.log(
|
||||||
'Found invalid path to type definitions in the following packages:\n',
|
'Found invalid path to type definitions in the following packages:\n',
|
||||||
invalid.map(p => `- ${p.name} (${p.types})`).join('\n')
|
invalid.map((p) => `- ${p.name} (${p.types})`).join('\n')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14637,10 +14637,10 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^1.19.1:
|
prettier@^2.0.1:
|
||||||
version "1.19.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.1.tgz#3f00ac71263be34684b2b2c8d7e7f63737592dac"
|
||||||
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
integrity sha512-piXGBcY1zoFOG0MvHpNE5reAGseLmaCRifQ/fmfF49BcYkInEs/naD/unxGNAeOKFA5+JxVrPyMvMlpzcd20UA==
|
||||||
|
|
||||||
pretty-bytes@^4.0.2:
|
pretty-bytes@^4.0.2:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user