This commit is contained in:
satyajit.happy
2019-07-25 15:36:41 +02:00
parent e4e009fb33
commit f4ac5c3e1a
3 changed files with 175 additions and 86 deletions

View File

@@ -1,5 +1,10 @@
import * as React from 'react';
import { View, StyleSheet } from 'react-native';
import {
View,
StyleSheet,
AccessibilityRole,
AccessibilityState,
} from 'react-native';
// eslint-disable-next-line import/no-unresolved
import { ScreenContainer } from 'react-native-screens';
@@ -7,18 +12,29 @@ import { ScreenContainer } from 'react-native-screens';
import createTabNavigator, {
NavigationViewProps,
} from '../utils/createTabNavigator';
import BottomTabBar, { TabBarOptions } from '../views/BottomTabBar';
import BottomTabBar from '../views/BottomTabBar';
import ResourceSavingScene from '../views/ResourceSavingScene';
import { NavigationProp, Route, SceneDescriptor } from '../types';
import {
NavigationProp,
Route,
SceneDescriptor,
NavigationBottomTabOptions,
BottomTabBarOptions,
} from '../types';
type Props = NavigationViewProps & {
getAccessibilityRole: (props: { route: any }) => string;
getAccessibilityStates: (props: { route: any }) => string[];
getAccessibilityRole: (props: {
route: Route;
}) => AccessibilityRole | undefined;
getAccessibilityStates: (props: {
route: Route;
focused: boolean;
}) => AccessibilityState[];
lazy?: boolean;
tabBarComponent?: React.ComponentType<any>;
tabBarOptions?: TabBarOptions;
tabBarOptions?: BottomTabBarOptions;
navigation: NavigationProp;
descriptors: { [key: string]: SceneDescriptor };
descriptors: { [key: string]: SceneDescriptor<NavigationBottomTabOptions> };
screenProps?: unknown;
};
@@ -29,9 +45,12 @@ type State = {
class TabNavigationView extends React.PureComponent<Props, State> {
static defaultProps = {
lazy: true,
getAccessibilityRole: () => 'button',
getAccessibilityStates: ({ focused }: { focused: boolean }) =>
focused ? ['selected'] : [],
getAccessibilityRole: (): AccessibilityRole => 'button',
getAccessibilityStates: ({
focused,
}: {
focused: boolean;
}): AccessibilityState[] => (focused ? ['selected'] : []),
};
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
@@ -157,4 +176,6 @@ const styles = StyleSheet.create({
},
});
export default createTabNavigator(TabNavigationView);
export default createTabNavigator<NavigationBottomTabOptions, Props>(
TabNavigationView
);

View File

@@ -1,4 +1,13 @@
import * as React from 'react';
import {
AccessibilityRole,
AccessibilityState,
StyleProp,
TextStyle,
ViewStyle,
} from 'react-native';
import SafeAreaView from 'react-native-safe-area-view';
import Animated from 'react-native-reanimated';
export type Route = {
key: string;
@@ -36,18 +45,127 @@ export type NavigationProp<RouteName = string, Params = object> = {
dangerouslyGetParent(): NavigationProp | undefined;
};
export type NavigationTabOptions = {
export type Orientation = 'horizontal' | 'vertical';
export type LabelPosition = 'beside-icon' | 'below-icon';
export type BottomTabBarOptions = {
keyboardHidesTabBar: boolean;
activeTintColor?: string;
inactiveTintColor?: string;
activeBackgroundColor?: string;
inactiveBackgroundColor?: string;
allowFontScaling: boolean;
showLabel: boolean;
showIcon: boolean;
labelStyle: StyleProp<TextStyle>;
tabStyle: StyleProp<ViewStyle>;
labelPosition?:
| LabelPosition
| ((options: { deviceOrientation: Orientation }) => LabelPosition);
adaptive?: boolean;
style: StyleProp<ViewStyle>;
};
export type BottomTabBarProps = BottomTabBarOptions & {
navigation: NavigationProp;
onTabPress: (props: { route: Route }) => void;
onTabLongPress: (props: { route: Route }) => void;
getAccessibilityLabel: (props: { route: Route }) => string | undefined;
getAccessibilityRole: (props: {
route: Route;
}) => AccessibilityRole | undefined;
getAccessibilityStates: (props: {
route: Route;
focused: boolean;
}) => AccessibilityState[];
getButtonComponent: (props: {
route: Route;
}) => React.ComponentType<any> | undefined;
getLabelText: (props: {
route: Route;
}) =>
| ((scene: {
focused: boolean;
tintColor?: string;
orientation?: 'horizontal' | 'vertical';
}) => string | undefined)
| string
| undefined;
getTestID: (props: { route: Route }) => string | undefined;
renderIcon: (props: {
route: Route;
focused: boolean;
tintColor?: string;
horizontal?: boolean;
}) => React.ReactNode;
dimensions: { width: number; height: number };
isLandscape: boolean;
safeAreaInset: React.ComponentProps<typeof SafeAreaView>['forceInset'];
};
export type MaterialTabBarOptions = {
activeTintColor?: string;
allowFontScaling?: boolean;
bounces?: boolean;
inactiveTintColor?: string;
pressColor?: string;
pressOpacity?: number;
scrollEnabled?: boolean;
showIcon?: boolean;
showLabel?: boolean;
upperCaseLabel?: boolean;
tabStyle?: StyleProp<ViewStyle>;
indicatorStyle?: StyleProp<ViewStyle>;
iconStyle?: StyleProp<ViewStyle>;
labelStyle?: StyleProp<TextStyle>;
contentContainerStyle?: StyleProp<ViewStyle>;
style?: StyleProp<ViewStyle>;
};
export type MaterialTabBarProps = MaterialTabBarOptions & {
layout: {
width: number;
height: number;
};
position: Animated.Node<number>;
jumpTo: (key: string) => void;
getLabelText: (scene: {
route: Route;
}) =>
| ((scene: { focused: boolean; tintColor: string }) => string | undefined)
| string
| undefined;
getAccessible?: (scene: { route: Route }) => boolean | undefined;
getAccessibilityLabel: (scene: { route: Route }) => string | undefined;
getTestID: (scene: { route: Route }) => string | undefined;
renderIcon: (scene: {
route: Route;
focused: boolean;
tintColor: string;
horizontal?: boolean;
}) => React.ReactNode;
renderBadge?: (scene: { route: Route }) => React.ReactNode;
onTabPress?: (scene: { route: Route }) => void;
onTabLongPress?: (scene: { route: Route }) => void;
tabBarPosition?: 'top' | 'bottom';
screenProps: unknown;
navigation: NavigationProp;
};
export type NavigationCommonTabOptions = {
title?: string;
tabBarVisible?: boolean;
tabBarLabel?: React.ReactNode;
tabBarVisible?: boolean;
tabBarAccessibilityLabel?: string;
tabBarTestID?: string;
tabBarIcon?:
| React.ReactNode
| ((props: {
focused: boolean;
tintColor: string;
horizontal: boolean;
tintColor?: string;
horizontal?: boolean;
}) => React.ReactNode);
tabBarTestID?: string;
tabBarOnPress?: (props: {
navigation: NavigationProp;
defaultHandler: () => void;
@@ -56,19 +174,28 @@ export type NavigationTabOptions = {
navigation: NavigationProp;
defaultHandler: () => void;
}) => void;
tabBarAccessibilityLabel?: string;
tabBarButtonComponent?: React.ComponentType<any>;
};
export type SceneDescriptor = {
export type NavigationBottomTabOptions = NavigationCommonTabOptions & {
tabBarButtonComponent?: React.ComponentType<BottomTabBarProps>;
};
export type NavigationMaterialTabOptions = NavigationCommonTabOptions & {
tabBarButtonComponent?: React.ComponentType<any>;
swipeEnabled?: boolean | ((state: NavigationState) => boolean);
};
export type SceneDescriptor<Options extends NavigationCommonTabOptions> = {
key: string;
options: NavigationTabOptions;
options: Options;
navigation: NavigationProp;
getComponent(): React.ComponentType;
};
export type Screen = React.ComponentType<any> & {
navigationOptions?: NavigationTabOptions & {
export type Screen<
Options extends NavigationCommonTabOptions
> = React.ComponentType<any> & {
navigationOptions?: Options & {
[key: string]: any;
};
};

View File

@@ -6,74 +6,13 @@ import {
View,
Keyboard,
Platform,
StyleProp,
TextStyle,
ViewStyle,
LayoutChangeEvent,
AccessibilityRole,
AccessibilityState,
} from 'react-native';
import SafeAreaView from 'react-native-safe-area-view';
import CrossFadeIcon from './CrossFadeIcon';
import withDimensions from '../utils/withDimensions';
import { Route, NavigationProp } from '../types';
type Orientation = 'horizontal' | 'vertical';
type Position = 'beside-icon' | 'below-icon';
type LabelPosition =
| Position
| ((options: { deviceOrientation: Orientation }) => Position);
export type TabBarOptions = {
keyboardHidesTabBar: boolean;
activeTintColor?: string;
inactiveTintColor?: string;
activeBackgroundColor?: string;
inactiveBackgroundColor?: string;
allowFontScaling: boolean;
showLabel: boolean;
showIcon: boolean;
labelStyle: StyleProp<TextStyle>;
tabStyle: StyleProp<ViewStyle>;
labelPosition?: LabelPosition;
adaptive?: boolean;
style: StyleProp<ViewStyle>;
};
type Props = TabBarOptions & {
navigation: NavigationProp;
onTabPress: (props: { route: Route }) => void;
onTabLongPress: (props: { route: Route }) => void;
getAccessibilityLabel: (props: { route: Route }) => string | undefined;
getAccessibilityRole: (props: {
route: Route;
}) => AccessibilityRole | undefined;
getAccessibilityStates: (props: { route: Route }) => AccessibilityState[];
getButtonComponent: (props: {
route: Route;
}) => React.ComponentType<any> | undefined;
getLabelText: (props: {
route: Route;
}) =>
| ((scene: {
focused: boolean;
tintColor?: string;
orientation: 'horizontal' | 'vertical';
}) => React.ReactNode)
| string
| undefined;
getTestID: (props: { route: Route }) => string;
renderIcon: (props: {
route: Route;
focused: boolean;
tintColor?: string;
horizontal?: boolean;
}) => React.ReactNode;
dimensions: { width: number; height: number };
isLandscape: boolean;
safeAreaInset: React.ComponentProps<typeof SafeAreaView>['forceInset'];
};
import { Route, BottomTabBarProps } from '../types';
type State = {
layout: { height: number; width: number };
@@ -88,7 +27,9 @@ const isIOS11 = majorVersion >= 11 && isIos;
const DEFAULT_MAX_TAB_ITEM_WIDTH = 125;
class TouchableWithoutFeedbackWrapper extends React.Component<
React.ComponentProps<typeof TouchableWithoutFeedback>
React.ComponentProps<typeof TouchableWithoutFeedback> & {
children: React.ReactNode;
}
> {
render() {
const {
@@ -117,7 +58,7 @@ class TouchableWithoutFeedbackWrapper extends React.Component<
}
}
class TabBarBottom extends React.Component<Props, State> {
class TabBarBottom extends React.Component<BottomTabBarProps, State> {
static defaultProps = {
keyboardHidesTabBar: true,
activeTintColor: '#007AFF',