mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-14 22:41:55 +08:00
Compare commits
6 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98a9487cda | ||
|
|
ff502820c7 | ||
|
|
30e510d123 | ||
|
|
114a5dc888 | ||
|
|
b4bbf9b0c3 | ||
|
|
98f0de088f |
@@ -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.0.0-alpha.9](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.8...@react-navigation/bottom-tabs@5.0.0-alpha.9) (2019-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* provide navigation prop in header ([30e510d](https://github.com/react-navigation/navigation-ex/commit/30e510d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.8](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.7...@react-navigation/bottom-tabs@5.0.0-alpha.8) (2019-09-16)
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.8",
|
||||
"version": "5.0.0-alpha.9",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -199,6 +199,7 @@ export type BottomTabBarOptions = {
|
||||
|
||||
export type BottomTabBarProps = BottomTabBarOptions & {
|
||||
state: TabNavigationState;
|
||||
descriptors: BottomTabDescriptorMap;
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
onTabPress: (props: { route: Route<string> }) => void;
|
||||
onTabLongPress: (props: { route: Route<string> }) => void;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Dimensions,
|
||||
} from 'react-native';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import { Route, NavigationContext } from '@react-navigation/core';
|
||||
|
||||
import TabBarIcon from './TabBarIcon';
|
||||
import TouchableWithoutFeedbackWrapper from './TouchableWithoutFeedbackWrapper';
|
||||
@@ -261,6 +261,7 @@ export default class TabBarBottom extends React.Component<Props, State> {
|
||||
render() {
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
keyboardHidesTabBar,
|
||||
activeBackgroundColor,
|
||||
inactiveBackgroundColor,
|
||||
@@ -337,26 +338,30 @@ export default class TabBarBottom extends React.Component<Props, State> {
|
||||
getButtonComponent({ route }) || TouchableWithoutFeedbackWrapper;
|
||||
|
||||
return (
|
||||
<ButtonComponent
|
||||
<NavigationContext.Provider
|
||||
key={route.key}
|
||||
onPress={() => onTabPress({ route })}
|
||||
onLongPress={() => onTabLongPress({ route })}
|
||||
testID={testID}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole={accessibilityRole}
|
||||
accessibilityStates={accessibilityStates}
|
||||
style={[
|
||||
styles.tab,
|
||||
{ backgroundColor },
|
||||
this.shouldUseHorizontalLabels()
|
||||
? styles.tabLandscape
|
||||
: styles.tabPortrait,
|
||||
tabStyle,
|
||||
]}
|
||||
value={descriptors[route.key].navigation}
|
||||
>
|
||||
{this.renderIcon(scene)}
|
||||
{this.renderLabel(scene)}
|
||||
</ButtonComponent>
|
||||
<ButtonComponent
|
||||
onPress={() => onTabPress({ route })}
|
||||
onLongPress={() => onTabLongPress({ route })}
|
||||
testID={testID}
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
accessibilityRole={accessibilityRole}
|
||||
accessibilityStates={accessibilityStates}
|
||||
style={[
|
||||
styles.tab,
|
||||
{ backgroundColor },
|
||||
this.shouldUseHorizontalLabels()
|
||||
? styles.tabLandscape
|
||||
: styles.tabPortrait,
|
||||
tabStyle,
|
||||
]}
|
||||
>
|
||||
{this.renderIcon(scene)}
|
||||
{this.renderLabel(scene)}
|
||||
</ButtonComponent>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
})}
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -177,6 +177,7 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
<TabBarComponent
|
||||
{...tabBarOptions}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
onTabPress={this.handleTabPress}
|
||||
onTabLongPress={this.handleTabLongPress}
|
||||
|
||||
@@ -3,6 +3,23 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.2](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.1...@react-navigation/compat@5.0.0-alpha.2) (2019-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* provide navigation prop in header ([30e510d](https://github.com/react-navigation/navigation-ex/commit/30e510d))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add createSwitchNavigator ([ff50282](https://github.com/react-navigation/navigation-ex/commit/ff50282))
|
||||
* add withNavigation and withNavigationFocus ([114a5dc](https://github.com/react-navigation/navigation-ex/commit/114a5dc))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# 5.0.0-alpha.1 (2019-09-16)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.0.0-alpha.1",
|
||||
"version": "5.0.0-alpha.2",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -7,15 +7,18 @@ import {
|
||||
import ScreenPropsContext from './ScreenPropsContext';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
|
||||
type Props = {
|
||||
navigation: NavigationProp<ParamListBase>;
|
||||
route: RouteProp<ParamListBase, string>;
|
||||
type Props<ParamList extends ParamListBase> = {
|
||||
navigation: NavigationProp<ParamList>;
|
||||
route: RouteProp<ParamList, string>;
|
||||
component: React.ComponentType<any>;
|
||||
};
|
||||
|
||||
function ScreenComponent(props: Props) {
|
||||
function ScreenComponent<ParamList extends ParamListBase>(
|
||||
props: Props<ParamList>
|
||||
) {
|
||||
const navigation = React.useMemo(
|
||||
() => createCompatNavigationProp(props.navigation, props.route),
|
||||
() =>
|
||||
createCompatNavigationProp(props.navigation as any, props.route as any),
|
||||
[props.navigation, props.route]
|
||||
);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
RouteProp,
|
||||
} from '@react-navigation/core';
|
||||
import * as helpers from './helpers';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
type EventName = 'willFocus' | 'willBlur' | 'didFocus' | 'didBlur' | 'refocus';
|
||||
|
||||
@@ -14,32 +15,28 @@ const blurSubscriptions = new WeakMap<() => void, () => void>();
|
||||
const refocusSubscriptions = new WeakMap<() => void, () => void>();
|
||||
|
||||
export default function createCompatNavigationProp<
|
||||
ParamList extends ParamListBase
|
||||
NavigationPropType extends NavigationProp<ParamListBase>,
|
||||
ParamList extends ParamListBase = NavigationPropType extends NavigationProp<
|
||||
infer P
|
||||
>
|
||||
? P
|
||||
: ParamListBase
|
||||
>(
|
||||
navigation: NavigationProp<ParamList>,
|
||||
navigation: NavigationPropType,
|
||||
state:
|
||||
| (RouteProp<ParamList, keyof ParamList> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
})
|
||||
| NavigationState
|
||||
| PartialState<NavigationState>
|
||||
) {
|
||||
): CompatNavigationProp<NavigationPropType> {
|
||||
return {
|
||||
...navigation,
|
||||
...Object.entries(helpers).reduce<{
|
||||
[key: string]: (...args: any[]) => void;
|
||||
}>((acc, [name, method]) => {
|
||||
}>((acc, [name, method]: [string, Function]) => {
|
||||
if (name in navigation) {
|
||||
acc[name] = (...args: any[]) => {
|
||||
// @ts-ignore
|
||||
const payload = method(...args);
|
||||
|
||||
navigation.dispatch(
|
||||
typeof payload === 'function'
|
||||
? payload(navigation.dangerouslyGetState())
|
||||
: payload
|
||||
);
|
||||
};
|
||||
acc[name] = (...args: any[]) => navigation.dispatch(method(...args));
|
||||
}
|
||||
|
||||
return acc;
|
||||
@@ -188,5 +185,5 @@ export default function createCompatNavigationProp<
|
||||
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
} as any;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function createCompatNavigatorFactory<
|
||||
navigation,
|
||||
route,
|
||||
}: {
|
||||
navigation: NavigationProp<ParamList>;
|
||||
navigation: NavigationPropType;
|
||||
route: RouteProp<ParamList, keyof ParamList> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
};
|
||||
@@ -101,10 +101,9 @@ export default function createCompatNavigatorFactory<
|
||||
typeof routeNavigationOptions === 'function' ||
|
||||
typeof screenNavigationOptions === 'function'
|
||||
? {
|
||||
navigation: createCompatNavigationProp<ParamList>(
|
||||
navigation,
|
||||
route
|
||||
),
|
||||
navigation: createCompatNavigationProp<
|
||||
NavigationPropType
|
||||
>(navigation, route),
|
||||
navigationOptions: defaultNavigationOptions || {},
|
||||
screenProps,
|
||||
}
|
||||
|
||||
28
packages/compat/src/createSwitchNavigator.tsx
Normal file
28
packages/compat/src/createSwitchNavigator.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
useNavigationBuilder,
|
||||
createNavigator,
|
||||
DefaultNavigatorOptions,
|
||||
} from '@react-navigation/core';
|
||||
import {
|
||||
TabRouter,
|
||||
TabRouterOptions,
|
||||
TabNavigationState,
|
||||
} from '@react-navigation/routers';
|
||||
import createCompatNavigatorFactory from './createCompatNavigatorFactory';
|
||||
|
||||
type Props = DefaultNavigatorOptions<{}> & TabRouterOptions;
|
||||
|
||||
function SwitchNavigator(props: Props) {
|
||||
const { state, descriptors } = useNavigationBuilder<
|
||||
TabNavigationState,
|
||||
TabRouterOptions,
|
||||
{},
|
||||
{}
|
||||
>(TabRouter, props);
|
||||
|
||||
return descriptors[state.routes[state.index].key].render();
|
||||
}
|
||||
|
||||
export default createCompatNavigatorFactory(
|
||||
createNavigator<{}, typeof SwitchNavigator>(SwitchNavigator)
|
||||
);
|
||||
@@ -9,4 +9,13 @@ export {
|
||||
default as createCompatNavigatorFactory,
|
||||
} from './createCompatNavigatorFactory';
|
||||
|
||||
export {
|
||||
default as createCompatNavigationProp,
|
||||
} from './createCompatNavigationProp';
|
||||
|
||||
export { default as createSwitchNavigator } from './createSwitchNavigator';
|
||||
|
||||
export { default as withNavigation } from './withNavigation';
|
||||
export { default as withNavigationFocus } from './withNavigationFocus';
|
||||
|
||||
export * from './types';
|
||||
|
||||
25
packages/compat/src/useCompatNavigation.tsx
Normal file
25
packages/compat/src/useCompatNavigation.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
useNavigation,
|
||||
useRoute,
|
||||
NavigationProp,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
import createCompatNavigationProp from './createCompatNavigationProp';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
export default function useCompatNavigation<
|
||||
T extends NavigationProp<ParamListBase>
|
||||
>() {
|
||||
const navigation = useNavigation();
|
||||
const route = useRoute();
|
||||
|
||||
return React.useMemo(
|
||||
() =>
|
||||
createCompatNavigationProp(
|
||||
navigation,
|
||||
route as any
|
||||
) as CompatNavigationProp<T>,
|
||||
[navigation, route]
|
||||
);
|
||||
}
|
||||
33
packages/compat/src/withNavigation.tsx
Normal file
33
packages/compat/src/withNavigation.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationProp, ParamListBase } from '@react-navigation/core';
|
||||
import useCompatNavigation from './useCompatNavigation';
|
||||
import { CompatNavigationProp } from './types';
|
||||
|
||||
type InjectedProps<T extends NavigationProp<ParamListBase>> = {
|
||||
navigation: CompatNavigationProp<T>;
|
||||
};
|
||||
|
||||
export default function withNavigation<
|
||||
T extends NavigationProp<ParamListBase>,
|
||||
P extends InjectedProps<T>,
|
||||
C extends React.ComponentType<P>
|
||||
>(Comp: C) {
|
||||
const WrappedComponent = ({
|
||||
onRef,
|
||||
...rest
|
||||
}: Exclude<P, InjectedProps<T>> & {
|
||||
onRef?: C extends React.ComponentClass<any>
|
||||
? React.Ref<InstanceType<C>>
|
||||
: never;
|
||||
}): React.ReactElement => {
|
||||
const navigation = useCompatNavigation<T>();
|
||||
|
||||
// @ts-ignore
|
||||
return <Comp ref={onRef} navigation={navigation} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigation(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
30
packages/compat/src/withNavigationFocus.tsx
Normal file
30
packages/compat/src/withNavigationFocus.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
import { useIsFocused } from '@react-navigation/core';
|
||||
|
||||
type InjectedProps = {
|
||||
isFocused: boolean;
|
||||
};
|
||||
|
||||
export default function withNavigationFocus<
|
||||
P extends InjectedProps,
|
||||
C extends React.ComponentType<P>
|
||||
>(Comp: C) {
|
||||
const WrappedComponent = ({
|
||||
onRef,
|
||||
...rest
|
||||
}: Exclude<P, InjectedProps> & {
|
||||
onRef?: C extends React.ComponentClass<any>
|
||||
? React.Ref<InstanceType<C>>
|
||||
: never;
|
||||
}): React.ReactElement => {
|
||||
const isFocused = useIsFocused();
|
||||
|
||||
// @ts-ignore
|
||||
return <Comp ref={onRef} isFocused={isFocused} {...rest} />;
|
||||
};
|
||||
|
||||
WrappedComponent.displayName = `withNavigationFocus(${Comp.displayName ||
|
||||
Comp.name})`;
|
||||
|
||||
return WrappedComponent;
|
||||
}
|
||||
@@ -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.0.0-alpha.10](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.9...@react-navigation/core@5.0.0-alpha.10) (2019-09-17)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.9](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.8...@react-navigation/core@5.0.0-alpha.9) (2019-09-16)
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.9",
|
||||
"version": "5.0.0-alpha.10",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -88,7 +88,9 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
|
||||
const { listeners, addListener: addFocusedListener } = useFocusedListeners();
|
||||
|
||||
const dispatch = (action: NavigationAction) => {
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: NavigationState) => NavigationAction)
|
||||
) => {
|
||||
listeners[0](navigation => navigation.dispatch(action));
|
||||
};
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@ type Props<State extends NavigationState, ScreenOptions extends object> = {
|
||||
route: Route<string> & {
|
||||
state?: NavigationState | PartialState<NavigationState>;
|
||||
};
|
||||
getState: () => NavigationState;
|
||||
setState: (state: NavigationState) => void;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -323,7 +323,7 @@ it('cleans up state when the navigator unmounts', () => {
|
||||
expect(onStateChange).lastCalledWith(undefined);
|
||||
});
|
||||
|
||||
it('allows arbitrary state updates by dispatching a function', () => {
|
||||
it('allows state updates by dispatching a function returning an action', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -332,11 +332,11 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
|
||||
const FooScreen = (props: any) => {
|
||||
React.useEffect(() => {
|
||||
props.navigation.dispatch((state: any) => ({
|
||||
...state,
|
||||
routes: state.routes.slice().reverse(),
|
||||
index: 1,
|
||||
}));
|
||||
props.navigation.dispatch((state: NavigationState) =>
|
||||
state.index === 0
|
||||
? { type: 'NAVIGATE', payload: { name: state.routeNames[1] } }
|
||||
: { type: 'NOOP' }
|
||||
);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -364,7 +364,7 @@ it('allows arbitrary state updates by dispatching a function', () => {
|
||||
index: 1,
|
||||
key: '0',
|
||||
routeNames: ['foo', 'bar'],
|
||||
routes: [{ key: 'bar', name: 'bar' }, { key: 'foo', name: 'foo' }],
|
||||
routes: [{ key: 'foo', name: 'foo' }, { key: 'bar', name: 'bar' }],
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -270,7 +270,9 @@ type NavigationHelpersCommon<
|
||||
*
|
||||
* @param action Action object or update function.
|
||||
*/
|
||||
dispatch(action: NavigationAction | ((state: State) => State)): void;
|
||||
dispatch(
|
||||
action: NavigationAction | ((state: State) => NavigationAction)
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Navigate to a route in current navigation tree.
|
||||
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
Router,
|
||||
} from './types';
|
||||
|
||||
type Options<ScreenOptions extends object> = {
|
||||
state: NavigationState;
|
||||
type Options<State extends NavigationState, ScreenOptions extends object> = {
|
||||
state: State;
|
||||
screens: { [key: string]: RouteConfig<ParamListBase, string, ScreenOptions> };
|
||||
navigation: NavigationHelpers<ParamListBase>;
|
||||
screenOptions?:
|
||||
@@ -31,12 +31,12 @@ type Options<ScreenOptions extends object> = {
|
||||
action: NavigationAction,
|
||||
visitedNavigators?: Set<string>
|
||||
) => boolean;
|
||||
getState: () => NavigationState;
|
||||
setState: (state: NavigationState) => void;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
addActionListener: (listener: ChildActionListener) => void;
|
||||
addFocusedListener: (listener: FocusedNavigationListener) => void;
|
||||
onRouteFocus: (key: string) => void;
|
||||
router: Router<NavigationState, NavigationAction>;
|
||||
router: Router<State, NavigationAction>;
|
||||
emitter: NavigationEventEmitter;
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ export default function useDescriptors<
|
||||
onRouteFocus,
|
||||
router,
|
||||
emitter,
|
||||
}: Options<ScreenOptions>) {
|
||||
}: Options<State, ScreenOptions>) {
|
||||
const [options, setOptions] = React.useState<{ [key: string]: object }>({});
|
||||
const { trackAction } = React.useContext(NavigationBuilderContext);
|
||||
|
||||
|
||||
@@ -245,7 +245,6 @@ export default function useNavigationBuilder<
|
||||
const navigation = useNavigationHelpers<State, NavigationAction, EventMap>({
|
||||
onAction,
|
||||
getState,
|
||||
setState,
|
||||
emitter,
|
||||
router,
|
||||
});
|
||||
|
||||
@@ -12,15 +12,15 @@ import {
|
||||
Router,
|
||||
} from './types';
|
||||
|
||||
type Options = {
|
||||
state: NavigationState;
|
||||
getState: () => NavigationState;
|
||||
type Options<State extends NavigationState> = {
|
||||
state: State;
|
||||
getState: () => State;
|
||||
navigation: NavigationHelpers<ParamListBase> &
|
||||
Partial<NavigationProp<ParamListBase, string, any, any, any>>;
|
||||
setOptions: (
|
||||
cb: (options: { [key: string]: object }) => { [key: string]: object }
|
||||
) => void;
|
||||
router: Router<NavigationState, NavigationAction>;
|
||||
router: Router<State, NavigationAction>;
|
||||
emitter: NavigationEventEmitter;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,14 @@ type NavigationCache<
|
||||
export default function useNavigationCache<
|
||||
State extends NavigationState,
|
||||
ScreenOptions extends object
|
||||
>({ state, getState, navigation, setOptions, router, emitter }: Options) {
|
||||
>({
|
||||
state,
|
||||
getState,
|
||||
navigation,
|
||||
setOptions,
|
||||
router,
|
||||
emitter,
|
||||
}: Options<State>) {
|
||||
// Cache object which holds navigation objects for each screen
|
||||
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
|
||||
// In reality, these deps will rarely change, if ever
|
||||
@@ -70,13 +77,17 @@ export default function useNavigationCache<
|
||||
const { emit, ...rest } = navigation;
|
||||
|
||||
const dispatch = (
|
||||
action: NavigationAction | ((state: State) => State)
|
||||
) =>
|
||||
action: NavigationAction | ((state: State) => NavigationAction)
|
||||
) => {
|
||||
const payload =
|
||||
typeof action === 'function' ? action(getState()) : action;
|
||||
|
||||
navigation.dispatch(
|
||||
typeof action === 'object' && action != null
|
||||
? { source: route.key, ...action }
|
||||
: action
|
||||
typeof payload === 'object' && payload != null
|
||||
? { source: route.key, ...payload }
|
||||
: payload
|
||||
);
|
||||
};
|
||||
|
||||
const helpers = Object.keys(actions).reduce(
|
||||
(acc, name) => {
|
||||
@@ -92,7 +103,7 @@ export default function useNavigationCache<
|
||||
...helpers,
|
||||
...emitter.create(route.key),
|
||||
dangerouslyGetParent: () => parentNavigation as any,
|
||||
dangerouslyGetState: getState as () => State,
|
||||
dangerouslyGetState: getState,
|
||||
dispatch,
|
||||
setOptions: (options: object) =>
|
||||
setOptions(o => ({
|
||||
|
||||
@@ -23,7 +23,6 @@ type Options<State extends NavigationState, Action extends NavigationAction> = {
|
||||
visitedNavigators?: Set<string>
|
||||
) => boolean;
|
||||
getState: () => State;
|
||||
setState: (state: State) => void;
|
||||
emitter: NavigationEventEmitter;
|
||||
router: Router<State, Action>;
|
||||
};
|
||||
@@ -36,18 +35,17 @@ export default function useNavigationHelpers<
|
||||
State extends NavigationState,
|
||||
Action extends NavigationAction,
|
||||
EventMap extends { [key: string]: any }
|
||||
>({ onAction, getState, setState, emitter, router }: Options<State, Action>) {
|
||||
>({ onAction, getState, emitter, router }: Options<State, Action>) {
|
||||
const parentNavigationHelpers = React.useContext(NavigationContext);
|
||||
const { performTransaction } = React.useContext(NavigationStateContext);
|
||||
|
||||
return React.useMemo(() => {
|
||||
const dispatch = (action: Action | ((state: State) => State)) =>
|
||||
const dispatch = (action: Action | ((state: State) => Action)) =>
|
||||
performTransaction(() => {
|
||||
if (typeof action === 'function') {
|
||||
setState(action(getState()));
|
||||
} else {
|
||||
onAction(action);
|
||||
}
|
||||
const payload =
|
||||
typeof action === 'function' ? action(getState()) : action;
|
||||
|
||||
onAction(payload);
|
||||
});
|
||||
|
||||
const actions = {
|
||||
@@ -87,7 +85,6 @@ export default function useNavigationHelpers<
|
||||
parentNavigationHelpers,
|
||||
emitter.emit,
|
||||
performTransaction,
|
||||
setState,
|
||||
onAction,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.16...@react-navigation/stack@5.0.0-alpha.17) (2019-09-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add fallbacks for non-web modules ([b4bbf9b](https://github.com/react-navigation/navigation-ex/commit/b4bbf9b)), closes [#95](https://github.com/react-navigation/navigation-ex/issues/95) [#96](https://github.com/react-navigation/navigation-ex/issues/96)
|
||||
* provide navigation prop in header ([30e510d](https://github.com/react-navigation/navigation-ex/commit/30e510d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.16](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.15...@react-navigation/stack@5.0.0-alpha.16) (2019-09-16)
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"stack"
|
||||
],
|
||||
"version": "5.0.0-alpha.16",
|
||||
"version": "5.0.0-alpha.17",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { I18nManager } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import getStatusBarHeight from '../utils/getStatusBarHeight';
|
||||
import { CardInterpolationProps, CardInterpolatedStyle } from '../types';
|
||||
import { getStatusBarHeight } from 'react-native-safe-area-view';
|
||||
|
||||
const { cond, add, multiply, interpolate } = Animated;
|
||||
|
||||
|
||||
9
packages/stack/src/utils/getStatusBarHeight.tsx
Normal file
9
packages/stack/src/utils/getStatusBarHeight.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Platform } from 'react-native';
|
||||
import { getStatusBarHeight as getStatusBarHeightNative } from 'react-native-safe-area-view';
|
||||
|
||||
const getStatusBarHeight = Platform.select({
|
||||
default: getStatusBarHeightNative,
|
||||
web: () => 0,
|
||||
});
|
||||
|
||||
export default getStatusBarHeight;
|
||||
@@ -6,17 +6,12 @@ import {
|
||||
Platform,
|
||||
StyleSheet,
|
||||
LayoutChangeEvent,
|
||||
UIManager,
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import MaskedView from '@react-native-community/masked-view';
|
||||
import MaskedView from '../MaskedView';
|
||||
import TouchableItem from '../TouchableItem';
|
||||
import { HeaderLeftButtonProps } from '../../types';
|
||||
|
||||
const isMaskedViewAvailable =
|
||||
// @ts-ignore
|
||||
UIManager.getViewManagerConfig('RNCMaskedView') != null;
|
||||
|
||||
type Props = HeaderLeftButtonProps & {
|
||||
tintColor: string;
|
||||
};
|
||||
@@ -129,7 +124,7 @@ class HeaderBackButton extends React.Component<Props, State> {
|
||||
</View>
|
||||
);
|
||||
|
||||
if (!isMaskedViewAvailable || backImage || Platform.OS !== 'ios') {
|
||||
if (backImage || Platform.OS !== 'ios') {
|
||||
// When a custom backimage is specified, we can't mask the label
|
||||
// Otherwise there might be weird effect due to our mask not being the same as the image
|
||||
return labelElement;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import { Route, ParamListBase } from '@react-navigation/core';
|
||||
import {
|
||||
NavigationContext,
|
||||
Route,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
import { StackNavigationState } from '@react-navigation/routers';
|
||||
|
||||
import Header from './Header';
|
||||
@@ -92,36 +96,40 @@ export default function HeaderContainer({
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
<NavigationContext.Provider
|
||||
key={scene.route.key}
|
||||
onLayout={
|
||||
onContentHeightChange
|
||||
? e =>
|
||||
onContentHeightChange({
|
||||
route: scene.route,
|
||||
height: e.nativeEvent.layout.height,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
pointerEvents="box-none"
|
||||
accessibilityElementsHidden={!isFocused}
|
||||
importantForAccessibility={
|
||||
isFocused ? 'auto' : 'no-hide-descendants'
|
||||
}
|
||||
style={
|
||||
mode === 'float' || options.headerTransparent
|
||||
? styles.header
|
||||
: null
|
||||
}
|
||||
value={scene.descriptor.navigation}
|
||||
>
|
||||
{options.header !== undefined ? (
|
||||
options.header === null ? null : (
|
||||
options.header(props)
|
||||
)
|
||||
) : (
|
||||
<Header {...props} />
|
||||
)}
|
||||
</View>
|
||||
<View
|
||||
onLayout={
|
||||
onContentHeightChange
|
||||
? e =>
|
||||
onContentHeightChange({
|
||||
route: scene.route,
|
||||
height: e.nativeEvent.layout.height,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
pointerEvents="box-none"
|
||||
accessibilityElementsHidden={!isFocused}
|
||||
importantForAccessibility={
|
||||
isFocused ? 'auto' : 'no-hide-descendants'
|
||||
}
|
||||
style={
|
||||
mode === 'float' || options.headerTransparent
|
||||
? styles.header
|
||||
: null
|
||||
}
|
||||
>
|
||||
{options.header !== undefined ? (
|
||||
options.header === null ? null : (
|
||||
options.header(props)
|
||||
)
|
||||
) : (
|
||||
<Header {...props} />
|
||||
)}
|
||||
</View>
|
||||
</NavigationContext.Provider>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
@@ -7,10 +7,10 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import { getStatusBarHeight } from 'react-native-safe-area-view';
|
||||
import { Route } from '@react-navigation/core';
|
||||
import HeaderBackButton from './HeaderBackButton';
|
||||
import HeaderBackground from './HeaderBackground';
|
||||
import getStatusBarHeight from '../../utils/getStatusBarHeight';
|
||||
import memoize from '../../utils/memoize';
|
||||
import {
|
||||
Layout,
|
||||
|
||||
19
packages/stack/src/views/MaskedView.tsx
Normal file
19
packages/stack/src/views/MaskedView.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { UIManager } from 'react-native';
|
||||
import RNCMaskedView from '@react-native-community/masked-view';
|
||||
|
||||
type Props = React.ComponentProps<typeof RNCMaskedView> & {
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
const isMaskedViewAvailable =
|
||||
// @ts-ignore
|
||||
UIManager.getViewManagerConfig('RNCMaskedView') != null;
|
||||
|
||||
export default function MaskedView({ children, ...rest }: Props) {
|
||||
if (isMaskedViewAvailable) {
|
||||
return <RNCMaskedView {...rest}>{children}</RNCMaskedView>;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
7
packages/stack/src/views/MaskedView.web.tsx
Normal file
7
packages/stack/src/views/MaskedView.web.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
type Props = {
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
export default function MaskedView({ children }: Props) {
|
||||
return children;
|
||||
}
|
||||
Reference in New Issue
Block a user