Skip to content
This repository has been archived by the owner on Feb 8, 2020. It is now read-only.

Commit

Permalink
feat: integrate reanimated based stack (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 authored and osdnk committed Aug 6, 2019
1 parent 89c279f commit dcf57c0
Show file tree
Hide file tree
Showing 15 changed files with 184 additions and 177 deletions.
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
"prettier": "^1.18.2",
"typescript": "^3.5.1"
},
"resolutions": {
"react": "16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-safe-area-view": "0.14.6"
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/BaseActions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PartialState, NavigationState, TargetRoute } from './types';

export type Action =
| { type: 'GO_BACK' }
| { type: 'GO_BACK'; source?: string }
| {
type: 'NAVIGATE';
payload:
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/NavigationContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import { NavigationProp, ParamListBase } from './types';

const NavigationContext = React.createContext<
NavigationProp<ParamListBase> | undefined
NavigationProp<ParamListBase, string, any, any> | undefined
>(undefined);

export default NavigationContext;
11 changes: 7 additions & 4 deletions packages/core/src/SceneView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,24 @@ import {
RouteConfig,
} from './types';

type Props<ScreenOptions extends object> = {
type Props<State extends NavigationState, ScreenOptions extends object> = {
screen: RouteConfig<ParamListBase, string, ScreenOptions>;
navigation: NavigationProp<ParamListBase>;
navigation: NavigationProp<ParamListBase, string, State, ScreenOptions>;
route: Route<string> & { state?: NavigationState };
getState: () => NavigationState;
setState: (state: NavigationState) => void;
};

export default function SceneView<ScreenOptions extends object>({
export default function SceneView<
State extends NavigationState,
ScreenOptions extends object
>({
screen,
route,
navigation,
getState,
setState,
}: Props<ScreenOptions>) {
}: Props<State, ScreenOptions>) {
const { performTransaction } = React.useContext(NavigationStateContext);

const getCurrentState = React.useCallback(() => {
Expand Down
21 changes: 19 additions & 2 deletions packages/core/src/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,13 @@ export type CompositeNavigationProp<
A extends NavigationProp<any, any, any, any, infer E> ? E : {}
>;

export type Descriptor<ScreenOptions extends object> = {
export type Descriptor<
ParamList extends ParamListBase,
RouteName extends keyof ParamList = string,
State extends NavigationState = NavigationState,
ScreenOptions extends object = {},
EventMap extends { [key: string]: any } = {}
> = {
/**
* Render the component associated with this route.
*/
Expand All @@ -359,6 +365,17 @@ export type Descriptor<ScreenOptions extends object> = {
* Options for the route.
*/
options: ScreenOptions;

/**
* Navigation object for the screen
*/
navigation: NavigationProp<
ParamList,
RouteName,
State,
ScreenOptions,
EventMap
>;
};

export type RouteConfig<
Expand All @@ -378,7 +395,7 @@ export type RouteConfig<
| ScreenOptions
| ((props: {
route: RouteProp<ParamList, RouteName>;
navigation: NavigationHelpersCommon<ParamList>;
navigation: any;
}) => ScreenOptions);

/**
Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/useDescriptors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ type Options<ScreenOptions extends object> = {
emitter: NavigationEventEmitter;
};

export default function useDescriptors<ScreenOptions extends object>({
export default function useDescriptors<
State extends NavigationState,
ScreenOptions extends object
>({
state,
screens,
navigation,
Expand Down Expand Up @@ -61,7 +64,7 @@ export default function useDescriptors<ScreenOptions extends object>({
]
);

const navigations = useNavigationCache({
const navigations = useNavigationCache<State, ScreenOptions>({
state,
getState,
navigation,
Expand Down Expand Up @@ -97,9 +100,12 @@ export default function useDescriptors<ScreenOptions extends object>({
})),
...options[route.key],
},
navigation: navigations[route.key],
};
return acc;
},
{} as { [key: string]: Descriptor<ScreenOptions> }
{} as {
[key: string]: Descriptor<ParamListBase, string, State, ScreenOptions>;
}
);
}
2 changes: 1 addition & 1 deletion packages/core/src/useNavigationBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ export default function useNavigationBuilder<
actionCreators: router.actionCreators,
});

const descriptors = useDescriptors<ScreenOptions>({
const descriptors = useDescriptors<State, ScreenOptions>({
state,
screens,
navigation,
Expand Down
109 changes: 56 additions & 53 deletions packages/core/src/useNavigationCache.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,66 +18,69 @@ type Options = {
emitter: NavigationEventEmitter;
};

type NavigationCache = { [key: string]: NavigationProp<ParamListBase> };
type NavigationCache<
State extends NavigationState,
ScreenOptions extends object
> = {
[key: string]: NavigationProp<ParamListBase, string, State, ScreenOptions>;
};

export default function useNavigationCache({
state,
getState,
navigation,
setOptions,
emitter,
}: Options) {
// eslint-disable-next-line react-hooks/exhaustive-deps
const cache = React.useMemo(() => ({ current: {} as NavigationCache }), [
getState,
navigation,
setOptions,
emitter,
]);
export default function useNavigationCache<
State extends NavigationState,
ScreenOptions extends object
>({ state, getState, navigation, setOptions, emitter }: Options) {
const cache = React.useMemo(
() => ({ current: {} as NavigationCache<State, ScreenOptions> }),
// eslint-disable-next-line react-hooks/exhaustive-deps
[getState, navigation, setOptions, emitter]
);

cache.current = state.routes.reduce<NavigationCache>((acc, route, index) => {
const previous = cache.current[route.key];
const isFirst = route.key === state.routes[0].key;
cache.current = state.routes.reduce<NavigationCache<State, ScreenOptions>>(
(acc, route, index) => {
const previous = cache.current[route.key];
const isFirst = route.key === state.routes[0].key;

if (previous && previous.isFirstRouteInParent() === isFirst) {
acc[route.key] = previous;
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { emit, ...rest } = navigation;
if (previous && previous.isFirstRouteInParent() === isFirst) {
acc[route.key] = previous;
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { emit, ...rest } = navigation;

acc[route.key] = {
...rest,
...emitter.create(route.key),
dispatch: (
action:
| NavigationAction
| ((state: NavigationState) => NavigationState)
) =>
navigation.dispatch(
typeof action === 'object' && action != null
? { source: route.key, ...action }
: action
),
setOptions: (options: object) =>
setOptions(o => ({
...o,
[route.key]: { ...o[route.key], ...options },
})),
isFocused: () => {
const state = getState();
acc[route.key] = {
...rest,
...emitter.create(route.key),
dispatch: (
action:
| NavigationAction
| ((state: NavigationState) => NavigationState)
) =>
navigation.dispatch(
typeof action === 'object' && action != null
? { source: route.key, ...action }
: action
),
setOptions: (options: object) =>
setOptions(o => ({
...o,
[route.key]: { ...o[route.key], ...options },
})),
isFocused: () => {
const state = getState();

if (index !== state.index) {
return false;
}
if (index !== state.index) {
return false;
}

return navigation ? navigation.isFocused() : true;
},
isFirstRouteInParent: () => isFirst,
} as NavigationProp<ParamListBase>;
}
return navigation ? navigation.isFocused() : true;
},
isFirstRouteInParent: () => isFirst,
} as NavigationProp<ParamListBase, string, State, ScreenOptions>;
}

return acc;
}, {});
return acc;
},
{}
);

return cache.current;
}
2 changes: 2 additions & 0 deletions packages/example/metro.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ module.exports = {

providesModuleNodeModules: [
'@babel/runtime',
'@react-native-community/masked-view',
'react',
'react-native',
'react-native-gesture-handler',
'react-native-reanimated',
'react-native-safe-area-view',
'react-native-screens',
'react-native-tab-view',
'shortid',
],
Expand Down
7 changes: 2 additions & 5 deletions packages/example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
"eject": "expo eject"
},
"dependencies": {
"@react-native-community/masked-view": "^0.1.1",
"expo": "^34.0.1",
"react": "16.8.3",
"react-dom": "^16.8.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-gesture-handler": "~1.3.0",
"react-native-paper": "3.0.0-alpha.3",
"react-native-reanimated": "~1.1.0",
"react-native-screens": "1.0.0-alpha.22",
"react-native-tab-view": "2.7.1",
"react-native-web": "^0.11.4",
"scheduler": "^0.14.0",
Expand All @@ -36,10 +38,5 @@
"@types/react-native": "^0.57.65",
"babel-preset-expo": "^6.0.0",
"expo-cli": "^3.0.6"
},
"resolutions": {
"react": "16.8.3",
"react-dom": "^16.8.3",
"react-native-safe-area-view": "0.14.6"
}
}
15 changes: 8 additions & 7 deletions packages/material-top-tabs/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Props = TabRouterOptions &
children: React.ReactNode;
};

export type TabNavigationOptions = {
export type MaterialTopTabNavigationOptions = {
/**
* Title text for the screen.
*/
Expand All @@ -36,7 +36,7 @@ export type MaterialTopTabNavigationProp<
ParamList,
RouteName,
TabNavigationState,
TabNavigationOptions
MaterialTopTabNavigationOptions
> & {
/**
* Jump to an existing tab.
Expand All @@ -51,15 +51,15 @@ export type MaterialTopTabNavigationProp<
): void;
};

export function TabNavigator({
function TabNavigator({
initialRouteName,
backBehavior,
children,
...rest
}: Props) {
const { state, descriptors, navigation } = useNavigationBuilder<
TabNavigationState,
TabNavigationOptions,
MaterialTopTabNavigationOptions,
TabRouterOptions
>(TabRouter, {
initialRouteName,
Expand All @@ -85,6 +85,7 @@ export function TabNavigator({
);
}

export default createNavigator<TabNavigationOptions, typeof TabNavigator>(
TabNavigator
);
export default createNavigator<
MaterialTopTabNavigationOptions,
typeof TabNavigator
>(TabNavigator);
Loading

0 comments on commit dcf57c0

Please sign in to comment.