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

Commit 3702f17

Browse files
committed
fix: accept functions instead of component for header elements
closes #225
1 parent 679aadd commit 3702f17

4 files changed

Lines changed: 52 additions & 34 deletions

File tree

src/types.tsx

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { Animated, StyleProp, TextStyle, ViewStyle } from 'react-native';
1+
import {
2+
Animated,
3+
TextProps,
4+
StyleProp,
5+
TextStyle,
6+
ViewStyle,
7+
} from 'react-native';
28
import {
39
SafeAreaView,
410
NavigationRoute,
@@ -93,7 +99,9 @@ export type HeaderTransitionConfig = {
9399
export type NavigationStackOptions = {
94100
title?: string;
95101
header?: ((props: HeaderProps) => React.ReactNode) | null;
96-
headerTitle?: string;
102+
headerTitle?:
103+
| ((props: TextProps & { children?: string }) => React.ReactNode)
104+
| React.ReactNode;
97105
headerTitleStyle?: StyleProp<TextStyle>;
98106
headerTitleContainerStyle?: StyleProp<ViewStyle>;
99107
headerTintColor?: string;
@@ -102,14 +110,16 @@ export type NavigationStackOptions = {
102110
headerBackTitle?: string | null;
103111
headerBackTitleStyle?: StyleProp<TextStyle>;
104112
headerTruncatedBackTitle?: string;
105-
headerLeft?: React.FunctionComponent<HeaderBackButtonProps> | null;
113+
headerLeft?:
114+
| ((props: HeaderBackButtonProps) => React.ReactNode)
115+
| React.ReactNode;
106116
headerLeftContainerStyle?: StyleProp<ViewStyle>;
107117
headerRight?: (() => React.ReactNode) | React.ReactNode;
108118
headerRightContainerStyle?: StyleProp<ViewStyle>;
109-
headerBackImage?: React.FunctionComponent<{
110-
tintColor: string;
119+
headerBackImage?: (props: {
120+
tintColor?: string;
111121
title?: string | null;
112-
}>;
122+
}) => React.ReactNode;
113123
headerPressColorAndroid?: string;
114124
headerBackground?: React.ReactNode;
115125
headerTransparent?: boolean;
@@ -175,7 +185,7 @@ export type HeaderBackButtonProps = {
175185
disabled?: boolean;
176186
onPress: () => void;
177187
pressColorAndroid?: string;
178-
tintColor: string;
188+
tintColor?: string;
179189
backImage?: NavigationStackOptions['headerBackImage'];
180190
title?: string | null;
181191
truncatedTitle?: string | null;

src/views/Header/Header.tsx

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ViewStyle,
1212
LayoutChangeEvent,
1313
StyleProp,
14+
TextProps,
1415
} from 'react-native';
1516

1617
import {
@@ -29,6 +30,7 @@ import {
2930
HeaderLayoutPreset,
3031
SceneInterpolatorProps,
3132
HeaderProps,
33+
HeaderBackButtonProps,
3234
} from '../../types';
3335

3436
type Props = HeaderProps & {
@@ -216,27 +218,27 @@ class Header extends React.PureComponent<Props, State> {
216218
}
217219
: undefined;
218220

219-
const HeaderTitleComponent =
221+
const render =
220222
headerTitle && typeof headerTitle !== 'string'
221-
? headerTitle
222-
: HeaderTitle;
223-
return (
224-
<HeaderTitleComponent
225-
onLayout={onLayout}
226-
allowFontScaling={!!allowFontScaling}
227-
style={[
228-
color ? { color } : null,
229-
layoutPreset === 'center'
230-
? // eslint-disable-next-line react-native/no-inline-styles
231-
{ textAlign: 'center' }
232-
: // eslint-disable-next-line react-native/no-inline-styles
233-
{ textAlign: 'left' },
234-
titleStyle,
235-
]}
236-
>
237-
{titleString}
238-
</HeaderTitleComponent>
239-
);
223+
? (headerTitle as (
224+
props: TextProps & { children?: string }
225+
) => React.ReactNode)
226+
: (props: TextProps & { children?: string }) => (
227+
<HeaderTitle {...props} />
228+
);
229+
230+
return render({
231+
onLayout,
232+
allowFontScaling: Boolean(allowFontScaling),
233+
style: [
234+
color ? { color } : null,
235+
layoutPreset === 'center'
236+
? { textAlign: 'center' }
237+
: { textAlign: 'left' },
238+
titleStyle,
239+
],
240+
children: titleString,
241+
});
240242
};
241243

242244
private renderLeftComponent = (props: SubviewProps) => {
@@ -259,7 +261,9 @@ class Header extends React.PureComponent<Props, State> {
259261
const width = this.state.widths[props.scene.key]
260262
? (this.props.layout.initWidth - this.state.widths[props.scene.key]) / 2
261263
: undefined;
262-
const RenderedLeftComponent = options.headerLeft || HeaderBackButton;
264+
const RenderedLeftComponent =
265+
(options.headerLeft as React.FunctionComponent<HeaderBackButtonProps>) ||
266+
HeaderBackButton;
263267
const goBack = () => {
264268
// Go back on next tick because button ripple effect needs to happen on Android
265269
requestAnimationFrame(() => {
@@ -331,6 +335,11 @@ class Header extends React.PureComponent<Props, State> {
331335

332336
private renderRightComponent = (props: SubviewProps) => {
333337
const { headerRight } = props.scene.descriptor.options;
338+
339+
if (typeof headerRight === 'function') {
340+
return headerRight();
341+
}
342+
334343
return headerRight || null;
335344
};
336345

src/views/Header/HeaderBackButton.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ class HeaderBackButton extends React.PureComponent<
5454
if (React.isValidElement(backImage)) {
5555
return backImage;
5656
} else if (backImage) {
57-
const BackImage = backImage;
58-
59-
return <BackImage tintColor={tintColor} title={title} />;
57+
return backImage({
58+
tintColor,
59+
title,
60+
});
6061
} else {
6162
return (
6263
<Image

src/views/Header/ModularHeaderBackButton.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ class ModularHeaderBackButton extends React.PureComponent<Props, State> {
4545
if (React.isValidElement(backImage)) {
4646
return backImage;
4747
} else if (backImage) {
48-
const BackImage = backImage;
49-
50-
return <BackImage tintColor={tintColor} />;
48+
return backImage({ tintColor });
5149
} else {
5250
return (
5351
<Image

0 commit comments

Comments
 (0)