diff --git a/packages/bottom-tabs/src/types.tsx b/packages/bottom-tabs/src/types.tsx index 0015f4c2..5f332a14 100644 --- a/packages/bottom-tabs/src/types.tsx +++ b/packages/bottom-tabs/src/types.tsx @@ -17,8 +17,17 @@ import { import { TabNavigationState } from '@navigation-ex/routers'; export type BottomTabNavigationEventMap = { + /** + * Event which fires on tapping on the tab for an already focused screen. + */ refocus: undefined; + /** + * Event which fires on tapping on the tab in the tab bar. + */ tabPress: undefined; + /** + * Event which fires on long press on the tab in the tab bar. + */ tabLongPress: undefined; }; @@ -113,26 +122,77 @@ export type BottomTabDescriptorMap = { }; export type BottomTabNavigationConfig = { + /** + * Whether the screens should render the first time they are accessed. Defaults to `true`. + * Set it to `false` if you want to render all screens on initial render. + */ lazy?: boolean; + /** + * Custom tab bar component. + */ tabBarComponent?: React.ComponentType; + /** + * Options for the tab bar which will be passed as props to the tab bar component. + */ tabBarOptions?: BottomTabBarOptions; }; export type BottomTabBarOptions = { + /** + * Whether the tab bar gets hidden when the keyboard is shown. + */ keyboardHidesTabBar?: boolean; + /** + * Color for the icon and label in the active tab. + */ activeTintColor?: string; + /** + * Color for the icon and label in the inactive tabs. + */ inactiveTintColor?: string; + /** + * Background olor for the active tab. + */ activeBackgroundColor?: string; + /** + * background color for the inactive tabs. + */ inactiveBackgroundColor?: string; + /** + * Whether label font should scale to respect Text Size accessibility settings. + */ allowFontScaling?: boolean; + /** + * Whether the tab label should be visible. Defaults to `true`. + */ showLabel?: boolean; + /** + * Whether the tab icon should be visible. Defaults to `true`. + */ showIcon?: boolean; + /** + * Style object for the tab label. + */ labelStyle?: StyleProp; + /** + * Style object for the tab container. + */ tabStyle?: StyleProp; + /** + * Whether the label is renderd below the icon or beside the icon. + * When a function is passed, it receives the device orientation to render the label differently. + * By default, in `vertical` orinetation, label is rendered below and in `horizontal` orientation, it's renderd beside. + */ labelPosition?: | LabelPosition | ((options: { deviceOrientation: Orientation }) => LabelPosition); + /** + * Whether the label position should adapt to the orientation. + */ adaptive?: boolean; + /** + * Style object for the tab bar container. + */ style?: StyleProp; }; diff --git a/packages/drawer/src/types.tsx b/packages/drawer/src/types.tsx index e61a6ba9..eff8d74f 100644 --- a/packages/drawer/src/types.tsx +++ b/packages/drawer/src/types.tsx @@ -18,20 +18,74 @@ export type Scene = { }; export type DrawerNavigationConfig = { + /** + * Custom background color for the drawer. Defaults to `white`. + */ drawerBackgroundColor: string; + /** + * Position of the drawer on the screen. Defaults to `left`. + */ drawerPosition: 'left' | 'right'; + /** + * Type of the drawer. It determines how the drawer looks and animates. + * - `front`: Traditional drawer which covers the screen with a overlay behind it. + * - `back`: The drawer is revealed behind the screen on swipe. + * - `slide`: Both the screen and the drawer slide on swipe to reveal the drawer. + */ drawerType: 'front' | 'back' | 'slide'; + /** + * Number or a function which returns the width of the drawer. + * If a function is provided, it'll be called again when the screen's dimensions change. + */ drawerWidth: number | (() => number); + /** + * How far from the edge of the screen the swipe gesture should activate. + */ edgeWidth?: number; + /** + * Whether the statusbar should be hidden when the drawer is pulled or opens, + */ hideStatusBar: boolean; + /** + * Whether the keyboard should be dismissed when the swipe gesture begins. + * Defaults to `'on-drag'`. Set to `'none'` to disable keyboard handling. + */ keyboardDismissMode: 'on-drag' | 'none'; + /** + * Minimum swipe distance threshold that should activate opening the drawer. + */ minSwipeDistance?: number; + /** + * Color of the overlay to be displayed on top of the content view when drawer gets open. + * The opacity is animated from `0` to `1` when the drawer opens. + */ overlayColor?: string; + /** + * Animation of the statusbar when hiding it. use in combination with `hideStatusBar`. + */ statusBarAnimation: 'slide' | 'none' | 'fade'; + /** + * Props to pass to the underlying pan gesture handler. + */ gestureHandlerProps?: React.ComponentProps; + /** + * Whether the screens should render the first time they are accessed. Defaults to `true`. + * Set it to `false` if you want to render all screens on initial render. + */ lazy: boolean; + /** + * Whether a screen should be unmounted when navigating away from it. + * Defaults to `false`.. + */ unmountInactiveRoutes?: boolean; + /** + * Custom component used to render as the content of the drawer, for example, navigation items. + * Defaults to `DrawerItems`. + */ contentComponent: React.ComponentType; + /** + * Options for the content component which will be passed as props. + */ contentOptions?: object; contentContainerStyle?: StyleProp; style?: StyleProp; @@ -52,30 +106,79 @@ export type DrawerNavigationOptions = { export type ContentComponentProps = DrawerNavigationItemsProps & { navigation: NavigationHelpers; descriptors: { [key: string]: any }; + /** + * Animated node which represents the current progress of the drawer's open state. + * `0` is closed, `1` is open. + */ drawerOpenProgress: Animated.Node; }; export type DrawerNavigationItemsProps = { + /** + * The array of routes, can be modified or overridden to control what's shown in the drawer. + */ items: Route[]; + /** + * Route key identifying the currently active route. + */ activeItemKey?: string | null; + /** + * Color for the icon and label in the active item in the drawer. + */ activeTintColor?: string; + /** + * Background color for the active item in the drawer. + */ activeBackgroundColor?: string; + /** + * Color for the icon and label in the inactive items in the drawer. + */ inactiveTintColor?: string; + /** + * Background color for the inactive items in the drawer. + */ inactiveBackgroundColor?: string; + /** + * Style object for the content section. + */ + itemsContainerStyle?: ViewStyle; + /** + * Style object for the single item, which can contain an icon and/or a label. + */ + itemStyle?: StyleProp; + /** + * Style object to overwrite `Text` style inside content section which renders a label. + */ + labelStyle?: StyleProp; + /** + * Style object to overwrite `Text` style of the active label. + */ + activeLabelStyle?: StyleProp; + /** + * Style object to overwrite `Text` style of the inactive label. + */ + inactiveLabelStyle?: StyleProp; + /** + * Style object for the wrapper `View` of the icon. + */ + iconContainerStyle?: StyleProp; + /** + * Position of the drawer on the screen. + */ + drawerPosition: 'left' | 'right'; getLabel: (scene: Scene) => React.ReactNode; renderIcon: (scene: Scene) => React.ReactNode; onItemPress: (scene: { route: Route; focused: boolean }) => void; - itemsContainerStyle?: ViewStyle; - itemStyle?: StyleProp; - labelStyle?: StyleProp; - activeLabelStyle?: StyleProp; - inactiveLabelStyle?: StyleProp; - iconContainerStyle?: StyleProp; - drawerPosition: 'left' | 'right'; }; export type DrawerNavigationEventMap = { + /** + * Event which fires when the drawer opens. + */ drawerOpen: undefined; + /** + * Event which fires when the drawer closes. + */ drawerClose: undefined; }; diff --git a/packages/material-top-tabs/src/types.tsx b/packages/material-top-tabs/src/types.tsx index a9066dd5..97a59043 100644 --- a/packages/material-top-tabs/src/types.tsx +++ b/packages/material-top-tabs/src/types.tsx @@ -10,10 +10,25 @@ import { import { TabNavigationState } from '@navigation-ex/routers'; export type MaterialTopTabNavigationEventMap = { + /** + * Event which fires on tapping on the tab for an already focused screen. + */ refocus: undefined; + /** + * Event which fires on tapping on the tab in the tab bar. + */ tabPress: undefined; + /** + * Event which fires on long press on the tab in the tab bar. + */ tabLongPress: undefined; + /** + * Event which fires when a swipe gesture starts, i.e. finger touches the screen. + */ swipeStart: undefined; + /** + * Event which fires when a swipe gesture ends, i.e. finger leaves the screen. + */ swipeEnd: undefined; }; @@ -102,9 +117,27 @@ export type MaterialTopTabNavigationConfig = Partial< | 'renderLazyPlaceholder' > > & { + /** + * Component to render for routes that haven't been rendered yet. + * Receives an object containing the route as the prop. + * The lazy prop also needs to be enabled. + * + * This view is usually only shown for a split second. Keep it lightweight. + * + * By default, this renders null.. + */ lazyPlaceholderComponent?: React.ComponentType<{ route: Route }>; + /** + * Custom tab bar component. + */ tabBarComponent?: React.ComponentType; + /** + * Options for the tab bar which will be passed as props to the tab bar component. + */ tabBarOptions?: MaterialTopTabBarOptions; + /** + * Position of the tab bar. Defaults to `top`. + */ tabBarPosition?: 'top' | 'bottom'; }; @@ -124,12 +157,33 @@ export type MaterialTopTabBarOptions = Partial< | keyof SceneRendererProps > > & { + /** + * Color for the icon and label in the active tab. + */ activeTintColor?: string; + /** + * Color for the icon and label in the inactive tabs. + */ inactiveTintColor?: string; + /** + * Style object for the tab icon container. + */ iconStyle?: StyleProp; + /** + * Whether the tab label should be visible. Defaults to `true`. + */ showLabel?: boolean; + /** + * Whether the tab icon should be visible. Defaults to `false`. + */ showIcon?: boolean; + /** + * Whether the tab label text should capitalized. Defaults to `true`. + */ upperCaseLabel?: boolean; + /** + * Whether label font should scale to respect Text Size accessibility settings. + */ allowFontScaling?: boolean; }; diff --git a/packages/stack/src/types.tsx b/packages/stack/src/types.tsx index 0f29cc25..c7ed3cb4 100644 --- a/packages/stack/src/types.tsx +++ b/packages/stack/src/types.tsx @@ -14,7 +14,13 @@ import { import { StackNavigationState } from '@navigation-ex/routers'; export type StackNavigationEventMap = { + /** + * Event which fires when a transition animation starts. + */ transitionStart: { closing: boolean }; + /** + * Event which fires when a transition animation ends. + */ transitionEnd: { closing: boolean }; }; @@ -58,44 +64,157 @@ export type GestureDirection = 'horizontal' | 'vertical'; export type HeaderMode = 'float' | 'screen' | 'none'; export type HeaderScene = { + /** + * Current route object, + */ route: T; + /** + * Descriptor object for the route containing options and navigation object. + */ descriptor: StackDescriptor; + /** + * Animated nodes representing the progress of the animation. + */ progress: { + /** + * Progress value of the current screen. + */ current: Animated.Node; + /** + * Progress value for the screen after this one in the stack. + * This can be `undefined` in case the screen animating is the last one. + */ next?: Animated.Node; + /** + * Progress value for the screen before this one in the stack. + * This can be `undefined` in case the screen animating is the first one. + */ previous?: Animated.Node; }; }; export type HeaderOptions = { + /** + * String or a function that returns a React Element to be used by the header. + * Defaults to scene `title`. + * It receives `allowFontScaling`, `onLayout`, `style` and `children` in the options object as an argument. + * The title string is passed in `children`. + */ headerTitle?: string | ((props: HeaderTitleProps) => React.ReactNode); + /** + * Style object for the title component. + */ headerTitleStyle?: StyleProp; + /** + * Style object for the container of the `headerTitle` component, for example to add padding. + * By default, `headerTitleContainerStyle` is with an absolute position style and offsets both `left` and `right`. + * This may lead to white space or overlap between `headerLeft` and `headerTitle` if a customized `headerLeft` is used. + * It can be solved by adjusting `left` and `right` style in `headerTitleContainerStyle` and `marginHorizontal` in `headerTitleStyle`. + */ headerTitleContainerStyle?: StyleProp; + /** + * Tint color for the header. + */ headerTintColor?: string; + /** + * Whether header title font should scale to respect Text Size accessibility settings. Defaults to `false`. + */ headerTitleAllowFontScaling?: boolean; + /** + * Whether back button title font should scale to respect Text Size accessibility settings. Defaults to `false`. + */ headerBackAllowFontScaling?: boolean; + /** + * Title string used by the back button on iOS, or `null` to disable label. Defaults to the previous scene's `headerTitle`. + */ headerBackTitle?: string; + /** + * Style object for the back title. + */ headerBackTitleStyle?: StyleProp; + /** + * A reasonable default is supplied for whether the back button title should be visible or not. + * But if you want to override that you can use `true` or `false` in this option. + */ headerBackTitleVisible?: boolean; + /** + * Title string used by the back button when `headerBackTitle` doesn't fit on the screen. `"Back"` by default. + */ headerTruncatedBackTitle?: string; - headerLeft?: (props: HeaderBackButtonProps) => React.ReactNode; + /** + * Function which returns a React Element to display on the left side of the header. + * It receives a number of arguments when rendered (`onPress`, `label`, `labelStyle` and more. + */ + headerLeft?: (props: HeaderLeftButtonProps) => React.ReactNode; + /** + * Style object for the container of the `headerLeft` component, for example to add padding. + */ headerLeftContainerStyle?: StyleProp; + /** + * Function which returns a React Element to display on the right side of the header. + */ headerRight?: (props: { tintColor?: string }) => React.ReactNode; + /** + * Style object for the container of the `headerRight` component, for example to add padding. + */ headerRightContainerStyle?: StyleProp; - headerBackImage?: HeaderBackButtonProps['backImage']; + /** + * Function which returns a React Element to display custom image in header's back button. + * It receives the `tintColor` in in the options object as an argument. object. + * Defaults to Image component with a the default back icon image for the platform (a chevron on iOS and an arrow on Android). + */ + headerBackImage?: HeaderLeftButtonProps['backImage']; + /** + * Color for material ripple (Android >= 5.0 only). + */ headerPressColorAndroid?: string; + /** + * Function which returns a React Element to render as the background of the header. + * This is useful for using backgrounds such as an image or a gradient. + * You can use this with `headerTransparent` to render a blur view, for example, to create a translucent header. + */ headerBackground?: () => React.ReactNode; + /** + * Style object for the header. You can specify a custom background color here, for example. + */ headerStyle?: StyleProp; + /** + * Custom status bar height to set as the top padding in the header. + */ headerStatusBarHeight?: number; + /** + * Defaults to `false`. If `true`, the header will not have a background unless you explicitly provide it with `headerBackground`. + * The header will also float over the screen so that it overlaps the content underneath. + * This is useful if you want to render a semi-transparent header or a blurred background. + */ headerTransparent?: boolean; }; export type HeaderProps = { + /** + * Mode of the header: `float` renders a single floating header across all screens, + * `screen` renders separate headers for each screen. + */ mode: 'float' | 'screen'; + /** + * Layout of the screen. + */ layout: Layout; + /** + * Object representing the current scene, such as the route object and animation progress. + */ scene: HeaderScene>; + /** + * Object representing the previous scene. + */ previous?: HeaderScene>; + /** + * Navigation prop for the header. + */ navigation: StackNavigationProp; + /** + * Interpolated styles for various elements in the header. + */ styleInterpolator: HeaderStyleInterpolator; }; @@ -110,22 +229,60 @@ export type StackDescriptorMap = { [key: string]: StackDescriptor; }; -export type TransitionCallbackProps = { - closing: boolean; -}; - export type StackNavigationOptions = HeaderOptions & Partial & { + /** + * String that can be displayed in the header as a fallback for `headerTitle`. + */ title?: string; + /** + * Function that given `HeaderProps` returns a React Element to display as a header. + * Setting to `null` hides header. + */ header?: null | ((props: HeaderProps) => React.ReactNode); + /** + * Whether a shadow is visible for the card during transitions. Defaults to `true`. + */ cardShadowEnabled?: boolean; + /** + * Whether to have a semi-transparent dark overlay visible under the card during transitions. + * Defaults to `true` on Android and `false` on iOS. + */ cardOverlayEnabled?: boolean; + /** + * Whether to use a transparent background for the card instead of a white one. + * This is useful to implement things like modal dialogs where the previous scene should still be visible underneath the current one. + * Defaults to `false`. + * + * If you use [`react-native-screens`](https://github.com/kmagiera/react-native-screens), + * you should also specify `mode: 'modal'` in the stack view config so previous screens aren't detached. + */ cardTransparent?: boolean; + /** + * Style object for the card in stack. + * You can provide a custom background color to use instead of the default background here. + */ cardStyle?: StyleProp; + /** + * Whether transition animation should be enabled the screen. + * If you set it to `false`, the screen won't animate when pushing or popping. Defaults to `true`. + */ animationEnabled?: boolean; + /** + * Whether you can use gestures to dismiss this screen. Defaults to `true` on iOS, `false` on Android. + */ gestureEnabled?: boolean; + /** + * Object to override the distance of touch start from the edge of the screen to recognize gestures. + */ gestureResponseDistance?: { + /** + * Distance for horizontal direction. Defaults to 25. + */ vertical?: number; + /** + * Distance for vertical direction. Defaults to 135. + */ horizontal?: number; }; }; @@ -133,30 +290,91 @@ export type StackNavigationOptions = HeaderOptions & export type StackNavigationConfig = { mode?: 'card' | 'modal'; headerMode?: HeaderMode; + /** + * If `false`, the keyboard will NOT automatically dismiss when navigating to a new screen. + * Defaults to `true`. + */ keyboardHandlingEnabled?: boolean; }; -export type HeaderBackButtonProps = { +export type HeaderLeftButtonProps = { + /** + * Whether the button is disabled. + */ disabled?: boolean; + /** + * Callback to call when the button is pressed. + * By default, this triggers `goBack`. + */ onPress?: () => void; + /** + * Color for material ripple (Android >= 5.0 only). + */ pressColorAndroid?: string; + /** + * Function which returns a React Element to display custom image in header's back button. + */ backImage?: (props: { tintColor: string }) => React.ReactNode; + /** + * Tint color for the header. + */ tintColor?: string; + /** + * Label text for the button. Usually the title of the previous screen. + * By default, this is only shown on iOS. + */ label?: string; + /** + * Label text to show when there isn't enough space for the full label. + */ truncatedLabel?: string; + /** + * Whether the label text is visible. + * Defaults to `true` on iOS and `false` on Android. + */ labelVisible?: boolean; + /** + * Style object for the label. + */ labelStyle?: React.ComponentProps['style']; + /** + * Whether label font should scale to respect Text Size accessibility settings. + */ allowFontScaling?: boolean; + /** + * Callback to trigger when the size of the label changes. + */ onLabelLayout?: (e: LayoutChangeEvent) => void; + /** + * Layout of the screen. + */ screenLayout?: Layout; + /** + * Layout of the title element in the header. + */ titleLayout?: Layout; + /** + * Whether it's possible to navigate back in stack. + */ canGoBack?: boolean; }; export type HeaderTitleProps = { + /** + * Callback to trigger when the size of the title element changes. + */ onLayout: (e: LayoutChangeEvent) => void; + /** + * Whether title font should scale to respect Text Size accessibility settings. + */ allowFontScaling?: boolean; + /** + * Content of the title element. Usually the title string. + */ children?: string; + /** + * Style object for the title element. + */ style?: StyleProp; }; @@ -185,21 +403,55 @@ export type TransitionSpec = | { timing: 'timing'; config: TimingConfig }; export type CardInterpolationProps = { + /** + * The index of the card in the stack. + */ index: number; + /** + * Animated nodes representing the progress of the animation. + */ progress: { + /** + * Progress value of the current screen. + */ current: Animated.Node; + /** + * Progress value for the screen after this one in the stack. + * This can be `undefined` in case the screen animating is the last one. + */ next?: Animated.Node; }; + /** + * Animated node representing whether the card is closing. + */ closing: Animated.Node<0 | 1>; + /** + * Layout measurements for various items we use for animation. + */ layouts: { + /** + * Layout of the whole screen. + */ screen: Layout; }; }; export type CardInterpolatedStyle = { + /** + * Interpolated style for the container view wrapping the card. + */ containerStyle?: any; + /** + * Interpolated style for the view representing the card. + */ cardStyle?: any; + /** + * Interpolated style for the view representing the semi-transparent overlay below the card. + */ overlayStyle?: any; + /** + * Interpolated style representing the card shadow. + */ shadowStyle?: any; }; @@ -208,22 +460,59 @@ export type CardStyleInterpolator = ( ) => CardInterpolatedStyle; export type HeaderInterpolationProps = { + /** + * Animated nodes representing the progress of the animation. + */ progress: { + /** + * Progress value of the current screen (the screen which owns this header). + */ current: Animated.Node; + /** + * Progress value for the screen after this one in the stack. + * This can be `undefined` in case the screen animating is the last one. + */ next?: Animated.Node; }; + /** + * Layout measurements for various items we use for animation. + */ layouts: { + /** + * Layout of the whole screen. + */ screen: Layout; + /** + * Layout of the title element. + */ title?: Layout; + /** + * Layout of the back button label. + */ leftLabel?: Layout; }; }; export type HeaderInterpolatedStyle = { + /** + * Interpolated style for the label of the left button (back button label). + */ leftLabelStyle?: any; + /** + * Interpolated style for the left button (usually the back button). + */ leftButtonStyle?: any; + /** + * Interpolated style for the right button. + */ rightButtonStyle?: any; + /** + * Interpolated style for the header title text. + */ titleStyle?: any; + /** + * Interpolated style for the header background. + */ backgroundStyle?: any; }; @@ -232,11 +521,29 @@ export type HeaderStyleInterpolator = ( ) => HeaderInterpolatedStyle; export type TransitionPreset = { + /** + * The direction of swipe gestures, `horizontal` or `vertical`. + */ gestureDirection: GestureDirection; + /** + * Object which specifies the animation type (timing or spring) and their options (such as duration for timing). + */ transitionSpec: { + /** + * Transition configuration when adding a screen. + */ open: TransitionSpec; + /** + * Transition configuration when removing a screen. + */ close: TransitionSpec; }; + /** + * Function which specifies interpolated styles for various parts of the card, e.g. the overlay, shadow etc. + */ cardStyleInterpolator: CardStyleInterpolator; + /** + * Function which specifies interpolated styles for various parts of the header, e.g. the title, left button etc. + */ headerStyleInterpolator: HeaderStyleInterpolator; }; diff --git a/packages/stack/src/views/Header/HeaderBackButton.tsx b/packages/stack/src/views/Header/HeaderBackButton.tsx index 32b436a0..885fe54a 100644 --- a/packages/stack/src/views/Header/HeaderBackButton.tsx +++ b/packages/stack/src/views/Header/HeaderBackButton.tsx @@ -11,13 +11,13 @@ import { import Animated from 'react-native-reanimated'; import MaskedView from '@react-native-community/masked-view'; import TouchableItem from '../TouchableItem'; -import { HeaderBackButtonProps } from '../../types'; +import { HeaderLeftButtonProps } from '../../types'; const isMaskedViewAvailable = // @ts-ignore UIManager.getViewManagerConfig('RNCMaskedView') != null; -type Props = HeaderBackButtonProps & { +type Props = HeaderLeftButtonProps & { tintColor: string; }; diff --git a/packages/stack/src/views/Header/HeaderSegment.tsx b/packages/stack/src/views/Header/HeaderSegment.tsx index 8f7d5959..0295436e 100644 --- a/packages/stack/src/views/Header/HeaderSegment.tsx +++ b/packages/stack/src/views/Header/HeaderSegment.tsx @@ -15,7 +15,7 @@ import memoize from '../../utils/memoize'; import { Layout, HeaderStyleInterpolator, - HeaderBackButtonProps, + HeaderLeftButtonProps, HeaderTitleProps, HeaderOptions, HeaderScene, @@ -142,7 +142,7 @@ export default class HeaderSegment extends React.Component { onGoBack, headerTitle, headerLeft: left = onGoBack - ? (props: HeaderBackButtonProps) => + ? (props: HeaderLeftButtonProps) => : undefined, // @ts-ignore headerStatusBarHeight = getStatusBarHeight(layout.width > layout.height),