feat: export types for ScreenProps amd ScreenComponent

This commit is contained in:
satyajit.happy
2019-09-12 16:39:34 +02:00
parent 72c98c918f
commit 7ecc884ecd
18 changed files with 189 additions and 128 deletions

View File

@@ -15,6 +15,8 @@
},
"rules": {
"import/named": "off"
"import/named": "off",
"import/default": "off",
"import/namespace": "off",
}
}

View File

@@ -4,6 +4,7 @@ import { View, TouchableOpacity, StyleSheet } from 'react-native';
import {
Assets as StackAssets,
createStackNavigator,
NavigationStackScreenProps,
} from 'react-navigation-stack';
import {
Themed,
@@ -20,7 +21,7 @@ import MaterialTopTabs from './src/MaterialTopTabs';
// Load the back button etc
Asset.loadAsync(StackAssets);
const Home = props => {
const Home = (props: NavigationStackScreenProps) => {
let theme = useTheme();
return (
@@ -62,7 +63,7 @@ const List = createStackNavigator({
const Navigation = createAppContainer(List);
const App = () => {
let [theme, setTheme] = React.useState('light');
let [theme, setTheme] = React.useState<'light' | 'dark'>('light');
return (
<View style={styles.container}>
@@ -97,7 +98,7 @@ const styles = {
flex: 1,
},
buttonContainer: {
position: 'absolute',
position: 'absolute' as const,
bottom: 60,
right: 20,
},
@@ -111,8 +112,8 @@ const styles = {
borderRadius: 25,
width: 50,
height: 50,
alignItems: 'center',
justifyContent: 'center',
alignItems: 'center' as const,
justifyContent: 'center' as const,
elevation: 5,
borderWidth: 1,
},
@@ -130,4 +131,5 @@ const styles = {
},
};
// @ts-ignore
registerRootComponent(App);

View File

@@ -14,12 +14,12 @@
"expo-asset": "^6.0.0",
"expo-constants": "~5.0.1",
"react": "16.8.3",
"react-navigation": "^4.0.3",
"react-native": "https://github.com/expo/react-native/archive/sdk-33.0.0.tar.gz",
"react-native-safe-area-view": "0.13.1",
"react-native-screens": "1.0.0-alpha.22",
"react-native-tab-view": "^2.10.0",
"react-navigation-stack": "1.5.3"
"react-navigation": "^4.0.4",
"react-navigation-stack": "^1.7.2"
},
"devDependencies": {
"babel-plugin-module-resolver": "^3.2.0",

View File

@@ -6,10 +6,16 @@ import Article from './Shared/Article';
import Chat from './Shared/Chat';
import Contacts from './Shared/Contacts';
// eslint-disable-next-line import/default
// @ts-ignore
import TouchableBounce from 'react-native/Libraries/Components/Touchable/TouchableBounce';
const tabBarIcon = name => ({ tintColor, horizontal }) => (
const tabBarIcon = (name: string) => ({
tintColor,
horizontal,
}: {
tintColor: string;
horizontal: boolean;
}) => (
<MaterialIcons name={name} color={tintColor} size={horizontal ? 17 : 24} />
);
@@ -61,9 +67,14 @@ class ContactsScreen extends React.Component {
}
}
export default createBottomTabNavigator({
AlbumsScreen,
ArticleScreen,
ChatScreen,
ContactsScreen,
});
export default createBottomTabNavigator(
{
AlbumsScreen,
ArticleScreen,
ChatScreen,
ContactsScreen,
},
{
initialRouteName: 'AlbumsScreen',
}
);

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as React from 'react';
import { Image, Dimensions, ScrollView, StyleSheet } from 'react-native';
@@ -14,7 +12,7 @@ const COVERS = [
require('../../assets/album-art-8.jpg'),
];
export default class Albums extends React.Component<*> {
export default class Albums extends React.Component {
render() {
return (
<ScrollView

View File

@@ -1,9 +1,7 @@
/* @flow */
import * as React from 'react';
import { View, Text, Image, ScrollView, StyleSheet } from 'react-native';
export default class Article extends React.Component<*> {
export default class Article extends React.Component {
render() {
return (
<ScrollView

View File

@@ -1,5 +1,3 @@
/* @flow */
import * as React from 'react';
import { View, Image, Text, ScrollView, StyleSheet } from 'react-native';
@@ -10,7 +8,7 @@ const MESSAGES = [
'make me a sandwich',
];
export default class Albums extends React.Component<*> {
export default class Albums extends React.Component {
render() {
return (
<View style={styles.container}>

View File

@@ -1,9 +1,9 @@
/* @flow */
import * as React from 'react';
import { View, Text, StyleSheet, FlatList } from 'react-native';
const CONTACTS = [
type Item = { name: string; number: number };
const CONTACTS: Item[] = [
{ name: 'Marissa Castillo', number: 7766398169 },
{ name: 'Denzel Curry', number: 9394378449 },
{ name: 'Miles Ferguson', number: 8966872888 },
@@ -57,7 +57,7 @@ const CONTACTS = [
];
class ContactItem extends React.PureComponent<{
item: { name: string, number: number },
item: Item;
}> {
render() {
const { item } = this.props;
@@ -78,8 +78,8 @@ class ContactItem extends React.PureComponent<{
}
}
export default class Contacts extends React.Component<*> {
_renderItem = ({ item }) => <ContactItem item={item} />;
export default class Contacts extends React.Component {
_renderItem = ({ item }: { item: Item }) => <ContactItem item={item} />;
_ItemSeparator = () => <View style={styles.separator} />;
@@ -87,7 +87,7 @@ export default class Contacts extends React.Component<*> {
return (
<FlatList
data={CONTACTS}
keyExtractor={(item, i) => String(i)}
keyExtractor={(_, i) => String(i)}
renderItem={this._renderItem}
ItemSeparatorComponent={this._ItemSeparator}
/>

View File

@@ -1,78 +0,0 @@
import * as React from 'react';
import { View, Image, ScrollView, Dimensions, StyleSheet } from 'react-native';
import { withNavigation } from 'react-navigation';
@withNavigation
class NavigationAwareScrollView extends React.Component {
componentDidMount() {
this.props.navigation.addListener('willFocus', () => {
this._isFocused = true;
});
this.props.navigation.addListener('willBlur', () => {
this._isFocused = false;
});
this.props.navigation.addListener('refocus', () => {
if (this._isFocused) {
this._component.scrollTo({ x: 0, y: 0 });
}
});
}
setNativeProps(props) {
this._component.setNativeProps(props);
}
_setComponentRef(c) {
this._component = c;
}
getNode() {
return this._component;
}
render() {
return (
<ScrollView
{...this.props}
ref={view => {
this._component = view;
}}
/>
);
}
}
export default function PhotoGrid({ id }) {
const PHOTOS = Array.from({ length: 24 }).map(
(_, i) => `https://unsplash.it/300/300/?random&__id=${id}${i}`
);
return (
<NavigationAwareScrollView contentContainerStyle={styles.content}>
{PHOTOS.map(uri => (
<View key={uri} style={styles.item}>
<Image source={{ uri }} style={styles.photo} />
</View>
))}
</NavigationAwareScrollView>
);
}
const styles = StyleSheet.create({
content: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 4,
},
item: {
height: Dimensions.get('window').width / 2,
width: '50%',
padding: 4,
},
photo: {
flex: 1,
resizeMode: 'cover',
},
});

View File

@@ -0,0 +1,86 @@
import * as React from 'react';
import {
View,
Image,
ScrollView,
Dimensions,
StyleSheet,
StyleProp,
ViewStyle,
ScrollViewProperties,
} from 'react-native';
import {
withNavigation,
NavigationScreenProp,
NavigationRoute,
NavigationEventSubscription,
} from 'react-navigation';
class NavigationAwareScrollViewBase extends React.Component<{
navigation: NavigationScreenProp<NavigationRoute>;
contentContainerStyle: StyleProp<ViewStyle>;
}> {
componentDidMount() {
this.subscription = this.props.navigation.addListener('refocus', () => {
if (this.props.navigation.isFocused()) {
this.root.current && this.root.current.scrollTo({ x: 0, y: 0 });
}
});
}
componentWillUnmount() {
this.subscription && this.subscription.remove();
}
setNativeProps(props: ScrollViewProperties) {
// @ts-ignore
this.root.current.setNativeProps(props);
}
getNode() {
return this.root.current;
}
private subscription: NavigationEventSubscription | undefined;
private root = React.createRef<ScrollView>();
render() {
return <ScrollView {...this.props} ref={this.root} />;
}
}
const NavigationAwareScrollView = withNavigation(NavigationAwareScrollViewBase);
export default function PhotoGrid({ id }: { id: string }) {
const PHOTOS = Array.from({ length: 24 }).map(
(_, i) => `https://unsplash.it/300/300/?random&__id=${id}${i}`
);
return (
<NavigationAwareScrollView contentContainerStyle={styles.content}>
{PHOTOS.map(uri => (
<View key={uri} style={styles.item}>
<Image source={{ uri }} style={styles.photo} />
</View>
))}
</NavigationAwareScrollView>
);
}
const styles = StyleSheet.create({
content: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 4,
},
item: {
height: Dimensions.get('window').width / 2,
width: '50%',
padding: 4,
},
photo: {
flex: 1,
resizeMode: 'cover',
},
});

View File

@@ -4587,17 +4587,17 @@ react-native-webview@5.8.1:
xmldoc "^0.4.0"
yargs "^9.0.0"
react-navigation-stack@1.5.3:
version "1.5.3"
resolved "https://registry.yarnpkg.com/react-navigation-stack/-/react-navigation-stack-1.5.3.tgz#cdc9f5a6dbdc55509a15f60d765722573dec1997"
integrity sha512-MQcwDVbZUYsTtDJb5cFOSm+K+e7KpUCoROaGoUOR+JHWE3uuaJ3pd/Nu+32a57J98TNBf4qq0+2TPJWl6z6IBg==
react-navigation-stack@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/react-navigation-stack/-/react-navigation-stack-1.7.2.tgz#d7cf7a7dc76c2390024be6358fc65461c848a034"
integrity sha512-72oL9rVXUFvFayoA7k+OgXcwP/6e5BAtCSpUXfKX+lZYrJe3BvuhZz2KDhEjdfbuP/sNok55ZRzc3/X1kh5mxQ==
dependencies:
prop-types "^15.7.2"
react-navigation@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-4.0.3.tgz#ba2cacb71db56e22ee50d774829ebc7fa95a0724"
integrity sha512-oASR5gHwd6se1Mw8AM4Ie8GicD5mKzRiYP6oaQujiQroQzQPij9sXxkRSqOscd/Kw1/Hf3htvBX3ZRPbOkWsfA==
react-navigation@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-4.0.4.tgz#afa43c7183891d38708cf57f1d4394fed1d4c2ad"
integrity sha512-MZeVkYkFTKZobhrXMV3Hgeg0HHeokCrYsbxActVfO0n6zfzm0/La6EiC2mIHiwOymvb1ZygyFf90vryLUMEBNA==
dependencies:
"@react-navigation/core" "^3.5.0"
"@react-navigation/native" "^3.6.2"

View File

@@ -74,18 +74,18 @@
"react-native": "~0.57.1",
"react-native-gesture-handler": "^1.4.1",
"react-native-reanimated": "^1.2.0",
"react-navigation": "^4.0.3",
"react-navigation": "^4.0.4",
"react-test-renderer": "16.5.0",
"release-it": "^10.3.1",
"typescript": "^3.5.2"
},
"peerDependencies": {
"react": "*",
"react-navigation": "^4.0.3",
"react-native": "*",
"react-native-gesture-handler": "^1.0.0",
"react-native-reanimated": "^1.0.0-alpha",
"react-native-screens": "^1.0.0 || ^1.0.0-alpha"
"react-native-screens": "^1.0.0 || ^1.0.0-alpha",
"react-navigation": "^4.0.4"
},
"husky": {
"hooks": {

View File

@@ -22,10 +22,12 @@ export { default as createTabNavigator } from './utils/createTabNavigator';
/**
* Types
*/
export {
NavigationTabState,
NavigationTabProp,
NavigationTabScreenProps,
NavigationBottomTabOptions,
NavigationMaterialTabOptions,
NavigationBottomTabScreenComponent,
NavigationMaterialTabScreenComponent,
} from './types';

View File

@@ -14,6 +14,8 @@ import {
NavigationScreenProp,
NavigationParams,
NavigationDescriptor,
NavigationScreenConfig,
SupportedThemes,
} from 'react-navigation';
export type NavigationTabState = NavigationState;
@@ -178,6 +180,35 @@ export type NavigationMaterialTabOptions = NavigationCommonTabOptions & {
swipeEnabled?: boolean | ((state: NavigationState) => boolean);
};
export type NavigationTabScreenProps<
Params = NavigationParams,
ScreenProps = unknown
> = {
theme: SupportedThemes;
navigation: NavigationTabProp<NavigationRoute, Params>;
screenProps: ScreenProps;
};
export type NavigationMaterialTabScreenComponent<
Params = NavigationParams,
ScreenProps = unknown
> = React.ComponentType<NavigationTabScreenProps<Params, ScreenProps>> & {
navigationOptions?: NavigationScreenConfig<
NavigationMaterialTabOptions,
NavigationTabProp<NavigationRoute, Params>
>;
};
export type NavigationBottomTabScreenComponent<
Params = NavigationParams,
ScreenProps = unknown
> = React.ComponentType<NavigationTabScreenProps<Params, ScreenProps>> & {
navigationOptions?: NavigationScreenConfig<
NavigationBottomTabOptions,
NavigationTabProp<NavigationRoute, Params>
>;
};
export type SceneDescriptorMap = {
[key: string]: NavigationDescriptor<
NavigationParams,

View File

@@ -58,7 +58,12 @@ export default function createTabNavigator<
TabView: React.ComponentType<Props>
): (
routes: RouteConfig<Options>,
config: Options
config?: CreateNavigatorConfig<
{},
NavigationTabRouterConfig,
Partial<Options>,
NavigationTabProp
>
) => React.ComponentType<
Pick<Props, Exclude<keyof Props, keyof NavigationViewProps>> & ExtraProps
> {
@@ -256,7 +261,8 @@ export default function createTabNavigator<
config: CreateNavigatorConfig<
{},
NavigationTabRouterConfig,
Partial<Options>
Partial<Options>,
NavigationTabProp
> = {}
) => {
const router = TabRouter(routes, config as any);

View File

@@ -1,5 +1,9 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"react-navigation-tabs": ["./src/index"]
},
"allowUnreachableCode": false,
"allowUnusedLabels": false,
"esModuleInterop": true,
@@ -15,6 +19,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "esnext"
}

View File

@@ -7672,10 +7672,10 @@ react-native@~0.57.1:
xmldoc "^0.4.0"
yargs "^9.0.0"
react-navigation@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-4.0.3.tgz#ba2cacb71db56e22ee50d774829ebc7fa95a0724"
integrity sha512-oASR5gHwd6se1Mw8AM4Ie8GicD5mKzRiYP6oaQujiQroQzQPij9sXxkRSqOscd/Kw1/Hf3htvBX3ZRPbOkWsfA==
react-navigation@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/react-navigation/-/react-navigation-4.0.4.tgz#afa43c7183891d38708cf57f1d4394fed1d4c2ad"
integrity sha512-MZeVkYkFTKZobhrXMV3Hgeg0HHeokCrYsbxActVfO0n6zfzm0/La6EiC2mIHiwOymvb1ZygyFf90vryLUMEBNA==
dependencies:
"@react-navigation/core" "^3.5.0"
"@react-navigation/native" "^3.6.2"