mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 22:39:41 +08:00
Copy native support to @react-navigation/native
This commit is contained in:
@@ -515,6 +515,25 @@
|
||||
path-to-regexp "^2.4.0"
|
||||
query-string "^6.2.0"
|
||||
|
||||
"@react-navigation/core@^3.0.0-alpha.4":
|
||||
version "3.0.0-alpha.4"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-3.0.0-alpha.4.tgz#0167a8352e867ebd09e444aac42b315f569fb81d"
|
||||
integrity sha512-kj9PzNadCjPYU1NGzNrg6eb3KDTNECUzWL38Ef7yHwhNG6U62AbedLD8VtuSZHGAEFXnI68hhnuoIe+9f6aJ8w==
|
||||
dependencies:
|
||||
create-react-context "^0.2.3"
|
||||
hoist-non-react-statics "^3.0.1"
|
||||
path-to-regexp "^2.4.0"
|
||||
query-string "^6.2.0"
|
||||
|
||||
"@react-navigation/native@^3.0.0-alpha.2":
|
||||
version "3.0.0-alpha.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-3.0.0-alpha.2.tgz#c483a54ddb82768c0c2c6923a8007ac9c924b92d"
|
||||
integrity sha512-6bPR+g15gJQo5bER4oJ4lxTs0hk0rZOnrgMwI+MflAqlRwqUBseRHiBr5tvfssrkTu3Q2GqZ0eSucc6WQDBU/A==
|
||||
dependencies:
|
||||
"@react-navigation/core" "^3.0.0-alpha.4"
|
||||
hoist-non-react-statics "^3.0.1"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
abab@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^3.0.0-alpha.2",
|
||||
"@react-navigation/native": "^3.0.0-alpha.2",
|
||||
"react-lifecycles-compat": "^3",
|
||||
"react-native-gesture-handler": "^1.0.0",
|
||||
"react-native-safe-area-view": "0.11.0",
|
||||
@@ -89,7 +90,7 @@
|
||||
"<rootDir>/examples/"
|
||||
],
|
||||
"transformIgnorePatterns": [
|
||||
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|react-navigation-deprecated-tab-navigator|react-navigation-stack|@react-navigation/core)"
|
||||
"node_modules/(?!(jest-)?react-native|react-clone-referenced-element|react-navigation-deprecated-tab-navigator|react-navigation-stack|@react-navigation/core|@react-navigation/native)"
|
||||
]
|
||||
},
|
||||
"lint-staged": {
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
import createNavigationContainer, {
|
||||
_TESTING_ONLY_reset_container_count,
|
||||
} from '../createNavigationContainer';
|
||||
|
||||
import {
|
||||
NavigationActions,
|
||||
createNavigator,
|
||||
StackRouter,
|
||||
SwitchView,
|
||||
} from '@react-navigation/core';
|
||||
|
||||
function createStackNavigator(routeConfigMap, stackConfig = {}) {
|
||||
const router = StackRouter(routeConfigMap, stackConfig);
|
||||
return createNavigationContainer(
|
||||
createNavigator(SwitchView, router, stackConfig)
|
||||
);
|
||||
}
|
||||
|
||||
describe('NavigationContainer', () => {
|
||||
jest.useFakeTimers();
|
||||
beforeEach(() => {
|
||||
_TESTING_ONLY_reset_container_count();
|
||||
});
|
||||
|
||||
const FooScreen = () => <div />;
|
||||
const BarScreen = () => <div />;
|
||||
const BazScreen = () => <div />;
|
||||
const CarScreen = () => <div />;
|
||||
const DogScreen = () => <div />;
|
||||
const ElkScreen = () => <div />;
|
||||
const Stack = createStackNavigator(
|
||||
{
|
||||
foo: {
|
||||
screen: FooScreen,
|
||||
},
|
||||
bar: {
|
||||
screen: BarScreen,
|
||||
},
|
||||
baz: {
|
||||
screen: BazScreen,
|
||||
},
|
||||
car: {
|
||||
screen: CarScreen,
|
||||
},
|
||||
dog: {
|
||||
screen: DogScreen,
|
||||
},
|
||||
elk: {
|
||||
screen: ElkScreen,
|
||||
},
|
||||
},
|
||||
{
|
||||
initialRouteName: 'foo',
|
||||
}
|
||||
);
|
||||
const NavigationContainer = createNavigationContainer(Stack);
|
||||
|
||||
describe('state.nav', () => {
|
||||
it("should be preloaded with the router's initial state", () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
expect(navigationContainer.state.nav).toMatchObject({ index: 0 });
|
||||
expect(navigationContainer.state.nav.routes).toBeInstanceOf(Array);
|
||||
expect(navigationContainer.state.nav.routes.length).toBe(1);
|
||||
expect(navigationContainer.state.nav.routes[0]).toMatchObject({
|
||||
routeName: 'foo',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('dispatch', () => {
|
||||
it('returns true when given a valid action', () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
jest.runOnlyPendingTimers();
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'bar' })
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
it('returns false when given an invalid action', () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
jest.runOnlyPendingTimers();
|
||||
expect(navigationContainer.dispatch(NavigationActions.back())).toEqual(
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('updates state.nav with an action by the next tick', () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'bar' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Fake the passing of a tick
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(navigationContainer.state.nav).toMatchObject({
|
||||
index: 1,
|
||||
routes: [{ routeName: 'foo' }, { routeName: 'bar' }],
|
||||
});
|
||||
});
|
||||
|
||||
it('does not discard actions when called twice in one tick', () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
const initialState = JSON.parse(
|
||||
JSON.stringify(navigationContainer.state.nav)
|
||||
);
|
||||
|
||||
// First dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'bar' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Make sure that the test runner has NOT synchronously applied setState before the tick
|
||||
expect(navigationContainer.state.nav).toMatchObject(initialState);
|
||||
|
||||
// Second dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'baz' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Fake the passing of a tick
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(navigationContainer.state.nav).toMatchObject({
|
||||
index: 2,
|
||||
routes: [
|
||||
{ routeName: 'foo' },
|
||||
{ routeName: 'bar' },
|
||||
{ routeName: 'baz' },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('does not discard actions when called more than 2 times in one tick', () => {
|
||||
const navigationContainer = renderer
|
||||
.create(<NavigationContainer />)
|
||||
.getInstance();
|
||||
const initialState = JSON.parse(
|
||||
JSON.stringify(navigationContainer.state.nav)
|
||||
);
|
||||
|
||||
// First dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'bar' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Make sure that the test runner has NOT synchronously applied setState before the tick
|
||||
expect(navigationContainer.state.nav).toMatchObject(initialState);
|
||||
|
||||
// Second dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'baz' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Third dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'car' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Fourth dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'dog' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Fifth dispatch
|
||||
expect(
|
||||
navigationContainer.dispatch(
|
||||
NavigationActions.navigate({ routeName: 'elk' })
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
// Fake the passing of a tick
|
||||
jest.runOnlyPendingTimers();
|
||||
|
||||
expect(navigationContainer.state.nav).toMatchObject({
|
||||
index: 5,
|
||||
routes: [
|
||||
{ routeName: 'foo' },
|
||||
{ routeName: 'bar' },
|
||||
{ routeName: 'baz' },
|
||||
{ routeName: 'car' },
|
||||
{ routeName: 'dog' },
|
||||
{ routeName: 'elk' },
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('warnings', () => {
|
||||
function spyConsole() {
|
||||
let spy = {};
|
||||
|
||||
beforeEach(() => {
|
||||
spy.console = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
spy.console.mockRestore();
|
||||
});
|
||||
|
||||
return spy;
|
||||
}
|
||||
|
||||
describe('detached navigators', () => {
|
||||
beforeEach(() => {
|
||||
_TESTING_ONLY_reset_container_count();
|
||||
});
|
||||
|
||||
let spy = spyConsole();
|
||||
|
||||
it('warns when you render more than one container explicitly', () => {
|
||||
class BlankScreen extends React.Component {
|
||||
render() {
|
||||
return <View />;
|
||||
}
|
||||
}
|
||||
|
||||
class RootScreen extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<View>
|
||||
<ChildNavigator />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ChildNavigator = createNavigationContainer(
|
||||
createStackNavigator({
|
||||
Child: BlankScreen,
|
||||
})
|
||||
);
|
||||
|
||||
const RootStack = createNavigationContainer(
|
||||
createStackNavigator({
|
||||
Root: RootScreen,
|
||||
})
|
||||
);
|
||||
|
||||
renderer.create(<RootStack />).toJSON();
|
||||
expect(spy).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`NavigationContainer warnings detached navigators warns when you render more than one container explicitly 1`] = `
|
||||
Object {
|
||||
"console": [MockFunction] {
|
||||
"calls": Array [
|
||||
Array [
|
||||
"You should only render one navigator explicitly in your app, and other navigators should by rendered by including them in that navigator. Full details at: https://reactnavigation.org/docs/common-mistakes.html#explicitly-rendering-more-than-one-navigator",
|
||||
],
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
@@ -1,385 +0,0 @@
|
||||
import React from 'react';
|
||||
import { AsyncStorage, Linking, Platform, BackHandler } from 'react-native';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
|
||||
import {
|
||||
NavigationActions,
|
||||
pathUtils,
|
||||
getNavigation,
|
||||
} from '@react-navigation/core';
|
||||
import invariant from './utils/invariant';
|
||||
import docsUrl from './utils/docsUrl';
|
||||
|
||||
const { urlToPathAndParams } = pathUtils;
|
||||
|
||||
function isStateful(props) {
|
||||
return !props.navigation;
|
||||
}
|
||||
|
||||
function validateProps(props) {
|
||||
if (isStateful(props)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { navigation, screenProps, ...containerProps } = props;
|
||||
|
||||
const keys = Object.keys(containerProps);
|
||||
|
||||
if (keys.length !== 0) {
|
||||
throw new Error(
|
||||
'This navigator has both navigation and container props, so it is ' +
|
||||
`unclear if it should own its own state. Remove props: "${keys.join(
|
||||
', '
|
||||
)}" ` +
|
||||
'if the navigator should get its state from the navigation prop. If the ' +
|
||||
'navigator should maintain its own state, do not pass a navigation prop.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Track the number of stateful container instances. Warn if >0 and not using the
|
||||
// detached prop to explicitly acknowledge the behavior. We should deprecated implicit
|
||||
// stateful navigation containers in a future release and require a provider style pattern
|
||||
// instead in order to eliminate confusion entirely.
|
||||
let _statefulContainerCount = 0;
|
||||
export function _TESTING_ONLY_reset_container_count() {
|
||||
_statefulContainerCount = 0;
|
||||
}
|
||||
|
||||
// We keep a global flag to catch errors during the state persistence hydrating scenario.
|
||||
// The innermost navigator who catches the error will dispatch a new init action.
|
||||
let _reactNavigationIsHydratingState = false;
|
||||
// Unfortunate to use global state here, but it seems necessesary for the time
|
||||
// being. There seems to be some problems with cascading componentDidCatch
|
||||
// handlers. Ideally the inner non-stateful navigator catches the error and
|
||||
// re-throws it, to be caught by the top-level stateful navigator.
|
||||
|
||||
/**
|
||||
* Create an HOC that injects the navigation and manages the navigation state
|
||||
* in case it's not passed from above.
|
||||
* This allows to use e.g. the StackNavigator and TabNavigator as root-level
|
||||
* components.
|
||||
*/
|
||||
export default function createNavigationContainer(Component) {
|
||||
class NavigationContainer extends React.Component {
|
||||
subs = null;
|
||||
|
||||
static router = Component.router;
|
||||
static navigationOptions = null;
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
validateProps(nextProps);
|
||||
return null;
|
||||
}
|
||||
|
||||
_actionEventSubscribers = new Set();
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
validateProps(props);
|
||||
|
||||
this._initialAction = NavigationActions.init();
|
||||
|
||||
if (this._isStateful()) {
|
||||
this.subs = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
if (!this._isMounted) {
|
||||
this.subs && this.subs.remove();
|
||||
} else {
|
||||
// dispatch returns true if the action results in a state change,
|
||||
// and false otherwise. This maps well to what BackHandler expects
|
||||
// from a callback -- true if handled, false if not handled
|
||||
return this.dispatch(NavigationActions.back());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.state = {
|
||||
nav:
|
||||
this._isStateful() && !props.persistenceKey
|
||||
? Component.router.getStateForAction(this._initialAction)
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
_renderLoading() {
|
||||
return this.props.renderLoadingExperimental
|
||||
? this.props.renderLoadingExperimental()
|
||||
: null;
|
||||
}
|
||||
|
||||
_isStateful() {
|
||||
return isStateful(this.props);
|
||||
}
|
||||
|
||||
_validateProps(props) {
|
||||
if (this._isStateful()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { navigation, screenProps, ...containerProps } = props;
|
||||
|
||||
const keys = Object.keys(containerProps);
|
||||
|
||||
if (keys.length !== 0) {
|
||||
throw new Error(
|
||||
'This navigator has both navigation and container props, so it is ' +
|
||||
`unclear if it should own its own state. Remove props: "${keys.join(
|
||||
', '
|
||||
)}" ` +
|
||||
'if the navigator should get its state from the navigation prop. If the ' +
|
||||
'navigator should maintain its own state, do not pass a navigation prop.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_handleOpenURL = ({ url }) => {
|
||||
const { enableURLHandling, uriPrefix } = this.props;
|
||||
if (enableURLHandling === false) {
|
||||
return;
|
||||
}
|
||||
const parsedUrl = urlToPathAndParams(url, uriPrefix);
|
||||
if (parsedUrl) {
|
||||
const { path, params } = parsedUrl;
|
||||
const action = Component.router.getActionForPathAndParams(path, params);
|
||||
if (action) {
|
||||
this.dispatch(action);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_onNavigationStateChange(prevNav, nav, action) {
|
||||
if (
|
||||
typeof this.props.onNavigationStateChange === 'undefined' &&
|
||||
this._isStateful() &&
|
||||
!!process.env.REACT_NAV_LOGGING
|
||||
) {
|
||||
/* eslint-disable no-console */
|
||||
if (console.group) {
|
||||
console.group('Navigation Dispatch: ');
|
||||
console.log('Action: ', action);
|
||||
console.log('New State: ', nav);
|
||||
console.log('Last State: ', prevNav);
|
||||
console.groupEnd();
|
||||
} else {
|
||||
console.log('Navigation Dispatch: ', {
|
||||
action,
|
||||
newState: nav,
|
||||
lastState: prevNav,
|
||||
});
|
||||
}
|
||||
/* eslint-enable no-console */
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof this.props.onNavigationStateChange === 'function') {
|
||||
this.props.onNavigationStateChange(prevNav, nav, action);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
// Clear cached _navState every tick
|
||||
if (this._navState === this.state.nav) {
|
||||
this._navState = null;
|
||||
}
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
this._isMounted = true;
|
||||
if (!this._isStateful()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (__DEV__ && !this.props.detached) {
|
||||
if (_statefulContainerCount > 0) {
|
||||
// Temporarily only show this on iOS due to this issue:
|
||||
// https://github.com/react-navigation/react-navigation/issues/4196#issuecomment-390827829
|
||||
if (Platform.OS === 'ios') {
|
||||
console.warn(
|
||||
`You should only render one navigator explicitly in your app, and other navigators should by rendered by including them in that navigator. Full details at: ${docsUrl(
|
||||
'common-mistakes.html#explicitly-rendering-more-than-one-navigator'
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_statefulContainerCount++;
|
||||
Linking.addEventListener('url', this._handleOpenURL);
|
||||
|
||||
// Pull out anything that can impact state
|
||||
const { persistenceKey, uriPrefix, enableURLHandling } = this.props;
|
||||
let parsedUrl = null;
|
||||
let startupStateJSON = null;
|
||||
if (enableURLHandling !== false) {
|
||||
startupStateJSON =
|
||||
persistenceKey && (await AsyncStorage.getItem(persistenceKey));
|
||||
const url = await Linking.getInitialURL();
|
||||
parsedUrl = url && urlToPathAndParams(url, uriPrefix);
|
||||
}
|
||||
|
||||
// Initialize state. This must be done *after* any async code
|
||||
// so we don't end up with a different value for this.state.nav
|
||||
// due to changes while async function was resolving
|
||||
let action = this._initialAction;
|
||||
let startupState = this.state.nav;
|
||||
if (!startupState) {
|
||||
!!process.env.REACT_NAV_LOGGING &&
|
||||
console.log('Init new Navigation State');
|
||||
startupState = Component.router.getStateForAction(action);
|
||||
}
|
||||
|
||||
// Pull persisted state from AsyncStorage
|
||||
if (startupStateJSON) {
|
||||
try {
|
||||
startupState = JSON.parse(startupStateJSON);
|
||||
_reactNavigationIsHydratingState = true;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Pull state out of URL
|
||||
if (parsedUrl) {
|
||||
const { path, params } = parsedUrl;
|
||||
const urlAction = Component.router.getActionForPathAndParams(
|
||||
path,
|
||||
params
|
||||
);
|
||||
if (urlAction) {
|
||||
!!process.env.REACT_NAV_LOGGING &&
|
||||
console.log('Applying Navigation Action for Initial URL:', url);
|
||||
action = urlAction;
|
||||
startupState = Component.router.getStateForAction(
|
||||
urlAction,
|
||||
startupState
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const dispatchActions = () =>
|
||||
this._actionEventSubscribers.forEach(subscriber =>
|
||||
subscriber({
|
||||
type: 'action',
|
||||
action,
|
||||
state: this.state.nav,
|
||||
lastState: null,
|
||||
})
|
||||
);
|
||||
|
||||
if (startupState === this.state.nav) {
|
||||
dispatchActions();
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ nav: startupState }, () => {
|
||||
_reactNavigationIsHydratingState = false;
|
||||
dispatchActions();
|
||||
});
|
||||
}
|
||||
|
||||
componentDidCatch(e, errorInfo) {
|
||||
if (_reactNavigationIsHydratingState) {
|
||||
_reactNavigationIsHydratingState = false;
|
||||
console.warn(
|
||||
'Uncaught exception while starting app from persisted navigation state! Trying to render again with a fresh navigation state..'
|
||||
);
|
||||
this.dispatch(NavigationActions.init());
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
_persistNavigationState = async nav => {
|
||||
const { persistenceKey } = this.props;
|
||||
if (!persistenceKey) {
|
||||
return;
|
||||
}
|
||||
await AsyncStorage.setItem(persistenceKey, JSON.stringify(nav));
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
Linking.removeEventListener('url', this._handleOpenURL);
|
||||
this.subs && this.subs.remove();
|
||||
|
||||
if (this._isStateful()) {
|
||||
_statefulContainerCount--;
|
||||
}
|
||||
}
|
||||
|
||||
// Per-tick temporary storage for state.nav
|
||||
|
||||
dispatch = action => {
|
||||
if (this.props.navigation) {
|
||||
return this.props.navigation.dispatch(action);
|
||||
}
|
||||
|
||||
// navState will have the most up-to-date value, because setState sometimes behaves asyncronously
|
||||
this._navState = this._navState || this.state.nav;
|
||||
const lastNavState = this._navState;
|
||||
invariant(lastNavState, 'should be set in constructor if stateful');
|
||||
const reducedState = Component.router.getStateForAction(
|
||||
action,
|
||||
lastNavState
|
||||
);
|
||||
const navState = reducedState === null ? lastNavState : reducedState;
|
||||
|
||||
const dispatchActionEvents = () => {
|
||||
this._actionEventSubscribers.forEach(subscriber =>
|
||||
subscriber({
|
||||
type: 'action',
|
||||
action,
|
||||
state: navState,
|
||||
lastState: lastNavState,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
if (reducedState === null) {
|
||||
// The router will return null when action has been handled and the state hasn't changed.
|
||||
// dispatch returns true when something has been handled.
|
||||
dispatchActionEvents();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (navState !== lastNavState) {
|
||||
// Cache updates to state.nav during the tick to ensure that subsequent calls will not discard this change
|
||||
this._navState = navState;
|
||||
this.setState({ nav: navState }, () => {
|
||||
this._onNavigationStateChange(lastNavState, navState, action);
|
||||
dispatchActionEvents();
|
||||
this._persistNavigationState(navState);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
dispatchActionEvents();
|
||||
return false;
|
||||
};
|
||||
|
||||
_getScreenProps = () => this.props.screenProps;
|
||||
|
||||
render() {
|
||||
let navigation = this.props.navigation;
|
||||
if (this._isStateful()) {
|
||||
const navState = this.state.nav;
|
||||
if (!navState) {
|
||||
return this._renderLoading();
|
||||
}
|
||||
if (!this._navigation || this._navigation.state !== navState) {
|
||||
this._navigation = getNavigation(
|
||||
Component.router,
|
||||
navState,
|
||||
this.dispatch,
|
||||
this._actionEventSubscribers,
|
||||
this._getScreenProps,
|
||||
() => this._navigation
|
||||
);
|
||||
}
|
||||
navigation = this._navigation;
|
||||
}
|
||||
invariant(navigation, 'failed to get navigation');
|
||||
return <Component {...this.props} navigation={navigation} />;
|
||||
}
|
||||
}
|
||||
|
||||
return polyfill(NavigationContainer);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import createNavigationContainer from '../createNavigationContainer';
|
||||
import { createNavigationContainer } from '@react-navigation/native';
|
||||
import { createSwitchNavigator } from '@react-navigation/core';
|
||||
|
||||
const SwitchNavigator = (routeConfigs, config = {}) => {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import React from 'react';
|
||||
import { TextInput } from 'react-native';
|
||||
|
||||
export default (Navigator, navigatorConfig) =>
|
||||
class KeyboardAwareNavigator extends React.Component {
|
||||
static router = Navigator.router;
|
||||
_previouslyFocusedTextInput = null;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Navigator
|
||||
{...this.props}
|
||||
onGestureBegin={this._handleGestureBegin}
|
||||
onGestureCanceled={this._handleGestureCanceled}
|
||||
onGestureFinish={this._handleGestureFinish}
|
||||
onTransitionStart={this._handleTransitionStart}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_handleGestureBegin = () => {
|
||||
this._previouslyFocusedTextInput = TextInput.State.currentlyFocusedField();
|
||||
if (this._previouslyFocusedTextInput) {
|
||||
TextInput.State.blurTextInput(this._previouslyFocusedTextInput);
|
||||
}
|
||||
this.props.onGestureBegin && this.props.onGestureBegin();
|
||||
};
|
||||
|
||||
_handleGestureCanceled = () => {
|
||||
if (this._previouslyFocusedTextInput) {
|
||||
TextInput.State.focusTextInput(this._previouslyFocusedTextInput);
|
||||
}
|
||||
this.props.onGestureCanceled && this.props.onGestureCanceled();
|
||||
};
|
||||
|
||||
_handleGestureFinish = () => {
|
||||
this._previouslyFocusedTextInput = null;
|
||||
this.props.onGestureFinish && this.props.onGestureFinish();
|
||||
};
|
||||
|
||||
_handleTransitionStart = (transitionProps, prevTransitionProps) => {
|
||||
// TODO: We should not even have received the transition start event
|
||||
// in the case where the index did not change, I believe. We
|
||||
// should revisit this after 2.0 release.
|
||||
if (transitionProps.index !== prevTransitionProps.index) {
|
||||
const currentField = TextInput.State.currentlyFocusedField();
|
||||
if (currentField) {
|
||||
TextInput.State.blurTextInput(currentField);
|
||||
}
|
||||
}
|
||||
|
||||
const onTransitionStart =
|
||||
this.props.onTransitionStart || navigatorConfig.onTransitionStart;
|
||||
onTransitionStart &&
|
||||
onTransitionStart(transitionProps, prevTransitionProps);
|
||||
};
|
||||
};
|
||||
9
src/react-navigation.js
vendored
9
src/react-navigation.js
vendored
@@ -3,8 +3,9 @@
|
||||
module.exports = {
|
||||
// Core
|
||||
get createNavigationContainer() {
|
||||
return require('./createNavigationContainer').default;
|
||||
return require('@react-navigation/native').createNavigationContainer;
|
||||
},
|
||||
|
||||
get StateUtils() {
|
||||
return require('@react-navigation/core').StateUtils;
|
||||
},
|
||||
@@ -17,7 +18,7 @@ module.exports = {
|
||||
return require('@react-navigation/core').createNavigator;
|
||||
},
|
||||
get createKeyboardAwareNavigator() {
|
||||
return require('./navigators/createKeyboardAwareNavigator').default;
|
||||
return require('@react-navigation/native').createKeyboardAwareNavigator;
|
||||
},
|
||||
get NavigationProvider() {
|
||||
return require('@react-navigation/core').NavigationProvider;
|
||||
@@ -135,7 +136,7 @@ module.exports = {
|
||||
return require('@react-navigation/core').SceneView;
|
||||
},
|
||||
get ResourceSavingSceneView() {
|
||||
return require('./views/ResourceSavingSceneView').default;
|
||||
return require('@react-navigation/native').ResourceSavingSceneView;
|
||||
},
|
||||
|
||||
// Header
|
||||
@@ -201,6 +202,6 @@ module.exports = {
|
||||
return require('@react-navigation/core').withNavigationFocus;
|
||||
},
|
||||
get withOrientation() {
|
||||
return require('./views/withOrientation').default;
|
||||
return require('@react-navigation/native').withOrientation;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Use invariant() to assert state which your program assumes to be true.
|
||||
*
|
||||
* Provide sprintf-style format (only %s is supported) and arguments
|
||||
* to provide information about what broke and what you were
|
||||
* expecting.
|
||||
*
|
||||
* The invariant message will be stripped in production, but the invariant
|
||||
* will remain to ensure logic does not differ in production.
|
||||
*/
|
||||
|
||||
var validateFormat = function(format) {};
|
||||
|
||||
if (__DEV__) {
|
||||
validateFormat = function(format) {
|
||||
if (format === undefined) {
|
||||
throw new Error('invariant requires an error message argument');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function invariant(condition, format, a, b, c, d, e, f) {
|
||||
validateFormat(format);
|
||||
|
||||
if (!condition) {
|
||||
var error;
|
||||
if (format === undefined) {
|
||||
error = new Error(
|
||||
'Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.'
|
||||
);
|
||||
} else {
|
||||
var args = [a, b, c, d, e, f];
|
||||
var argIndex = 0;
|
||||
error = new Error(
|
||||
format.replace(/%s/g, function() {
|
||||
return args[argIndex++];
|
||||
})
|
||||
);
|
||||
error.name = 'Invariant Violation';
|
||||
}
|
||||
|
||||
error.framesToPop = 1; // we don't care about invariant's own frame
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = invariant;
|
||||
@@ -1,79 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Platform, StyleSheet, View } from 'react-native';
|
||||
import { polyfill } from 'react-lifecycles-compat';
|
||||
|
||||
import { SceneView } from '@react-navigation/core';
|
||||
|
||||
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container
|
||||
|
||||
class ResourceSavingSceneView extends React.PureComponent {
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (nextProps.isFocused && !prevState.awake) {
|
||||
return { awake: true };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
awake: props.lazy ? props.isFocused : true,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { awake } = this.state;
|
||||
const {
|
||||
isFocused,
|
||||
childNavigation,
|
||||
navigation,
|
||||
removeClippedSubviews,
|
||||
lazy,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={styles.container}
|
||||
collapsable={false}
|
||||
removeClippedSubviews={
|
||||
Platform.OS === 'android'
|
||||
? removeClippedSubviews
|
||||
: !isFocused && removeClippedSubviews
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
this._mustAlwaysBeVisible() || isFocused
|
||||
? styles.innerAttached
|
||||
: styles.innerDetached
|
||||
}
|
||||
>
|
||||
{awake ? <SceneView {...rest} navigation={childNavigation} /> : null}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_mustAlwaysBeVisible = () => {
|
||||
return this.props.animationEnabled || this.props.swipeEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
innerAttached: {
|
||||
flex: 1,
|
||||
},
|
||||
innerDetached: {
|
||||
flex: 1,
|
||||
top: FAR_FAR_AWAY,
|
||||
},
|
||||
});
|
||||
|
||||
export default polyfill(ResourceSavingSceneView);
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"extends": "../../../.eslintrc",
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const {
|
||||
TabView,
|
||||
TabBarBottom,
|
||||
} = require('react-navigation-deprecated-tab-navigator');
|
||||
|
||||
const dummyEventSubscriber = (name, handler) => ({
|
||||
remove: () => {},
|
||||
});
|
||||
|
||||
describe('TabBarBottom', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
it('renders successfully', () => {
|
||||
const route = { key: 's1', routeName: 's1' };
|
||||
const navigation = {
|
||||
state: {
|
||||
index: 0,
|
||||
routes: [route],
|
||||
},
|
||||
addListener: dummyEventSubscriber,
|
||||
};
|
||||
|
||||
const rendered = renderer
|
||||
.create(
|
||||
<TabView
|
||||
tabBarComponent={TabBarBottom}
|
||||
navigation={navigation}
|
||||
navigationConfig={{}}
|
||||
descriptors={{
|
||||
s1: {
|
||||
state: route,
|
||||
key: route.key,
|
||||
options: {},
|
||||
navigation: { state: route },
|
||||
getComponent: () => View,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)
|
||||
.toJSON();
|
||||
|
||||
expect(rendered).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
@@ -1,144 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TabBarBottom renders successfully 1`] = `
|
||||
<View
|
||||
collapsable={false}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"flex": 1,
|
||||
"overflow": "hidden",
|
||||
},
|
||||
Object {
|
||||
"flex": 1,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
onLayout={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<RCTScrollView
|
||||
DEPRECATED_sendUpdatedChildFrames={false}
|
||||
alwaysBounceHorizontal={false}
|
||||
alwaysBounceVertical={false}
|
||||
automaticallyAdjustContentInsets={false}
|
||||
bounces={false}
|
||||
contentContainerStyle={
|
||||
Object {
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
contentOffset={
|
||||
Object {
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
}
|
||||
}
|
||||
directionalLockEnabled={true}
|
||||
horizontal={true}
|
||||
keyboardDismissMode="on-drag"
|
||||
keyboardShouldPersistTaps="always"
|
||||
onContentSizeChange={null}
|
||||
onMomentumScrollBegin={[Function]}
|
||||
onMomentumScrollEnd={[Function]}
|
||||
onResponderGrant={[Function]}
|
||||
onResponderReject={[Function]}
|
||||
onResponderRelease={[Function]}
|
||||
onResponderTerminate={undefined}
|
||||
onResponderTerminationRequest={[Function]}
|
||||
onScroll={[Function]}
|
||||
onScrollBeginDrag={[Function]}
|
||||
onScrollEndDrag={[Function]}
|
||||
onScrollShouldSetResponder={[Function]}
|
||||
onStartShouldSetResponder={[Function]}
|
||||
onStartShouldSetResponderCapture={[Function]}
|
||||
onTouchCancel={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
onTouchMove={[Function]}
|
||||
onTouchStart={[Function]}
|
||||
overScrollMode="never"
|
||||
pagingEnabled={true}
|
||||
scrollEnabled={undefined}
|
||||
scrollEventThrottle={1}
|
||||
scrollsToTop={false}
|
||||
sendMomentumEvents={true}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"flexDirection": "row",
|
||||
"flexGrow": 1,
|
||||
"flexShrink": 1,
|
||||
"overflow": "scroll",
|
||||
},
|
||||
Object {
|
||||
"flex": 1,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<RCTScrollContentView
|
||||
collapsable={false}
|
||||
removeClippedSubviews={undefined}
|
||||
style={
|
||||
Array [
|
||||
Object {
|
||||
"flexDirection": "row",
|
||||
},
|
||||
Object {
|
||||
"flex": 1,
|
||||
},
|
||||
]
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
"overflow": "hidden",
|
||||
}
|
||||
}
|
||||
testID={undefined}
|
||||
>
|
||||
<View
|
||||
collapsable={false}
|
||||
removeClippedSubviews={false}
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
"overflow": "hidden",
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
style={
|
||||
Object {
|
||||
"flex": 1,
|
||||
}
|
||||
}
|
||||
>
|
||||
<View
|
||||
navigation={
|
||||
Object {
|
||||
"state": Object {
|
||||
"key": "s1",
|
||||
"routeName": "s1",
|
||||
},
|
||||
}
|
||||
}
|
||||
screenProps={undefined}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</RCTScrollContentView>
|
||||
</RCTScrollView>
|
||||
</View>
|
||||
</View>
|
||||
`;
|
||||
@@ -1,7 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`it adds isLandscape to props 1`] = `
|
||||
<View
|
||||
isLandscape={false}
|
||||
/>
|
||||
`;
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react';
|
||||
import { View } from 'react-native';
|
||||
import renderer from 'react-test-renderer';
|
||||
import withOrientation, { isOrientationLandscape } from '../withOrientation';
|
||||
|
||||
test('it adds isLandscape to props', () => {
|
||||
const WrappedComponent = withOrientation(View);
|
||||
const rendered = renderer.create(<WrappedComponent />).toJSON();
|
||||
expect(rendered).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('calculates orientation correctly', () => {
|
||||
const isLandscape = isOrientationLandscape({ width: 10, height: 1 });
|
||||
expect(isLandscape).toBeTruthy();
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Dimensions } from 'react-native';
|
||||
import hoistNonReactStatic from 'hoist-non-react-statics';
|
||||
|
||||
export const isOrientationLandscape = ({ width, height }) => width > height;
|
||||
|
||||
export default function(WrappedComponent) {
|
||||
class withOrientation extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const isLandscape = isOrientationLandscape(Dimensions.get('window'));
|
||||
this.state = { isLandscape };
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
Dimensions.addEventListener('change', this.handleOrientationChange);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Dimensions.removeEventListener('change', this.handleOrientationChange);
|
||||
}
|
||||
|
||||
handleOrientationChange = ({ window }) => {
|
||||
const isLandscape = isOrientationLandscape(window);
|
||||
this.setState({ isLandscape });
|
||||
};
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} {...this.state} />;
|
||||
}
|
||||
}
|
||||
|
||||
return hoistNonReactStatic(withOrientation, WrappedComponent);
|
||||
}
|
||||
67
yarn.lock
67
yarn.lock
@@ -28,6 +28,25 @@
|
||||
path-to-regexp "^2.4.0"
|
||||
query-string "^6.2.0"
|
||||
|
||||
"@react-navigation/core@^3.0.0-alpha.4":
|
||||
version "3.0.0-alpha.4"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-3.0.0-alpha.4.tgz#0167a8352e867ebd09e444aac42b315f569fb81d"
|
||||
integrity sha512-kj9PzNadCjPYU1NGzNrg6eb3KDTNECUzWL38Ef7yHwhNG6U62AbedLD8VtuSZHGAEFXnI68hhnuoIe+9f6aJ8w==
|
||||
dependencies:
|
||||
create-react-context "^0.2.3"
|
||||
hoist-non-react-statics "^3.0.1"
|
||||
path-to-regexp "^2.4.0"
|
||||
query-string "^6.2.0"
|
||||
|
||||
"@react-navigation/native@^3.0.0-alpha.2":
|
||||
version "3.0.0-alpha.2"
|
||||
resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-3.0.0-alpha.2.tgz#c483a54ddb82768c0c2c6923a8007ac9c924b92d"
|
||||
integrity sha512-6bPR+g15gJQo5bER4oJ4lxTs0hk0rZOnrgMwI+MflAqlRwqUBseRHiBr5tvfssrkTu3Q2GqZ0eSucc6WQDBU/A==
|
||||
dependencies:
|
||||
"@react-navigation/core" "^3.0.0-alpha.4"
|
||||
hoist-non-react-statics "^3.0.1"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
abab@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f"
|
||||
@@ -1600,9 +1619,9 @@ combined-stream@^1.0.5, combined-stream@~1.0.5, combined-stream@~1.0.6:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
commander@^2.11.0, commander@^2.9.0:
|
||||
version "2.18.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970"
|
||||
integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
||||
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
|
||||
|
||||
commander@~2.13.0:
|
||||
version "2.13.0"
|
||||
@@ -1892,9 +1911,9 @@ debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.1.0:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407"
|
||||
integrity sha512-D61LaDQPQkxJ5AUM2mbSJRbPkNs/TmdmOeLAi1hgDkpDfIfetSrjmWhccwtuResSwMbACjx/xXQofvM9CE/aeg==
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
@@ -2206,9 +2225,9 @@ eslint-plugin-import@^2.7.0:
|
||||
resolve "^1.6.0"
|
||||
|
||||
eslint-plugin-jsx-a11y@^6.0.2:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.1.tgz#7bf56dbe7d47d811d14dbb3ddff644aa656ce8e1"
|
||||
integrity sha512-JsxNKqa3TwmPypeXNnI75FntkUktGzI1wSa1LgNZdSOMI+B4sxnr1lSF8m8lPiz4mKiC+14ysZQM4scewUrP7A==
|
||||
version "6.1.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.2.tgz#69bca4890b36dcf0fe16dd2129d2d88b98f33f88"
|
||||
integrity sha512-7gSSmwb3A+fQwtw0arguwMdOdzmKUgnUcbSNlo+GjKLAQFuC2EZxWqG9XHRI8VscBJD5a8raz3RuxQNFW+XJbw==
|
||||
dependencies:
|
||||
aria-query "^3.0.0"
|
||||
array-includes "^3.0.3"
|
||||
@@ -2531,9 +2550,9 @@ fast-deep-equal@^1.0.0:
|
||||
integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=
|
||||
|
||||
fast-diff@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
|
||||
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
|
||||
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -4590,9 +4609,9 @@ minipass@^2.2.1, minipass@^2.3.3:
|
||||
yallist "^3.0.0"
|
||||
|
||||
minizlib@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb"
|
||||
integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42"
|
||||
integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==
|
||||
dependencies:
|
||||
minipass "^2.2.1"
|
||||
|
||||
@@ -4781,9 +4800,9 @@ npm-bundled@^1.0.1:
|
||||
integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==
|
||||
|
||||
npm-packlist@^1.1.6:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de"
|
||||
integrity sha512-CxKlZ24urLkJk+9kCm48RTQ7L4hsmgSVzEk0TLGPzzyuFxD7VNgy5Sl24tOLMzQv773a/NeJ1ce1DKeacqffEA==
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a"
|
||||
integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==
|
||||
dependencies:
|
||||
ignore-walk "^3.0.1"
|
||||
npm-bundled "^1.0.1"
|
||||
@@ -6032,9 +6051,9 @@ schedule@^0.5.0:
|
||||
object-assign "^4.1.1"
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@5.x, semver@^5.0.1, semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
|
||||
version "5.5.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477"
|
||||
integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
|
||||
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
|
||||
|
||||
semver@5.5.0:
|
||||
version "5.5.0"
|
||||
@@ -6268,9 +6287,9 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
spdx-correct@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.1.tgz#434434ff9d1726b4d9f4219d1004813d80639e30"
|
||||
integrity sha512-hxSPZbRZvSDuOvADntOElzJpenIR7wXJkuoUcUtS0erbgt2fgeaoPIYretfKpslMhfFDY4k0MZ2F5CUzhBsSvQ==
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.2.tgz#19bb409e91b47b1ad54159243f7312a858db3c2e"
|
||||
integrity sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==
|
||||
dependencies:
|
||||
spdx-expression-parse "^3.0.0"
|
||||
spdx-license-ids "^3.0.0"
|
||||
|
||||
Reference in New Issue
Block a user