@react-navigation/drawer
Version:
Integration for the drawer component from react-native-drawer-layout
290 lines (288 loc) • 11.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DrawerView = DrawerView;
var _elements = require("@react-navigation/elements");
var _native = require("@react-navigation/native");
var React = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _reactNativeDrawerLayout = require("react-native-drawer-layout");
var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
var _useLatestCallback = _interopRequireDefault(require("use-latest-callback"));
var _addCancelListener = require("../utils/addCancelListener");
var _DrawerPositionContext = require("../utils/DrawerPositionContext.js");
var _DrawerStatusContext = require("../utils/DrawerStatusContext.js");
var _getDrawerStatusFromState = require("../utils/getDrawerStatusFromState.js");
var _DrawerContent = require("./DrawerContent.js");
var _DrawerToggleButton = require("./DrawerToggleButton.js");
var _ScreenFallback = require("./ScreenFallback.js");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const DRAWER_BORDER_RADIUS = 16;
const renderDrawerContentDefault = props => /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerContent.DrawerContent, {
...props
});
function DrawerViewBase({
state,
navigation,
descriptors,
defaultStatus,
drawerContent = renderDrawerContentDefault,
detachInactiveScreens = _reactNative.Platform.OS === 'web' || _reactNative.Platform.OS === 'android' || _reactNative.Platform.OS === 'ios'
}) {
const {
direction
} = (0, _native.useLocale)();
const focusedRouteKey = state.routes[state.index].key;
const {
drawerHideStatusBarOnOpen,
drawerPosition = direction === 'rtl' ? 'right' : 'left',
drawerStatusBarAnimation,
drawerStyle,
drawerType = _reactNative.Platform.select({
ios: 'slide',
default: 'front'
}),
configureGestureHandler,
keyboardDismissMode,
overlayColor = 'rgba(0, 0, 0, 0.5)',
swipeEdgeWidth,
swipeEnabled = _reactNative.Platform.OS !== 'web' && _reactNative.Platform.OS !== 'windows' && _reactNative.Platform.OS !== 'macos',
swipeMinDistance,
overlayAccessibilityLabel
} = descriptors[focusedRouteKey].options;
const [loaded, setLoaded] = React.useState([focusedRouteKey]);
if (!loaded.includes(focusedRouteKey)) {
setLoaded([...loaded, focusedRouteKey]);
}
const previousRouteKeyRef = React.useRef(focusedRouteKey);
React.useEffect(() => {
const previousRouteKey = previousRouteKeyRef.current;
if (previousRouteKey !== focusedRouteKey && descriptors[previousRouteKey]?.options.popToTopOnBlur) {
const prevRoute = state.routes.find(route => route.key === previousRouteKey);
if (prevRoute?.state?.type === 'stack' && prevRoute.state.key) {
navigation.dispatch({
..._native.StackActions.popToTop(),
target: prevRoute.state.key
});
}
}
previousRouteKeyRef.current = focusedRouteKey;
}, [descriptors, focusedRouteKey, navigation, state.routes]);
const dimensions = (0, _reactNativeSafeAreaContext.useSafeAreaFrame)();
const {
colors
} = (0, _native.useTheme)();
const drawerStatus = (0, _getDrawerStatusFromState.getDrawerStatusFromState)(state);
const handleDrawerOpen = (0, _useLatestCallback.default)(() => {
navigation.dispatch({
..._native.DrawerActions.openDrawer(),
target: state.key
});
});
const handleDrawerClose = (0, _useLatestCallback.default)(() => {
navigation.dispatch({
..._native.DrawerActions.closeDrawer(),
target: state.key
});
});
const handleGestureStart = (0, _useLatestCallback.default)(() => {
navigation.emit({
type: 'gestureStart',
target: state.key
});
});
const handleGestureEnd = (0, _useLatestCallback.default)(() => {
navigation.emit({
type: 'gestureEnd',
target: state.key
});
});
const handleGestureCancel = (0, _useLatestCallback.default)(() => {
navigation.emit({
type: 'gestureCancel',
target: state.key
});
});
const handleTransitionStart = (0, _useLatestCallback.default)(closing => {
navigation.emit({
type: 'transitionStart',
data: {
closing
},
target: state.key
});
});
const handleTransitionEnd = (0, _useLatestCallback.default)(closing => {
navigation.emit({
type: 'transitionEnd',
data: {
closing
},
target: state.key
});
});
React.useEffect(() => {
if (drawerStatus === defaultStatus || drawerType === 'permanent') {
return;
}
const handleHardwareBack = () => {
// We shouldn't handle the back button if the parent screen isn't focused
// This will avoid the drawer overriding event listeners from a focused screen
if (!navigation.isFocused()) {
return false;
}
if (defaultStatus === 'open') {
handleDrawerOpen();
} else {
handleDrawerClose();
}
return true;
};
// We only add the listeners when drawer opens
// This way we can make sure that the listener is added as late as possible
// This will make sure that our handler will run first when back button is pressed
return (0, _addCancelListener.addCancelListener)(handleHardwareBack);
}, [defaultStatus, drawerStatus, drawerType, handleDrawerClose, handleDrawerOpen, navigation]);
const renderDrawerContent = () => {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerPositionContext.DrawerPositionContext.Provider, {
value: drawerPosition,
children: drawerContent({
state: state,
navigation: navigation,
descriptors: descriptors
})
});
};
const renderSceneContent = () => {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScreenFallback.MaybeScreenContainer, {
enabled: detachInactiveScreens,
hasTwoStates: true,
style: styles.content,
children: state.routes.map((route, index) => {
const descriptor = descriptors[route.key];
const {
lazy = true
} = descriptor.options;
const isFocused = state.index === index;
const isPreloaded = state.preloadedRouteKeys.includes(route.key);
if (lazy && !loaded.includes(route.key) && !isFocused && !isPreloaded) {
// Don't render a lazy screen if we've never navigated to it or it wasn't preloaded
return null;
}
const {
freezeOnBlur,
header = ({
layout,
options
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_elements.Header, {
...options,
layout: layout,
title: (0, _elements.getHeaderTitle)(options, route.name),
headerLeft: drawerPosition === 'left' && options.headerLeft == null ? props => /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerToggleButton.DrawerToggleButton, {
...props
}) : options.headerLeft,
headerRight: drawerPosition === 'right' && options.headerRight == null ? props => /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerToggleButton.DrawerToggleButton, {
...props
}) : options.headerRight
}),
headerShown,
headerStatusBarHeight,
headerTransparent,
sceneStyle
} = descriptor.options;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScreenFallback.MaybeScreen, {
style: [_reactNative.StyleSheet.absoluteFill, {
zIndex: isFocused ? 0 : -1
}],
visible: isFocused,
enabled: detachInactiveScreens,
freezeOnBlur: freezeOnBlur,
shouldFreeze: !isFocused && !isPreloaded,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_elements.Screen, {
focused: isFocused,
route: descriptor.route,
navigation: descriptor.navigation,
headerShown: headerShown,
headerStatusBarHeight: headerStatusBarHeight,
headerTransparent: headerTransparent,
header: header({
layout: dimensions,
route: descriptor.route,
navigation: descriptor.navigation,
options: descriptor.options
}),
style: sceneStyle,
children: descriptor.render()
})
}, route.key);
})
});
};
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_DrawerStatusContext.DrawerStatusContext.Provider, {
value: drawerStatus,
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeDrawerLayout.Drawer, {
open: drawerStatus !== 'closed',
onOpen: handleDrawerOpen,
onClose: handleDrawerClose,
onGestureStart: handleGestureStart,
onGestureEnd: handleGestureEnd,
onGestureCancel: handleGestureCancel,
onTransitionStart: handleTransitionStart,
onTransitionEnd: handleTransitionEnd,
layout: dimensions,
direction: direction,
configureGestureHandler: configureGestureHandler,
swipeEnabled: swipeEnabled,
swipeEdgeWidth: swipeEdgeWidth,
swipeMinDistance: swipeMinDistance,
hideStatusBarOnOpen: drawerHideStatusBarOnOpen,
statusBarAnimation: drawerStatusBarAnimation,
keyboardDismissMode: keyboardDismissMode,
drawerType: drawerType,
overlayAccessibilityLabel: overlayAccessibilityLabel,
drawerPosition: drawerPosition,
drawerStyle: [{
backgroundColor: colors.card,
width: (0, _elements.getDefaultSidebarWidth)(dimensions)
}, drawerType === 'permanent' && ((_reactNative.Platform.OS === 'web' ? drawerPosition === 'right' : direction === 'rtl' && drawerPosition !== 'right' || direction !== 'rtl' && drawerPosition === 'right') ? {
borderLeftColor: colors.border,
borderLeftWidth: _reactNative.StyleSheet.hairlineWidth
} : {
borderRightColor: colors.border,
borderRightWidth: _reactNative.StyleSheet.hairlineWidth
}), drawerType === 'front' && (drawerPosition === 'left' ? {
borderTopRightRadius: DRAWER_BORDER_RADIUS,
borderBottomRightRadius: DRAWER_BORDER_RADIUS
} : {
borderTopLeftRadius: DRAWER_BORDER_RADIUS,
borderBottomLeftRadius: DRAWER_BORDER_RADIUS
}), drawerStyle],
overlayStyle: {
backgroundColor: overlayColor
},
renderDrawerContent: renderDrawerContent,
children: renderSceneContent()
})
});
}
function DrawerView({
navigation,
...rest
}) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_elements.SafeAreaProviderCompat, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(DrawerViewBase, {
navigation: navigation,
...rest
})
});
}
const styles = _reactNative.StyleSheet.create({
content: {
flex: 1
}
});
//# sourceMappingURL=DrawerView.js.map