mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 09:30:30 +08:00
Compare commits
8 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f2368965c | ||
|
|
61f16d3f25 | ||
|
|
853740bfaf | ||
|
|
179b6312fe | ||
|
|
043924ca48 | ||
|
|
813a5903b5 | ||
|
|
3709e652f4 | ||
|
|
5b15c7164f |
@@ -1,4 +1,4 @@
|
||||
module.exports = function(api) {
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
|
||||
@@ -15,8 +15,8 @@ const modules = ['@expo/vector-icons']
|
||||
// List all packages under `packages/`
|
||||
.readdirSync(packages)
|
||||
// Ignore hidden files such as .DS_Store
|
||||
.filter(p => !p.startsWith('.'))
|
||||
.map(p => {
|
||||
.filter((p) => !p.startsWith('.'))
|
||||
.map((p) => {
|
||||
const pak = JSON.parse(
|
||||
fs.readFileSync(path.join(packages, p, 'package.json'), 'utf8')
|
||||
);
|
||||
@@ -50,9 +50,9 @@ module.exports = {
|
||||
blacklistRE: blacklist(
|
||||
fs
|
||||
.readdirSync(packages)
|
||||
.map(p => path.join(packages, p))
|
||||
.map((p) => path.join(packages, p))
|
||||
.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: {
|
||||
enhanceMiddleware: middleware => {
|
||||
enhanceMiddleware: (middleware) => {
|
||||
return (req, res, next) => {
|
||||
// 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
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function BottomTabsScreen() {
|
||||
return (
|
||||
<BottomTabs.Navigator
|
||||
screenOptions={{
|
||||
tabBarButton: props => <TouchableBounce {...props} />,
|
||||
tabBarButton: (props) => <TouchableBounce {...props} />,
|
||||
}}
|
||||
>
|
||||
<BottomTabs.Screen
|
||||
@@ -38,7 +38,7 @@ export default function BottomTabsScreen() {
|
||||
tabBarIcon: getTabBarIcon('file-document-box'),
|
||||
}}
|
||||
>
|
||||
{props => <SimpleStackScreen {...props} headerMode="none" />}
|
||||
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
|
||||
</BottomTabs.Screen>
|
||||
<BottomTabs.Screen
|
||||
name="Chat"
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function BottomTabsScreen() {
|
||||
|
||||
return (
|
||||
<BottomTabs.Navigator>
|
||||
{tabs.map(i => (
|
||||
{tabs.map((i) => (
|
||||
<BottomTabs.Screen
|
||||
key={i}
|
||||
name={`tab-${i}`}
|
||||
@@ -29,12 +29,14 @@ export default function BottomTabsScreen() {
|
||||
{() => (
|
||||
<View style={styles.container}>
|
||||
<Title>Tab {i}</Title>
|
||||
<Button onPress={() => setTabs(tabs => [...tabs, tabs.length])}>
|
||||
<Button onPress={() => setTabs((tabs) => [...tabs, tabs.length])}>
|
||||
Add a tab
|
||||
</Button>
|
||||
<Button
|
||||
onPress={() =>
|
||||
setTabs(tabs => (tabs.length > 1 ? tabs.slice(0, -1) : tabs))
|
||||
setTabs((tabs) =>
|
||||
tabs.length > 1 ? tabs.slice(0, -1) : tabs
|
||||
)
|
||||
}
|
||||
>
|
||||
Remove a tab
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function MaterialBottomTabsScreen() {
|
||||
tabBarColor: '#C9E7F8',
|
||||
}}
|
||||
>
|
||||
{props => <SimpleStackScreen {...props} headerMode="none" />}
|
||||
{(props) => <SimpleStackScreen {...props} headerMode="none" />}
|
||||
</MaterialBottomTabs.Screen>
|
||||
<MaterialBottomTabs.Screen
|
||||
name="Chat"
|
||||
|
||||
@@ -68,10 +68,7 @@ export default function Chat(props: Partial<ScrollViewProps>) {
|
||||
styles.input,
|
||||
{ backgroundColor: colors.card, color: colors.text },
|
||||
]}
|
||||
placeholderTextColor={Color(colors.text)
|
||||
.alpha(0.5)
|
||||
.rgb()
|
||||
.string()}
|
||||
placeholderTextColor={Color(colors.text).alpha(0.5).rgb().string()}
|
||||
placeholder="Write a message"
|
||||
underlineColorAndroid="transparent"
|
||||
/>
|
||||
|
||||
@@ -51,10 +51,7 @@ export default function NewsFeed(props: Props) {
|
||||
<Card style={styles.card}>
|
||||
<TextInput
|
||||
placeholder="What's on your mind?"
|
||||
placeholderTextColor={Color(colors.text)
|
||||
.alpha(0.5)
|
||||
.rgb()
|
||||
.string()}
|
||||
placeholderTextColor={Color(colors.text).alpha(0.5).rgb().string()}
|
||||
style={styles.input}
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -224,7 +224,7 @@ export default function App() {
|
||||
<NavigationContainer
|
||||
ref={containerRef}
|
||||
initialState={initialState}
|
||||
onStateChange={state =>
|
||||
onStateChange={(state) =>
|
||||
AsyncStorage.setItem(
|
||||
NAVIGATION_PERSISTENCE_KEY,
|
||||
JSON.stringify(state)
|
||||
@@ -298,12 +298,12 @@ export default function App() {
|
||||
theme.dark ? 'light' : 'dark'
|
||||
);
|
||||
|
||||
setTheme(t => (t.dark ? DefaultTheme : DarkTheme));
|
||||
setTheme((t) => (t.dark ? DefaultTheme : DarkTheme));
|
||||
}}
|
||||
/>
|
||||
<Divider />
|
||||
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
||||
name => (
|
||||
(name) => (
|
||||
<List.Item
|
||||
key={name}
|
||||
title={SCREENS[name].title}
|
||||
@@ -315,7 +315,7 @@ export default function App() {
|
||||
)}
|
||||
</Stack.Screen>
|
||||
{(Object.keys(SCREENS) as (keyof typeof SCREENS)[]).map(
|
||||
name => (
|
||||
(name) => (
|
||||
<Stack.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
|
||||
@@ -7,7 +7,7 @@ const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
|
||||
const node_modules = path.resolve(__dirname, '..', 'node_modules');
|
||||
const packages = path.resolve(__dirname, '..', 'packages');
|
||||
|
||||
module.exports = async function(env, argv) {
|
||||
module.exports = async function (env, argv) {
|
||||
const config = await createExpoWebpackConfigAsync(env, argv);
|
||||
|
||||
config.context = path.resolve(__dirname, '..');
|
||||
@@ -20,7 +20,7 @@ module.exports = async function(env, argv) {
|
||||
});
|
||||
|
||||
config.resolve.plugins = config.resolve.plugins.filter(
|
||||
p => !(p instanceof ModuleScopePlugin)
|
||||
(p) => !(p instanceof ModuleScopePlugin)
|
||||
);
|
||||
|
||||
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'),
|
||||
});
|
||||
|
||||
fs.readdirSync(packages).forEach(name => {
|
||||
fs.readdirSync(packages).forEach((name) => {
|
||||
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
||||
packages,
|
||||
name,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
"husky": "^4.2.3",
|
||||
"jest": "^25.1.0",
|
||||
"lerna": "^3.20.2",
|
||||
"prettier": "^1.19.1",
|
||||
"prettier": "^2.0.1",
|
||||
"typescript": "^3.7.5"
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/bottom-tabs",
|
||||
"description": "Bottom tab navigator following iOS design guidelines",
|
||||
"version": "5.2.2",
|
||||
"version": "5.2.3",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
|
||||
@@ -121,7 +121,7 @@ export default function BottomTabBar({
|
||||
const handleLayout = (e: LayoutChangeEvent) => {
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
|
||||
setLayout(layout => {
|
||||
setLayout((layout) => {
|
||||
if (height === layout.height && width === layout.width) {
|
||||
return layout;
|
||||
} else {
|
||||
|
||||
@@ -133,9 +133,7 @@ export default function BottomTabBarItem({
|
||||
|
||||
const inactiveTintColor =
|
||||
customInactiveTintColor === undefined
|
||||
? Color(colors.text)
|
||||
.mix(Color(colors.card), 0.5)
|
||||
.hex()
|
||||
? Color(colors.text).mix(Color(colors.card), 0.5).hex()
|
||||
: customInactiveTintColor;
|
||||
|
||||
const renderLabel = ({ focused }: { focused: boolean }) => {
|
||||
|
||||
@@ -30,7 +30,7 @@ type Props = {
|
||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||
return (
|
||||
<SafeAreaConsumer>
|
||||
{insets => {
|
||||
{(insets) => {
|
||||
if (insets) {
|
||||
// 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
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.1.4",
|
||||
"version": "5.1.5",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
||||
"bugs": {
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/react": "^16.9.23",
|
||||
"react": "~16.9.0",
|
||||
"typescript": "^3.7.5"
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function createCompatNavigatorFactory<
|
||||
function Navigator({ screenProps }: { screenProps?: unknown }) {
|
||||
const screens = React.useMemo(
|
||||
() =>
|
||||
routeNames.map(name => {
|
||||
routeNames.map((name) => {
|
||||
let getScreenComponent: () => CompatScreenType<NavigationPropType>;
|
||||
|
||||
let initialParams;
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function useCompatNavigation<
|
||||
const route = useRoute();
|
||||
|
||||
const isFirstRouteInParent = useNavigationState(
|
||||
state => state.routes[0].key === route.key
|
||||
(state) => state.routes[0].key === route.key
|
||||
);
|
||||
|
||||
const context = React.useRef<Record<string, any>>({});
|
||||
|
||||
@@ -26,8 +26,9 @@ export default function withNavigation<
|
||||
return <Comp ref={onRef} navigation={navigation} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigation(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
WrappedComponent.displayName = `withNavigation(${
|
||||
Comp.displayName || Comp.name
|
||||
})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,9 @@ export default function withNavigationFocus<
|
||||
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigationFocus(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
WrappedComponent.displayName = `withNavigationFocus(${
|
||||
Comp.displayName || Comp.name
|
||||
})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/core",
|
||||
"description": "Core utilities for building navigators",
|
||||
"version": "5.2.3",
|
||||
"version": "5.3.0",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
@@ -29,7 +29,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.1.1",
|
||||
"@react-navigation/routers": "^5.2.0",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"query-string": "^6.11.1",
|
||||
"react-is": "^16.13.0",
|
||||
|
||||
@@ -73,7 +73,7 @@ const getPartialState = (
|
||||
return {
|
||||
...partialState,
|
||||
stale: true,
|
||||
routes: state.routes.map(route => {
|
||||
routes: state.routes.map((route) => {
|
||||
if (route.state === undefined) {
|
||||
return route as Route<string> & {
|
||||
state?: PartialState<NavigationState>;
|
||||
@@ -156,7 +156,7 @@ const BaseNavigationContainer = React.forwardRef(
|
||||
throw new Error(NOT_INITIALIZED_ERROR);
|
||||
}
|
||||
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
listeners[0]((navigation) => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
const canGoBack = () => {
|
||||
@@ -164,7 +164,7 @@ const BaseNavigationContainer = React.forwardRef(
|
||||
return false;
|
||||
}
|
||||
|
||||
const { result, handled } = listeners[0](navigation =>
|
||||
const { result, handled } = listeners[0]((navigation) =>
|
||||
navigation.canGoBack()
|
||||
);
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export default function SceneView<
|
||||
|
||||
const getCurrentState = React.useCallback(() => {
|
||||
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;
|
||||
}, [getState, route.key]);
|
||||
@@ -62,7 +62,7 @@ export default function SceneView<
|
||||
|
||||
setState({
|
||||
...state,
|
||||
routes: state.routes.map(r =>
|
||||
routes: state.routes.map((r) =>
|
||||
r.key === route.key ? { ...r, state: child } : r
|
||||
),
|
||||
});
|
||||
|
||||
@@ -122,7 +122,7 @@ it('handle dispatching with ref', () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -220,7 +220,7 @@ it('handle resetting state with ref', () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -371,7 +371,7 @@ it('emits state events when the state changes', () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
key: String(MockRouterKey.current++),
|
||||
index,
|
||||
routeNames,
|
||||
routes: routeNames.map(name => ({
|
||||
routes: routeNames.map((name) => ({
|
||||
name,
|
||||
key: name,
|
||||
params: routeParamList[name],
|
||||
@@ -43,9 +43,9 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
}
|
||||
|
||||
const routes = state.routes
|
||||
.filter(route => routeNames.includes(route.name))
|
||||
.filter((route) => routeNames.includes(route.name))
|
||||
.map(
|
||||
route =>
|
||||
(route) =>
|
||||
({
|
||||
...route,
|
||||
key: route.key || `${route.name}-${MockRouterKey.current++}`,
|
||||
@@ -73,7 +73,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
},
|
||||
|
||||
getStateForRouteNamesChange(state, { routeNames }) {
|
||||
const routes = state.routes.filter(route =>
|
||||
const routes = state.routes.filter((route) =>
|
||||
routeNames.includes(route.name)
|
||||
);
|
||||
|
||||
@@ -86,7 +86,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
},
|
||||
|
||||
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) {
|
||||
return state;
|
||||
@@ -105,7 +105,7 @@ export default function MockRouter(options: DefaultRouterOptions) {
|
||||
|
||||
case 'NAVIGATE': {
|
||||
const index = state.routes.findIndex(
|
||||
route => route.name === action.payload.name
|
||||
(route) => route.name === action.payload.name
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
|
||||
@@ -42,7 +42,8 @@ it('converts state to path string with config', () => {
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
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/, '')),
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -128,7 +129,8 @@ it('handles state with config with nested screens', () => {
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -192,12 +194,14 @@ it('handles state with config with nested screens and unused configs', () => {
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
stringify: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toLowerCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
unknown: (_: unknown) => 'x',
|
||||
},
|
||||
},
|
||||
@@ -255,11 +259,11 @@ it('handles nested object with stringify in it', () => {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
|
||||
@@ -42,7 +42,8 @@ it('converts path string to initial state with config', () => {
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -153,7 +154,8 @@ it('converts path string to initial state with config with nested screens', () =
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -217,7 +219,8 @@ it('converts path string to initial state with config with nested screens and un
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
parse: {
|
||||
author: (author: string) => author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
id: Boolean,
|
||||
@@ -277,11 +280,11 @@ it('handles nested object with unused configs and with parse in it', () => {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -528,11 +531,11 @@ it('handles two initialRouteNames', () => {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
@@ -610,11 +613,11 @@ it('accepts initialRouteName without config for it', () => {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
|
||||
@@ -119,7 +119,7 @@ it('sets options with screenOptions prop as an object', () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.routes.map(route => {
|
||||
{state.routes.map((route) => {
|
||||
const { render, options } = descriptors[route.key];
|
||||
|
||||
return (
|
||||
@@ -179,7 +179,7 @@ it('sets options with screenOptions prop as a fuction', () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{state.routes.map(route => {
|
||||
{state.routes.map((route) => {
|
||||
const { render, options } = descriptors[route.key];
|
||||
|
||||
return (
|
||||
@@ -273,7 +273,7 @@ it('sets initial options with setOptions', () => {
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
{(props) => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
@@ -338,7 +338,7 @@ it('updates options with setOptions', () => {
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" options={{ color: 'blue' }}>
|
||||
{props => <TestScreen {...props} />}
|
||||
{(props) => <TestScreen {...props} />}
|
||||
</Screen>
|
||||
<Screen name="bar" component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
|
||||
@@ -15,7 +15,7 @@ it('fires focus and blur events in root navigator', () => {
|
||||
|
||||
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();
|
||||
@@ -106,7 +106,7 @@ it('fires focus and blur events in nested navigator', () => {
|
||||
|
||||
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();
|
||||
@@ -376,7 +376,7 @@ it('fires custom events added with addListener', () => {
|
||||
state,
|
||||
]);
|
||||
|
||||
return state.routes.map(route => descriptors[route.key].render());
|
||||
return state.routes.map((route) => descriptors[route.key].render());
|
||||
});
|
||||
|
||||
const firstCallback = jest.fn();
|
||||
@@ -456,7 +456,7 @@ it("doesn't call same listener multiple times with addListener", () => {
|
||||
state,
|
||||
]);
|
||||
|
||||
return state.routes.map(route => descriptors[route.key].render());
|
||||
return state.routes.map((route) => descriptors[route.key].render());
|
||||
});
|
||||
|
||||
const callback = jest.fn();
|
||||
@@ -640,7 +640,7 @@ it('has option to prevent default', () => {
|
||||
state,
|
||||
]);
|
||||
|
||||
return state.routes.map(route => descriptors[route.key].render());
|
||||
return state.routes.map((route) => descriptors[route.key].render());
|
||||
});
|
||||
|
||||
const callback = (e: any) => {
|
||||
|
||||
@@ -10,7 +10,7 @@ it('runs focus effect on focus change', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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();
|
||||
@@ -107,7 +107,7 @@ it('runs focus effect when initial state is given', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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();
|
||||
|
||||
@@ -10,7 +10,7 @@ it('renders correct focus state', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 = () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ it('gets navigation prop from context', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 = () => {
|
||||
@@ -38,7 +38,7 @@ it("gets navigation's parent from context", () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 = () => {
|
||||
@@ -70,7 +70,7 @@ it("gets navigation's parent's parent from context", () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 = () => {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
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 useNavigationCache from '../useNavigationCache';
|
||||
import useNavigationBuilder from '../useNavigationBuilder';
|
||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||
import Screen from '../Screen';
|
||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||
|
||||
beforeEach(() => (MockRouterKey.current = 0));
|
||||
@@ -40,7 +43,7 @@ it('preserves reference for navigation objects', () => {
|
||||
});
|
||||
|
||||
if (previous.current) {
|
||||
Object.keys(navigations).forEach(key => {
|
||||
Object.keys(navigations).forEach((key) => {
|
||||
expect(navigations[key]).toBe(previous.current[key]);
|
||||
});
|
||||
}
|
||||
@@ -56,3 +59,136 @@ it('preserves reference for navigation objects', () => {
|
||||
|
||||
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 { 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 Test = () => {
|
||||
const state = useNavigationState(state => state);
|
||||
const state = useNavigationState((state) => state);
|
||||
|
||||
callback(state);
|
||||
|
||||
@@ -62,13 +62,13 @@ it('gets the current navigation state with selector', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 Test = () => {
|
||||
const index = useNavigationState(state => state.index);
|
||||
const index = useNavigationState((state) => state.index);
|
||||
|
||||
callback(index);
|
||||
|
||||
@@ -112,7 +112,7 @@ it('gets the correct value if selector changes', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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();
|
||||
@@ -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.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.mock.calls[1][0]).toBe('first');
|
||||
|
||||
@@ -137,7 +137,7 @@ it("lets children handle the action if parent didn't", () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -270,7 +270,7 @@ it("action doesn't bubble if target is specified", () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
@@ -317,7 +317,7 @@ it('logs error if no navigator handled the action', () => {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
{state.routes.map((route) => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ it('gets route prop from context', () => {
|
||||
const TestNavigator = (props: any): any => {
|
||||
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 = () => {
|
||||
|
||||
@@ -16,7 +16,7 @@ export default function createNavigatorFactory<
|
||||
EventMap extends EventMapBase,
|
||||
NavigatorComponent extends React.ComponentType<any>
|
||||
>(Navigator: NavigatorComponent) {
|
||||
return function<ParamList extends ParamListBase>(): TypedNavigator<
|
||||
return function <ParamList extends ParamListBase>(): TypedNavigator<
|
||||
ParamList,
|
||||
State,
|
||||
ScreenOptions,
|
||||
|
||||
@@ -125,7 +125,7 @@ export default function getPathFromState(
|
||||
if (currentOptions[route.name] !== undefined) {
|
||||
path += pattern
|
||||
.split('/')
|
||||
.map(p => {
|
||||
.map((p) => {
|
||||
const name = p.replace(/^:/, '');
|
||||
|
||||
// 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[] = [];
|
||||
// Create a normalized configs array which will be easier to use
|
||||
const configs = ([] as RouteConfig[]).concat(
|
||||
...Object.keys(options).map(key =>
|
||||
...Object.keys(options).map((key) =>
|
||||
createNormalizedConfigs(key, options, [], initialRoutes)
|
||||
)
|
||||
);
|
||||
@@ -91,7 +91,7 @@ export default function getStateFromPath(
|
||||
|
||||
const paramPatterns = config.pattern
|
||||
.split('/')
|
||||
.filter(p => p.startsWith(':'));
|
||||
.filter((p) => p.startsWith(':'));
|
||||
|
||||
if (paramPatterns.length) {
|
||||
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
||||
@@ -188,7 +188,7 @@ export default function getStateFromPath(
|
||||
const parseFunction = findParseConfigForRoute(route.name, configs);
|
||||
|
||||
if (parseFunction) {
|
||||
Object.keys(params).forEach(name => {
|
||||
Object.keys(params).forEach((name) => {
|
||||
if (parseFunction[name] && typeof params[name] === 'string') {
|
||||
params[name] = parseFunction[name](params[name] as string);
|
||||
}
|
||||
@@ -233,7 +233,7 @@ function createNormalizedConfigs(
|
||||
connectedRoutes: Object.keys(value.screens),
|
||||
});
|
||||
}
|
||||
Object.keys(value.screens).forEach(nestedConfig => {
|
||||
Object.keys(value.screens).forEach((nestedConfig) => {
|
||||
const result = createNormalizedConfigs(
|
||||
nestedConfig,
|
||||
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<
|
||||
ParamList extends ParamListBase,
|
||||
RouteName extends keyof ParamList,
|
||||
@@ -371,12 +381,12 @@ export type RouteConfig<
|
||||
/**
|
||||
* Event listeners for this screen.
|
||||
*/
|
||||
listeners?: Partial<
|
||||
{
|
||||
[EventName in keyof (EventMap &
|
||||
EventMapCore<State>)]: EventListenerCallback<EventMap, EventName>;
|
||||
}
|
||||
>;
|
||||
listeners?:
|
||||
| ScreenListeners<State, EventMap>
|
||||
| ((props: {
|
||||
route: RouteProp<ParamList, RouteName>;
|
||||
navigation: any;
|
||||
}) => ScreenListeners<State, EventMap>);
|
||||
|
||||
/**
|
||||
* Initial params object for the route.
|
||||
|
||||
@@ -58,7 +58,7 @@ export default function useDevTools({ name, reset, state, enabled }: Options) {
|
||||
|
||||
React.useEffect(
|
||||
() =>
|
||||
devTools?.subscribe(message => {
|
||||
devTools?.subscribe((message) => {
|
||||
if (message.type === 'DISPATCH' && message.state) {
|
||||
reset(JSON.parse(message.state));
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export default function useEventEmitter(
|
||||
target !== undefined
|
||||
? items[target] && items[target].slice()
|
||||
: ([] 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);
|
||||
|
||||
const event: EventArg<any, any, any> = {
|
||||
@@ -117,7 +117,7 @@ export default function useEventEmitter(
|
||||
|
||||
listenRef.current?.(event);
|
||||
|
||||
callbacks?.forEach(cb => cb(event));
|
||||
callbacks?.forEach((cb) => cb(event));
|
||||
|
||||
return event as any;
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
RouterFactory,
|
||||
PartialState,
|
||||
NavigationAction,
|
||||
Route,
|
||||
} from '@react-navigation/routers';
|
||||
import { NavigationStateContext } from './BaseNavigationContainer';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
@@ -103,7 +104,7 @@ const getRouteConfigsFromChildren = <
|
||||
}, []);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
configs.forEach(config => {
|
||||
configs.forEach((config) => {
|
||||
const { name, children, component } = config as any;
|
||||
|
||||
if (typeof name !== 'string' || !name) {
|
||||
@@ -212,7 +213,7 @@ export default function useNavigationBuilder<
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const routeNames = routeConfigs.map(config => config.name);
|
||||
const routeNames = routeConfigs.map((config) => config.name);
|
||||
const routeParamList = routeNames.reduce<Record<string, object | undefined>>(
|
||||
(acc, curr) => {
|
||||
const { initialParams } = screens[curr];
|
||||
@@ -241,12 +242,12 @@ export default function useNavigationBuilder<
|
||||
}
|
||||
|
||||
const isStateValid = React.useCallback(
|
||||
state => state.type === undefined || state.type === router.type,
|
||||
(state) => state.type === undefined || state.type === router.type,
|
||||
[router.type]
|
||||
);
|
||||
|
||||
const isStateInitialized = React.useCallback(
|
||||
state =>
|
||||
(state) =>
|
||||
state !== undefined && state.stale === false && isStateValid(state),
|
||||
[isStateValid]
|
||||
);
|
||||
@@ -367,14 +368,16 @@ export default function useNavigationBuilder<
|
||||
: (initializedStateRef.current as State);
|
||||
}, [getCurrentState, isStateInitialized]);
|
||||
|
||||
const emitter = useEventEmitter(e => {
|
||||
const emitter = useEventEmitter((e) => {
|
||||
let routeNames = [];
|
||||
|
||||
if (e.target) {
|
||||
const name = state.routes.find(route => route.key === e.target)?.name;
|
||||
let target: Route<string> | undefined;
|
||||
|
||||
if (name) {
|
||||
routeNames.push(name);
|
||||
if (e.target) {
|
||||
target = state.routes.find((route) => route.key === e.target);
|
||||
|
||||
if (target?.name) {
|
||||
routeNames.push(target.name);
|
||||
}
|
||||
} else {
|
||||
routeNames.push(...Object.keys(screens));
|
||||
@@ -382,19 +385,28 @@ export default function useNavigationBuilder<
|
||||
|
||||
const listeners = ([] as (((e: any) => void) | undefined)[])
|
||||
.concat(
|
||||
...routeNames.map(name => {
|
||||
...routeNames.map((name) => {
|
||||
const { listeners } = screens[name];
|
||||
|
||||
return listeners
|
||||
? Object.keys(listeners)
|
||||
.filter(type => type === e.type)
|
||||
.map(type => listeners[type])
|
||||
.filter((type) => type === e.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;
|
||||
})
|
||||
)
|
||||
.filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
|
||||
|
||||
listeners.forEach(listener => listener?.(e));
|
||||
listeners.forEach((listener) => listener?.(e));
|
||||
});
|
||||
|
||||
useFocusEvents({ state, emitter });
|
||||
|
||||
@@ -63,7 +63,7 @@ export default function useNavigationCache<
|
||||
};
|
||||
|
||||
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
|
||||
(acc, route, index) => {
|
||||
(acc, route) => {
|
||||
const previous = cache.current[route.key];
|
||||
|
||||
if (previous) {
|
||||
@@ -103,14 +103,14 @@ export default function useNavigationCache<
|
||||
dangerouslyGetState: getState,
|
||||
dispatch,
|
||||
setOptions: (options: object) =>
|
||||
setOptions(o => ({
|
||||
setOptions((o) => ({
|
||||
...o,
|
||||
[route.key]: { ...o[route.key], ...options },
|
||||
})),
|
||||
isFocused: () => {
|
||||
const state = getState();
|
||||
|
||||
if (index !== state.index) {
|
||||
if (state.routes[state.index].key !== route.key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function useNavigationState<T>(selector: Selector<T>): T {
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const unsubscribe = navigation.addListener('state', e => {
|
||||
const unsubscribe = navigation.addListener('state', (e) => {
|
||||
setResult(selectorRef.current(e.data.state));
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function useOnGetState({
|
||||
const state = getState();
|
||||
return {
|
||||
...state,
|
||||
routes: state.routes.map(route => ({
|
||||
routes: state.routes.map((route) => ({
|
||||
...route,
|
||||
state: getStateForRoute(route.key),
|
||||
})),
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/drawer",
|
||||
"description": "Drawer navigator component with animated transitions and gesturess",
|
||||
"version": "5.3.2",
|
||||
"version": "5.3.3",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"del-cli": "^3.0.0",
|
||||
|
||||
@@ -72,14 +72,8 @@ export default function DrawerItem(props: Props) {
|
||||
labelStyle,
|
||||
focused = false,
|
||||
activeTintColor = colors.primary,
|
||||
inactiveTintColor = Color(colors.text)
|
||||
.alpha(0.68)
|
||||
.rgb()
|
||||
.string(),
|
||||
activeBackgroundColor = Color(activeTintColor)
|
||||
.alpha(0.12)
|
||||
.rgb()
|
||||
.string(),
|
||||
inactiveTintColor = Color(colors.text).alpha(0.68).rgb().string(),
|
||||
activeBackgroundColor = Color(activeTintColor).alpha(0.12).rgb().string(),
|
||||
inactiveBackgroundColor = 'transparent',
|
||||
style,
|
||||
onPress,
|
||||
|
||||
@@ -99,7 +99,7 @@ export default function DrawerView({
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
const isDrawerOpen = state.history.some(it => it.type === 'drawer');
|
||||
const isDrawerOpen = state.history.some((it) => it.type === 'drawer');
|
||||
|
||||
const handleDrawerOpen = React.useCallback(() => {
|
||||
navigation.dispatch({
|
||||
@@ -212,7 +212,7 @@ export default function DrawerView({
|
||||
gestureEnabled={gestureEnabled}
|
||||
onOpen={handleDrawerOpen}
|
||||
onClose={handleDrawerClose}
|
||||
onGestureRef={ref => {
|
||||
onGestureRef={(ref) => {
|
||||
// @ts-ignore
|
||||
drawerGestureRef.current = ref;
|
||||
}}
|
||||
|
||||
@@ -30,7 +30,7 @@ type Props = {
|
||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||
return (
|
||||
<SafeAreaConsumer>
|
||||
{insets => {
|
||||
{(insets) => {
|
||||
if (insets) {
|
||||
// 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
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-bottom-tabs",
|
||||
"description": "Integration for bottom navigation component from react-native-paper",
|
||||
"version": "5.1.4",
|
||||
"version": "5.1.5",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"@types/react-native-vector-icons": "^6.4.5",
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-top-tabs",
|
||||
"description": "Integration for the animated tab view component from react-native-tab-view",
|
||||
"version": "5.1.4",
|
||||
"version": "5.1.5",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -39,7 +39,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"del-cli": "^3.0.0",
|
||||
|
||||
@@ -14,17 +14,11 @@ export default function TabBarTop(props: MaterialTopTabBarProps) {
|
||||
navigation,
|
||||
descriptors,
|
||||
activeTintColor = colors.text,
|
||||
inactiveTintColor = Color(activeTintColor)
|
||||
.alpha(0.5)
|
||||
.rgb()
|
||||
.string(),
|
||||
inactiveTintColor = Color(activeTintColor).alpha(0.5).rgb().string(),
|
||||
allowFontScaling = true,
|
||||
showIcon = false,
|
||||
showLabel = true,
|
||||
pressColor = Color(activeTintColor)
|
||||
.alpha(0.08)
|
||||
.rgb()
|
||||
.string(),
|
||||
pressColor = Color(activeTintColor).alpha(0.08).rgb().string(),
|
||||
iconStyle,
|
||||
labelStyle,
|
||||
indicatorStyle,
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function MaterialTopTabView({
|
||||
return (
|
||||
<TabView
|
||||
{...rest}
|
||||
onIndexChange={index =>
|
||||
onIndexChange={(index) =>
|
||||
navigation.dispatch({
|
||||
...TabActions.jumpTo(state.routes[index].name),
|
||||
target: state.key,
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/native",
|
||||
"description": "React Native integration for React Navigation",
|
||||
"version": "5.1.1",
|
||||
"version": "5.1.2",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"react-navigation",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.2.3"
|
||||
"@react-navigation/core": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export default function() {
|
||||
export default function () {
|
||||
throw new Error(
|
||||
"'NavigationNativeContainer' has been renamed to 'NavigationContainer"
|
||||
);
|
||||
|
||||
@@ -3,6 +3,17 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
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)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/routers",
|
||||
"description": "Routers to help build custom navigators",
|
||||
"version": "5.1.1",
|
||||
"version": "5.2.0",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import shortid from 'shortid';
|
||||
import { CommonNavigationAction, NavigationState, PartialState } from './types';
|
||||
|
||||
/**
|
||||
@@ -12,7 +13,7 @@ const BaseRouter = {
|
||||
switch (action.type) {
|
||||
case 'SET_PARAMS': {
|
||||
const index = action.source
|
||||
? state.routes.findIndex(r => r.key === action.source)
|
||||
? state.routes.findIndex((r) => r.key === action.source)
|
||||
: state.index;
|
||||
|
||||
if (index === -1) {
|
||||
@@ -32,15 +33,6 @@ const BaseRouter = {
|
||||
case 'RESET': {
|
||||
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 (
|
||||
nextState.routes.length === 0 ||
|
||||
nextState.routes.some(
|
||||
@@ -50,6 +42,26 @@ const BaseRouter = {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ export const DrawerActions = {
|
||||
|
||||
const isDrawerOpen = (
|
||||
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 => {
|
||||
if (isDrawerOpen(state)) {
|
||||
@@ -91,7 +91,7 @@ const closeDrawer = (state: DrawerNavigationState): DrawerNavigationState => {
|
||||
|
||||
return {
|
||||
...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
|
||||
.filter(route => routeNames.includes(route.name))
|
||||
.filter((route) => routeNames.includes(route.name))
|
||||
.map(
|
||||
route =>
|
||||
(route) =>
|
||||
({
|
||||
...route,
|
||||
key: route.key || `${route.name}-${shortid()}`,
|
||||
@@ -174,7 +174,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
},
|
||||
|
||||
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
||||
const routes = state.routes.filter(route =>
|
||||
const routes = state.routes.filter((route) =>
|
||||
routeNames.includes(route.name)
|
||||
);
|
||||
|
||||
@@ -201,7 +201,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
},
|
||||
|
||||
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) {
|
||||
return state;
|
||||
@@ -220,7 +220,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
switch (action.type) {
|
||||
case 'REPLACE': {
|
||||
const index = action.source
|
||||
? state.routes.findIndex(r => r.key === action.source)
|
||||
? state.routes.findIndex((r) => r.key === action.source)
|
||||
: state.index;
|
||||
|
||||
if (index === -1) {
|
||||
@@ -283,7 +283,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
case 'POP': {
|
||||
const index =
|
||||
action.target === state.key && action.source
|
||||
? state.routes.findIndex(r => r.key === action.source)
|
||||
? state.routes.findIndex((r) => r.key === action.source)
|
||||
: state.index;
|
||||
|
||||
if (index > 0) {
|
||||
|
||||
@@ -93,7 +93,7 @@ const changeIndex = (
|
||||
const currentKey = state.routes[index].key;
|
||||
|
||||
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 });
|
||||
} else {
|
||||
history = getRouteHistory(state.routes, index, backBehavior);
|
||||
@@ -124,7 +124,7 @@ export default function TabRouter({
|
||||
? routeNames.indexOf(initialRouteName)
|
||||
: 0;
|
||||
|
||||
const routes = routeNames.map(name => ({
|
||||
const routes = routeNames.map((name) => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
params: routeParamList[name],
|
||||
@@ -150,9 +150,9 @@ export default function TabRouter({
|
||||
return state;
|
||||
}
|
||||
|
||||
const routes = routeNames.map(name => {
|
||||
const routes = routeNames.map((name) => {
|
||||
const route = (state as PartialState<TabNavigationState>).routes.find(
|
||||
r => r.name === name
|
||||
(r) => r.name === name
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -184,8 +184,8 @@ export default function TabRouter({
|
||||
routes.length - 1
|
||||
);
|
||||
|
||||
let history = state.history?.filter(it =>
|
||||
routes.find(r => r.key === it.key)
|
||||
let history = state.history?.filter((it) =>
|
||||
routes.find((r) => r.key === it.key)
|
||||
);
|
||||
|
||||
if (!history?.length) {
|
||||
@@ -205,8 +205,8 @@ export default function TabRouter({
|
||||
|
||||
getStateForRouteNamesChange(state, { routeNames, routeParamList }) {
|
||||
const routes = routeNames.map(
|
||||
name =>
|
||||
state.routes.find(r => r.name === name) || {
|
||||
(name) =>
|
||||
state.routes.find((r) => r.name === name) || {
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
params: routeParamList[name],
|
||||
@@ -218,8 +218,8 @@ export default function TabRouter({
|
||||
routeNames.indexOf(state.routes[state.index].name)
|
||||
);
|
||||
|
||||
let history = state.history.filter(it =>
|
||||
routes.find(r => r.key === it.key)
|
||||
let history = state.history.filter((it) =>
|
||||
routes.find((r) => r.key === it.key)
|
||||
);
|
||||
|
||||
if (!history.length) {
|
||||
@@ -236,7 +236,7 @@ export default function TabRouter({
|
||||
},
|
||||
|
||||
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) {
|
||||
return state;
|
||||
@@ -253,11 +253,11 @@ export default function TabRouter({
|
||||
|
||||
if (action.type === 'NAVIGATE' && action.payload.key) {
|
||||
index = state.routes.findIndex(
|
||||
route => route.key === action.payload.key
|
||||
(route) => route.key === action.payload.key
|
||||
);
|
||||
} else {
|
||||
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 index = state.routes.findIndex(
|
||||
route => route.key === previousKey
|
||||
(route) => route.key === previousKey
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
|
||||
@@ -84,6 +84,22 @@ it('resets state to new state with RESET', () => {
|
||||
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", () => {
|
||||
const routes = [
|
||||
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.4...@react-navigation/stack@5.2.5) (2020-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix swipe gestures requiring a lot of velocity to dismiss ([61f16d3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/61f16d3f25cbbcc00d699dd09c5f4abde9b17d5a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [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)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/stack",
|
||||
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
||||
"version": "5.2.3",
|
||||
"version": "5.2.5",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -40,7 +40,7 @@
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-native-community/masked-view": "^0.1.7",
|
||||
"@react-navigation/native": "^5.1.1",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
|
||||
@@ -40,7 +40,7 @@ function StackNavigator({
|
||||
React.useEffect(
|
||||
() =>
|
||||
navigation.addListener &&
|
||||
navigation.addListener('tabPress', e => {
|
||||
navigation.addListener('tabPress', (e) => {
|
||||
const isFocused = navigation.isFocused();
|
||||
|
||||
// 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 {
|
||||
let timeout: NodeJS.Timeout | number | undefined;
|
||||
|
||||
return function(this: any, ...args) {
|
||||
return function (this: any, ...args) {
|
||||
if (!timeout) {
|
||||
// eslint-disable-next-line babel/no-invalid-this
|
||||
func.apply(this, args);
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function HeaderContainer({
|
||||
<View
|
||||
onLayout={
|
||||
onContentHeightChange
|
||||
? e =>
|
||||
? (e) =>
|
||||
onContentHeightChange({
|
||||
route: scene.route,
|
||||
height: e.nativeEvent.layout.height,
|
||||
|
||||
@@ -38,7 +38,7 @@ type State = {
|
||||
};
|
||||
|
||||
const warnIfHeaderStylesDefined = (styles: Record<string, any>) => {
|
||||
Object.keys(styles).forEach(styleProp => {
|
||||
Object.keys(styles).forEach((styleProp) => {
|
||||
const value = styles[styleProp];
|
||||
|
||||
if (styleProp === 'position' && value === 'absolute') {
|
||||
|
||||
@@ -30,7 +30,7 @@ type Props = {
|
||||
export default function SafeAreaProviderCompat({ children }: Props) {
|
||||
return (
|
||||
<SafeAreaConsumer>
|
||||
{insets => {
|
||||
{(insets) => {
|
||||
if (insets) {
|
||||
// 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
|
||||
|
||||
@@ -271,14 +271,9 @@ export default class Card extends React.Component<Props> {
|
||||
velocity = nativeEvent.velocityX;
|
||||
}
|
||||
|
||||
const gestureDirectionFactor =
|
||||
gestureDirection === 'horizontal' || gestureDirection === 'vertical'
|
||||
? 1
|
||||
: -1;
|
||||
|
||||
const closing =
|
||||
gestureDirectionFactor *
|
||||
(translation + velocity * gestureVelocityImpact) >
|
||||
(translation + velocity * gestureVelocityImpact) *
|
||||
getInvertedMultiplier(gestureDirection) >
|
||||
distance / 2
|
||||
? velocity !== 0 || translation !== 0
|
||||
: false;
|
||||
|
||||
@@ -115,7 +115,7 @@ export default class StackView extends React.Component<Props, State> {
|
||||
// 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
|
||||
|
||||
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 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];
|
||||
|
||||
closingRouteKeys = closingRouteKeys.filter(
|
||||
key => key !== nextFocusedRoute.key
|
||||
(key) => key !== nextFocusedRoute.key
|
||||
);
|
||||
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
|
||||
|
||||
openingRouteKeys = openingRouteKeys.filter(
|
||||
key => key !== previousFocusedRoute.key
|
||||
(key) => key !== previousFocusedRoute.key
|
||||
);
|
||||
|
||||
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
|
||||
// So remove it from `openingRouteKeys` which will remove the animation
|
||||
openingRouteKeys = openingRouteKeys.filter(
|
||||
key => key !== nextFocusedRoute.key
|
||||
(key) => key !== nextFocusedRoute.key
|
||||
);
|
||||
|
||||
// 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(
|
||||
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
|
||||
@@ -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
|
||||
|
||||
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
|
||||
// So we also need to remove it from the opening list
|
||||
openingRouteKeys = openingRouteKeys.filter(
|
||||
key => key !== previousFocusedRoute.key
|
||||
(key) => key !== previousFocusedRoute.key
|
||||
);
|
||||
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
|
||||
@@ -271,13 +271,13 @@ export default class StackView extends React.Component<Props, State> {
|
||||
private getPreviousRoute = ({ route }: { route: Route<string> }) => {
|
||||
const { closingRouteKeys, replacingRouteKeys } = this.state;
|
||||
const routes = this.state.routes.filter(
|
||||
r =>
|
||||
(r) =>
|
||||
r.key === route.key ||
|
||||
(!closingRouteKeys.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];
|
||||
};
|
||||
@@ -298,12 +298,16 @@ export default class StackView extends React.Component<Props, State> {
|
||||
};
|
||||
|
||||
private handleOpenRoute = ({ route }: { route: Route<string> }) => {
|
||||
this.setState(state => ({
|
||||
this.setState((state) => ({
|
||||
routes: state.replacingRouteKeys.length
|
||||
? state.routes.filter(r => !state.replacingRouteKeys.includes(r.key))
|
||||
? state.routes.filter((r) => !state.replacingRouteKeys.includes(r.key))
|
||||
: state.routes,
|
||||
openingRouteKeys: state.openingRouteKeys.filter(key => key !== route.key),
|
||||
closingRouteKeys: state.closingRouteKeys.filter(key => key !== route.key),
|
||||
openingRouteKeys: state.openingRouteKeys.filter(
|
||||
(key) => key !== route.key
|
||||
),
|
||||
closingRouteKeys: state.closingRouteKeys.filter(
|
||||
(key) => key !== route.key
|
||||
),
|
||||
replacingRouteKeys: [],
|
||||
}));
|
||||
};
|
||||
@@ -311,7 +315,7 @@ export default class StackView extends React.Component<Props, State> {
|
||||
private handleCloseRoute = ({ route }: { route: Route<string> }) => {
|
||||
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
|
||||
// This will happen in when the route was closed from the card component
|
||||
// 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 {
|
||||
// We need to clean up any state tracking the route and pop it immediately
|
||||
this.setState(state => ({
|
||||
routes: state.routes.filter(r => r.key !== route.key),
|
||||
this.setState((state) => ({
|
||||
routes: state.routes.filter((r) => r.key !== route.key),
|
||||
openingRouteKeys: state.openingRouteKeys.filter(
|
||||
key => key !== route.key
|
||||
(key) => key !== route.key
|
||||
),
|
||||
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}>
|
||||
<SafeAreaProviderCompat>
|
||||
<SafeAreaConsumer>
|
||||
{insets => (
|
||||
{(insets) => (
|
||||
<KeyboardManager enabled={keyboardHandlingEnabled !== false}>
|
||||
{props => (
|
||||
{(props) => (
|
||||
<CardStack
|
||||
mode={mode}
|
||||
insets={insets as EdgeInsets}
|
||||
|
||||
@@ -9,7 +9,7 @@ const packages = path.join(__dirname, '..', 'packages');
|
||||
|
||||
const invalid = [];
|
||||
|
||||
fs.readdirSync(packages).forEach(name => {
|
||||
fs.readdirSync(packages).forEach((name) => {
|
||||
const dir = path.join(packages, name);
|
||||
|
||||
if (fs.statSync(path.join(packages, name)).isDirectory()) {
|
||||
@@ -26,6 +26,6 @@ fs.readdirSync(packages).forEach(name => {
|
||||
if (invalid.length) {
|
||||
console.log(
|
||||
'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:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@^1.19.1:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
||||
prettier@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.1.tgz#3f00ac71263be34684b2b2c8d7e7f63737592dac"
|
||||
integrity sha512-piXGBcY1zoFOG0MvHpNE5reAGseLmaCRifQ/fmfF49BcYkInEs/naD/unxGNAeOKFA5+JxVrPyMvMlpzcd20UA==
|
||||
|
||||
pretty-bytes@^4.0.2:
|
||||
version "4.0.2"
|
||||
|
||||
Reference in New Issue
Block a user