From 0799b430464f57bc243aa8f7f55bbe709bb5af8e Mon Sep 17 00:00:00 2001 From: "satyajit.happy" Date: Thu, 16 May 2019 16:47:14 +0200 Subject: [PATCH] wip --- packages/bottom-tabs/src/types.tsx | 72 ++++++ .../src/utils/createTabNavigator.js | 206 ------------------ .../bottom-tabs/src/utils/withDimensions.js | 37 ---- 3 files changed, 72 insertions(+), 243 deletions(-) create mode 100644 packages/bottom-tabs/src/types.tsx delete mode 100644 packages/bottom-tabs/src/utils/createTabNavigator.js delete mode 100644 packages/bottom-tabs/src/utils/withDimensions.js diff --git a/packages/bottom-tabs/src/types.tsx b/packages/bottom-tabs/src/types.tsx new file mode 100644 index 00000000..1f1aa985 --- /dev/null +++ b/packages/bottom-tabs/src/types.tsx @@ -0,0 +1,72 @@ +import * as React from 'react'; + +export type Route = { + key: string; + routeName: string; +} & (NavigationState | undefined); + +export type NavigationEventName = + | 'willFocus' + | 'didFocus' + | 'willBlur' + | 'didBlur'; + +export type NavigationState = { + key: string; + index: number; + routes: Route[]; + isTransitioning?: boolean; + params?: { [key: string]: unknown }; +}; + +export type NavigationProp = { + emit(eventName: string): void; + navigate(routeName: RouteName): void; + goBack(): void; + goBack(key: string | null): void; + addListener: ( + event: NavigationEventName, + callback: () => void + ) => { remove: () => void }; + isFocused(): boolean; + state: NavigationState; + setParams(params: Params): void; + getParam(): Params; + dispatch(action: { type: string }): void; + dangerouslyGetParent(): NavigationProp | undefined; +}; + +export type NavigationTabOptions = { + title?: string; + tabBarLabel?: React.ReactNode; + tabBarIcon?: + | React.ReactNode + | ((props: { + focused: boolean; + tintColor: string; + horizontal: boolean; + }) => React.ReactNode); + tabBarTestID?: string; + tabBarOnPress?: (props: { + navigation: NavigationProp; + defaultHandler: () => void; + }) => void; + tabBarOnLongPress?: (props: { + navigation: NavigationProp; + defaultHandler: () => void; + }) => void; + tabBarAccessibilityLabel?: string; +}; + +export type SceneDescriptor = { + key: string; + options: NavigationTabOptions; + navigation: NavigationProp; + getComponent(): React.ComponentType; +}; + +export type Screen = React.ComponentType & { + navigationOptions?: NavigationTabOptions & { + [key: string]: any; + }; +}; diff --git a/packages/bottom-tabs/src/utils/createTabNavigator.js b/packages/bottom-tabs/src/utils/createTabNavigator.js deleted file mode 100644 index 347a59a9..00000000 --- a/packages/bottom-tabs/src/utils/createTabNavigator.js +++ /dev/null @@ -1,206 +0,0 @@ -/* @flow */ - -import * as React from 'react'; -import { - TabRouter, - StackActions, - SceneView, - createNavigator, - SwitchActions, -} from '@react-navigation/core'; - -export type InjectedProps = {| - getLabelText: (props: { route: any }) => any, - getAccessibilityLabel: (props: { route: any }) => string, - getTestID: (props: { route: any }) => string, - renderIcon: (props: { - route: any, - focused: boolean, - tintColor: string, - horizontal?: boolean, - }) => React.Node, - renderScene: (props: { route: any }) => ?React.Node, - onIndexChange: (index: number) => any, - onTabPress: (props: { route: any }) => mixed, - onTabLongPress: (props: { route: any }) => mixed, - navigation: any, - descriptors: any, - screenProps?: any, -|}; - -export default function createTabNavigator(TabView: React.ComponentType<*>) { - class NavigationView extends React.Component<*, *> { - _renderScene = ({ route }) => { - const { screenProps, descriptors } = this.props; - const descriptor = descriptors[route.key]; - const TabComponent = descriptor.getComponent(); - return ( - - ); - }; - - _renderIcon = ({ route, focused, tintColor, horizontal = false }) => { - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const options = descriptor.options; - - if (options.tabBarIcon) { - return typeof options.tabBarIcon === 'function' - ? options.tabBarIcon({ focused, tintColor, horizontal }) - : options.tabBarIcon; - } - - return null; - }; - - _getLabelText = ({ route }) => { - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const options = descriptor.options; - - if (options.tabBarLabel) { - return options.tabBarLabel; - } - - if (typeof options.title === 'string') { - return options.title; - } - - return route.routeName; - }; - - _getAccessibilityLabel = ({ route }) => { - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const options = descriptor.options; - - if (typeof options.tabBarAccessibilityLabel !== 'undefined') { - return options.tabBarAccessibilityLabel; - } - - const label = this._getLabelText({ route }); - - if (typeof label === 'string') { - const { routes } = this.props.navigation.state; - return `${label}, tab, ${routes.indexOf(route) + 1} of ${ - routes.length - }`; - } - }; - - _getTestID = ({ route }) => { - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const options = descriptor.options; - - return options.tabBarTestID; - }; - - _makeDefaultHandler = ({ route, navigation }) => () => { - if (navigation.isFocused()) { - if (route.hasOwnProperty('index') && route.index > 0) { - // If current tab has a nested navigator, pop to top - navigation.dispatch(StackActions.popToTop({ key: route.key })); - } else { - navigation.emit('refocus'); - } - } else { - this._jumpTo(route.routeName); - } - }; - - _handleTabPress = ({ route }) => { - this._isTabPress = true; - - // After tab press, handleIndexChange will be called synchronously - // So we reset it in promise callback - Promise.resolve().then(() => (this._isTabPress = false)); - - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const { navigation, options } = descriptor; - - const defaultHandler = this._makeDefaultHandler({ route, navigation }); - - if (options.tabBarOnPress) { - options.tabBarOnPress({ navigation, defaultHandler }); - } else { - defaultHandler(); - } - }; - - _handleTabLongPress = ({ route }) => { - const { descriptors } = this.props; - const descriptor = descriptors[route.key]; - const { navigation, options } = descriptor; - - const defaultHandler = this._makeDefaultHandler({ route, navigation }); - - if (options.tabBarOnLongPress) { - options.tabBarOnLongPress({ navigation, defaultHandler }); - } else { - defaultHandler(); - } - }; - - _handleIndexChange = index => { - if (this._isTabPress) { - this._isTabPress = false; - return; - } - - this._jumpTo(this.props.navigation.state.routes[index].routeName); - }; - - _jumpTo = routeName => { - const { navigation } = this.props; - - navigation.dispatch( - SwitchActions.jumpTo({ - routeName, - key: navigation.state.key, - preserveFocus: true, - }) - ); - }; - - _isTabPress: boolean = false; - - render() { - const { descriptors, navigation, screenProps } = this.props; - const { state } = navigation; - const route = state.routes[state.index]; - const descriptor = descriptors[route.key]; - const options = { - ...this.props.navigationConfig, - ...descriptor.options, - }; - - return ( - - ); - } - } - - return (routes: *, config: * = {}) => { - const router = TabRouter(routes, config); - return createNavigator(NavigationView, router, config); - }; -} diff --git a/packages/bottom-tabs/src/utils/withDimensions.js b/packages/bottom-tabs/src/utils/withDimensions.js deleted file mode 100644 index f0e2d77b..00000000 --- a/packages/bottom-tabs/src/utils/withDimensions.js +++ /dev/null @@ -1,37 +0,0 @@ -import * as 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 withDimensions(WrappedComponent) { - const { width, height } = Dimensions.get('window'); - - class EnhancedComponent extends React.Component { - static displayName = `withDimensions(${WrappedComponent.displayName})`; - - state = { - dimensions: { width, height }, - isLandscape: isOrientationLandscape({ width, height }), - }; - - componentDidMount() { - Dimensions.addEventListener('change', this.handleOrientationChange); - } - - componentWillUnmount() { - Dimensions.removeEventListener('change', this.handleOrientationChange); - } - - handleOrientationChange = ({ window }) => { - const isLandscape = isOrientationLandscape(window); - this.setState({ isLandscape }); - }; - - render() { - return ; - } - } - - return hoistNonReactStatic(EnhancedComponent, WrappedComponent); -}