@react-navigation/elements
Advanced tools
Comparing version 2.0.0-rc.18 to 2.0.0-rc.19
@@ -43,9 +43,4 @@ "use strict"; | ||
headerTitle: customTitle, | ||
// eslint-disable-next-line @eslint-react/no-unstable-default-props | ||
headerTitleAlign = _reactNative.Platform.select({ | ||
ios: 'center', | ||
default: 'left' | ||
}), | ||
headerTitleAlign = _reactNative.Platform.OS === 'ios' ? 'center' : 'left', | ||
headerLeft, | ||
headerLeftLabelVisible, | ||
headerTransparent, | ||
@@ -60,2 +55,3 @@ headerTintColor, | ||
headerTitleContainerStyle: titleContainerStyle, | ||
headerBackButtonDisplayMode = _reactNative.Platform.OS === 'ios' ? 'default' : 'minimal', | ||
headerBackgroundContainerStyle: backgroundContainerStyle, | ||
@@ -174,3 +170,3 @@ headerStyle: customHeaderStyle, | ||
pressOpacity: headerPressOpacity, | ||
labelVisible: headerLeftLabelVisible | ||
displayMode: headerBackButtonDisplayMode | ||
}) : null; | ||
@@ -220,3 +216,3 @@ const rightButton = headerRight ? headerRight({ | ||
// Avoid the title from going offscreen or overlapping buttons | ||
maxWidth: headerTitleAlign === 'center' ? layout.width - ((leftButton ? headerLeftLabelVisible !== false ? 80 : 32 : 16) + (rightButton ? 16 : 0) + Math.max(insets.left, insets.right)) * 2 : layout.width - ((leftButton ? 52 : 16) + (rightButton ? 52 : 16) + insets.left - insets.right) | ||
maxWidth: headerTitleAlign === 'center' ? layout.width - ((leftButton ? headerBackButtonDisplayMode !== 'minimal' ? 80 : 32 : 16) + (rightButton ? 16 : 0) + Math.max(insets.left, insets.right)) * 2 : layout.width - ((leftButton ? 52 : 16) + (rightButton ? 52 : 16) + insets.left - insets.right) | ||
}, headerTitleAlign === 'left' && leftButton ? { | ||
@@ -223,0 +219,0 @@ marginStart: 4 |
@@ -24,3 +24,3 @@ "use strict"; | ||
labelStyle, | ||
labelVisible = _reactNative.Platform.OS === 'ios', | ||
displayMode = _reactNative.Platform.OS === 'ios' ? 'default' : 'minimal', | ||
onLabelLayout, | ||
@@ -46,13 +46,4 @@ onPress, | ||
} = (0, _native.useLocale)(); | ||
const [initialLabelWidth, setInitialLabelWidth] = React.useState(undefined); | ||
const handleLabelLayout = e => { | ||
onLabelLayout?.(e); | ||
const { | ||
layout | ||
} = e.nativeEvent; | ||
setInitialLabelWidth((direction === 'rtl' ? layout.y : layout.x) + layout.width); | ||
}; | ||
const shouldTruncateLabel = () => { | ||
return !label || initialLabelWidth && titleLayout && screenLayout && (screenLayout.width - titleLayout.width) / 2 < initialLabelWidth + 26; | ||
}; | ||
const [labelWidth, setLabelWidth] = React.useState(null); | ||
const [truncatedLabelWidth, setTruncatedLabelWidth] = React.useState(null); | ||
const renderBackImage = () => { | ||
@@ -65,3 +56,3 @@ if (backImage) { | ||
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, { | ||
style: [styles.icon, direction === 'rtl' && styles.flip, Boolean(labelVisible) && styles.iconWithLabel, Boolean(tintColor) && { | ||
style: [styles.icon, direction === 'rtl' && styles.flip, displayMode !== 'minimal' && styles.iconWithLabel, Boolean(tintColor) && { | ||
tintColor | ||
@@ -76,21 +67,37 @@ }], | ||
const renderLabel = () => { | ||
const leftLabelText = shouldTruncateLabel() ? truncatedLabel : label; | ||
if (!labelVisible || leftLabelText === undefined) { | ||
if (displayMode === 'minimal') { | ||
return null; | ||
} | ||
const labelElement = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { | ||
const availableSpace = titleLayout && screenLayout ? (screenLayout.width - titleLayout.width) / 2 - (ICON_WIDTH + ICON_MARGIN_START) : null; | ||
const potentialLabelText = displayMode === 'default' ? label : truncatedLabel; | ||
const finalLabelText = availableSpace && labelWidth && truncatedLabelWidth ? availableSpace > labelWidth ? potentialLabelText : availableSpace > truncatedLabelWidth ? truncatedLabel : null : potentialLabelText; | ||
const commonStyle = [fonts.regular, styles.label, labelStyle]; | ||
const hiddenStyle = [commonStyle, { | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
opacity: 0 | ||
}]; | ||
const labelElement = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { | ||
style: styles.labelWrapper, | ||
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.Text, { | ||
children: [label && displayMode === 'default' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.Text, { | ||
style: hiddenStyle, | ||
numberOfLines: 1, | ||
onLayout: e => setLabelWidth(e.nativeEvent.layout.width), | ||
children: label | ||
}) : null, truncatedLabel ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.Text, { | ||
style: hiddenStyle, | ||
numberOfLines: 1, | ||
onLayout: e => setTruncatedLabelWidth(e.nativeEvent.layout.width), | ||
children: truncatedLabel | ||
}) : null, finalLabelText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.Text, { | ||
accessible: false, | ||
onLayout: | ||
// This measurement is used to determine if we should truncate the label when it doesn't fit | ||
// Only measure it when label is not truncated because we want the measurement of full label | ||
leftLabelText === label ? handleLabelLayout : undefined, | ||
onLayout: onLabelLayout, | ||
style: [tintColor ? { | ||
color: tintColor | ||
} : null, fonts.regular, styles.label, labelStyle], | ||
} : null, commonStyle], | ||
numberOfLines: 1, | ||
allowFontScaling: !!allowFontScaling, | ||
children: leftLabelText | ||
}) | ||
children: finalLabelText | ||
}) : null] | ||
}); | ||
@@ -139,2 +146,7 @@ if (backImage || _reactNative.Platform.OS !== 'ios') { | ||
} | ||
const ICON_WIDTH = _reactNative.Platform.OS === 'ios' ? 13 : 24; | ||
const ICON_HEIGHT = _reactNative.Platform.OS === 'ios' ? 21 : 24; | ||
const ICON_MARGIN_START = _reactNative.Platform.OS === 'ios' ? 8 : 3; | ||
const ICON_MARGIN_END = _reactNative.Platform.OS === 'ios' ? 22 : 3; | ||
const ICON_MARGIN_VERTICAL = _reactNative.Platform.OS === 'ios' ? 8 : 3; | ||
const styles = _reactNative.StyleSheet.create({ | ||
@@ -173,16 +185,9 @@ container: { | ||
}, | ||
icon: _reactNative.Platform.select({ | ||
ios: { | ||
height: 21, | ||
width: 13, | ||
marginStart: 8, | ||
marginEnd: 22, | ||
marginVertical: 8 | ||
}, | ||
default: { | ||
height: 24, | ||
width: 24, | ||
margin: 3 | ||
} | ||
}), | ||
icon: { | ||
height: ICON_HEIGHT, | ||
width: ICON_WIDTH, | ||
marginStart: ICON_MARGIN_START, | ||
marginEnd: ICON_MARGIN_END, | ||
marginVertical: ICON_MARGIN_VERTICAL | ||
}, | ||
iconWithLabel: _reactNative.Platform.OS === 'ios' ? { | ||
@@ -189,0 +194,0 @@ marginEnd: 6 |
@@ -38,9 +38,4 @@ "use strict"; | ||
headerTitle: customTitle, | ||
// eslint-disable-next-line @eslint-react/no-unstable-default-props | ||
headerTitleAlign = Platform.select({ | ||
ios: 'center', | ||
default: 'left' | ||
}), | ||
headerTitleAlign = Platform.OS === 'ios' ? 'center' : 'left', | ||
headerLeft, | ||
headerLeftLabelVisible, | ||
headerTransparent, | ||
@@ -55,2 +50,3 @@ headerTintColor, | ||
headerTitleContainerStyle: titleContainerStyle, | ||
headerBackButtonDisplayMode = Platform.OS === 'ios' ? 'default' : 'minimal', | ||
headerBackgroundContainerStyle: backgroundContainerStyle, | ||
@@ -169,3 +165,3 @@ headerStyle: customHeaderStyle, | ||
pressOpacity: headerPressOpacity, | ||
labelVisible: headerLeftLabelVisible | ||
displayMode: headerBackButtonDisplayMode | ||
}) : null; | ||
@@ -215,3 +211,3 @@ const rightButton = headerRight ? headerRight({ | ||
// Avoid the title from going offscreen or overlapping buttons | ||
maxWidth: headerTitleAlign === 'center' ? layout.width - ((leftButton ? headerLeftLabelVisible !== false ? 80 : 32 : 16) + (rightButton ? 16 : 0) + Math.max(insets.left, insets.right)) * 2 : layout.width - ((leftButton ? 52 : 16) + (rightButton ? 52 : 16) + insets.left - insets.right) | ||
maxWidth: headerTitleAlign === 'center' ? layout.width - ((leftButton ? headerBackButtonDisplayMode !== 'minimal' ? 80 : 32 : 16) + (rightButton ? 16 : 0) + Math.max(insets.left, insets.right)) * 2 : layout.width - ((leftButton ? 52 : 16) + (rightButton ? 52 : 16) + insets.left - insets.right) | ||
}, headerTitleAlign === 'left' && leftButton ? { | ||
@@ -218,0 +214,0 @@ marginStart: 4 |
@@ -17,3 +17,3 @@ "use strict"; | ||
labelStyle, | ||
labelVisible = Platform.OS === 'ios', | ||
displayMode = Platform.OS === 'ios' ? 'default' : 'minimal', | ||
onLabelLayout, | ||
@@ -39,13 +39,4 @@ onPress, | ||
} = useLocale(); | ||
const [initialLabelWidth, setInitialLabelWidth] = React.useState(undefined); | ||
const handleLabelLayout = e => { | ||
onLabelLayout?.(e); | ||
const { | ||
layout | ||
} = e.nativeEvent; | ||
setInitialLabelWidth((direction === 'rtl' ? layout.y : layout.x) + layout.width); | ||
}; | ||
const shouldTruncateLabel = () => { | ||
return !label || initialLabelWidth && titleLayout && screenLayout && (screenLayout.width - titleLayout.width) / 2 < initialLabelWidth + 26; | ||
}; | ||
const [labelWidth, setLabelWidth] = React.useState(null); | ||
const [truncatedLabelWidth, setTruncatedLabelWidth] = React.useState(null); | ||
const renderBackImage = () => { | ||
@@ -58,3 +49,3 @@ if (backImage) { | ||
return /*#__PURE__*/_jsx(Image, { | ||
style: [styles.icon, direction === 'rtl' && styles.flip, Boolean(labelVisible) && styles.iconWithLabel, Boolean(tintColor) && { | ||
style: [styles.icon, direction === 'rtl' && styles.flip, displayMode !== 'minimal' && styles.iconWithLabel, Boolean(tintColor) && { | ||
tintColor | ||
@@ -69,21 +60,37 @@ }], | ||
const renderLabel = () => { | ||
const leftLabelText = shouldTruncateLabel() ? truncatedLabel : label; | ||
if (!labelVisible || leftLabelText === undefined) { | ||
if (displayMode === 'minimal') { | ||
return null; | ||
} | ||
const labelElement = /*#__PURE__*/_jsx(View, { | ||
const availableSpace = titleLayout && screenLayout ? (screenLayout.width - titleLayout.width) / 2 - (ICON_WIDTH + ICON_MARGIN_START) : null; | ||
const potentialLabelText = displayMode === 'default' ? label : truncatedLabel; | ||
const finalLabelText = availableSpace && labelWidth && truncatedLabelWidth ? availableSpace > labelWidth ? potentialLabelText : availableSpace > truncatedLabelWidth ? truncatedLabel : null : potentialLabelText; | ||
const commonStyle = [fonts.regular, styles.label, labelStyle]; | ||
const hiddenStyle = [commonStyle, { | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
opacity: 0 | ||
}]; | ||
const labelElement = /*#__PURE__*/_jsxs(View, { | ||
style: styles.labelWrapper, | ||
children: /*#__PURE__*/_jsx(Animated.Text, { | ||
children: [label && displayMode === 'default' ? /*#__PURE__*/_jsx(Animated.Text, { | ||
style: hiddenStyle, | ||
numberOfLines: 1, | ||
onLayout: e => setLabelWidth(e.nativeEvent.layout.width), | ||
children: label | ||
}) : null, truncatedLabel ? /*#__PURE__*/_jsx(Animated.Text, { | ||
style: hiddenStyle, | ||
numberOfLines: 1, | ||
onLayout: e => setTruncatedLabelWidth(e.nativeEvent.layout.width), | ||
children: truncatedLabel | ||
}) : null, finalLabelText ? /*#__PURE__*/_jsx(Animated.Text, { | ||
accessible: false, | ||
onLayout: | ||
// This measurement is used to determine if we should truncate the label when it doesn't fit | ||
// Only measure it when label is not truncated because we want the measurement of full label | ||
leftLabelText === label ? handleLabelLayout : undefined, | ||
onLayout: onLabelLayout, | ||
style: [tintColor ? { | ||
color: tintColor | ||
} : null, fonts.regular, styles.label, labelStyle], | ||
} : null, commonStyle], | ||
numberOfLines: 1, | ||
allowFontScaling: !!allowFontScaling, | ||
children: leftLabelText | ||
}) | ||
children: finalLabelText | ||
}) : null] | ||
}); | ||
@@ -132,2 +139,7 @@ if (backImage || Platform.OS !== 'ios') { | ||
} | ||
const ICON_WIDTH = Platform.OS === 'ios' ? 13 : 24; | ||
const ICON_HEIGHT = Platform.OS === 'ios' ? 21 : 24; | ||
const ICON_MARGIN_START = Platform.OS === 'ios' ? 8 : 3; | ||
const ICON_MARGIN_END = Platform.OS === 'ios' ? 22 : 3; | ||
const ICON_MARGIN_VERTICAL = Platform.OS === 'ios' ? 8 : 3; | ||
const styles = StyleSheet.create({ | ||
@@ -166,16 +178,9 @@ container: { | ||
}, | ||
icon: Platform.select({ | ||
ios: { | ||
height: 21, | ||
width: 13, | ||
marginStart: 8, | ||
marginEnd: 22, | ||
marginVertical: 8 | ||
}, | ||
default: { | ||
height: 24, | ||
width: 24, | ||
margin: 3 | ||
} | ||
}), | ||
icon: { | ||
height: ICON_HEIGHT, | ||
width: ICON_WIDTH, | ||
marginStart: ICON_MARGIN_START, | ||
marginEnd: ICON_MARGIN_END, | ||
marginVertical: ICON_MARGIN_VERTICAL | ||
}, | ||
iconWithLabel: Platform.OS === 'ios' ? { | ||
@@ -182,0 +187,0 @@ marginEnd: 6 |
import type { HeaderBackButtonProps } from '../types'; | ||
export declare function HeaderBackButton({ disabled, allowFontScaling, backImage, label, labelStyle, labelVisible, onLabelLayout, onPress, pressColor, pressOpacity, screenLayout, tintColor, titleLayout, truncatedLabel, accessibilityLabel, testID, style, href, }: HeaderBackButtonProps): import("react/jsx-runtime").JSX.Element; | ||
export declare function HeaderBackButton({ disabled, allowFontScaling, backImage, label, labelStyle, displayMode, onLabelLayout, onPress, pressColor, pressOpacity, screenLayout, tintColor, titleLayout, truncatedLabel, accessibilityLabel, testID, style, href, }: HeaderBackButtonProps): import("react/jsx-runtime").JSX.Element; | ||
//# sourceMappingURL=HeaderBackButton.d.ts.map |
import type { Animated, LayoutChangeEvent, StyleProp, TextStyle, ViewStyle } from 'react-native'; | ||
export type HeaderBackButtonDisplayMode = 'default' | 'generic' | 'minimal'; | ||
export type Layout = { | ||
@@ -39,9 +40,16 @@ width: number; | ||
pressOpacity?: number; | ||
labelVisible?: boolean; | ||
displayMode?: HeaderBackButtonDisplayMode; | ||
href?: undefined; | ||
}) => React.ReactNode; | ||
/** | ||
* Whether a label is visible in the left button. Used to add extra padding. | ||
* How the back button displays icon and title. | ||
* | ||
* Supported values: | ||
* - "default" - Displays one of the following depending on the available space: previous screen's title, truncated title (e.g. 'Back') or no title (only icon). | ||
* - "generic" – Displays one of the following depending on the available space: truncated title (e.g. 'Back') or no title (only icon). | ||
* - "minimal" – Always displays only the icon without a title. | ||
* | ||
* Defaults to "default" on iOS, and "minimal" on Android. | ||
*/ | ||
headerLeftLabelVisible?: boolean; | ||
headerBackButtonDisplayMode?: HeaderBackButtonDisplayMode; | ||
/** | ||
@@ -205,3 +213,3 @@ * Style object for the container of the `headerLeft` element`. | ||
*/ | ||
labelVisible?: boolean; | ||
displayMode?: HeaderBackButtonDisplayMode; | ||
/** | ||
@@ -208,0 +216,0 @@ * Style object for the label. |
import type { HeaderBackButtonProps } from '../types'; | ||
export declare function HeaderBackButton({ disabled, allowFontScaling, backImage, label, labelStyle, labelVisible, onLabelLayout, onPress, pressColor, pressOpacity, screenLayout, tintColor, titleLayout, truncatedLabel, accessibilityLabel, testID, style, href, }: HeaderBackButtonProps): import("react/jsx-runtime").JSX.Element; | ||
export declare function HeaderBackButton({ disabled, allowFontScaling, backImage, label, labelStyle, displayMode, onLabelLayout, onPress, pressColor, pressOpacity, screenLayout, tintColor, titleLayout, truncatedLabel, accessibilityLabel, testID, style, href, }: HeaderBackButtonProps): import("react/jsx-runtime").JSX.Element; | ||
//# sourceMappingURL=HeaderBackButton.d.ts.map |
import type { Animated, LayoutChangeEvent, StyleProp, TextStyle, ViewStyle } from 'react-native'; | ||
export type HeaderBackButtonDisplayMode = 'default' | 'generic' | 'minimal'; | ||
export type Layout = { | ||
@@ -39,9 +40,16 @@ width: number; | ||
pressOpacity?: number; | ||
labelVisible?: boolean; | ||
displayMode?: HeaderBackButtonDisplayMode; | ||
href?: undefined; | ||
}) => React.ReactNode; | ||
/** | ||
* Whether a label is visible in the left button. Used to add extra padding. | ||
* How the back button displays icon and title. | ||
* | ||
* Supported values: | ||
* - "default" - Displays one of the following depending on the available space: previous screen's title, truncated title (e.g. 'Back') or no title (only icon). | ||
* - "generic" – Displays one of the following depending on the available space: truncated title (e.g. 'Back') or no title (only icon). | ||
* - "minimal" – Always displays only the icon without a title. | ||
* | ||
* Defaults to "default" on iOS, and "minimal" on Android. | ||
*/ | ||
headerLeftLabelVisible?: boolean; | ||
headerBackButtonDisplayMode?: HeaderBackButtonDisplayMode; | ||
/** | ||
@@ -205,3 +213,3 @@ * Style object for the container of the `headerLeft` element`. | ||
*/ | ||
labelVisible?: boolean; | ||
displayMode?: HeaderBackButtonDisplayMode; | ||
/** | ||
@@ -208,0 +216,0 @@ * Style object for the label. |
{ | ||
"name": "@react-navigation/elements", | ||
"description": "UI Components for React Navigation", | ||
"version": "2.0.0-rc.18", | ||
"version": "2.0.0-rc.19", | ||
"keywords": [ | ||
@@ -56,3 +56,3 @@ "react-native", | ||
"@react-native-masked-view/masked-view": "0.3.1", | ||
"@react-navigation/native": "^7.0.0-rc.16", | ||
"@react-navigation/native": "^7.0.0-rc.17", | ||
"@testing-library/react-native": "^12.4.3", | ||
@@ -68,3 +68,3 @@ "@types/react": "~18.2.79", | ||
"@react-native-masked-view/masked-view": ">= 0.2.0", | ||
"@react-navigation/native": "^7.0.0-rc.16", | ||
"@react-navigation/native": "^7.0.0-rc.17", | ||
"react": ">= 18.2.0", | ||
@@ -104,3 +104,3 @@ "react-native": ">= 0.72.0", | ||
}, | ||
"gitHead": "70c4339ca48961378837d9ee6cf63a396e55892d" | ||
"gitHead": "1a26dd67e4b9625075e6e5229736d1c679c67ccb" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
491115
5816