@react-navigation/drawer 7.0.0-alpha.0 → 7.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/lib/commonjs/index.js +20 -21
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/navigators/createDrawerNavigator.js +11 -9
  4. package/lib/commonjs/navigators/createDrawerNavigator.js.map +1 -1
  5. package/lib/commonjs/types.js.map +1 -1
  6. package/lib/commonjs/utils/DrawerPositionContext.js +4 -5
  7. package/lib/commonjs/utils/DrawerPositionContext.js.map +1 -1
  8. package/lib/commonjs/utils/DrawerStatusContext.js +4 -6
  9. package/lib/commonjs/utils/DrawerStatusContext.js.map +1 -1
  10. package/lib/commonjs/utils/addCancelListener.js +19 -0
  11. package/lib/commonjs/utils/addCancelListener.js.map +1 -0
  12. package/lib/commonjs/utils/addCancelListener.native.js +15 -0
  13. package/lib/commonjs/utils/addCancelListener.native.js.map +1 -0
  14. package/lib/commonjs/utils/getDrawerStatusFromState.js +2 -2
  15. package/lib/commonjs/utils/getDrawerStatusFromState.js.map +1 -1
  16. package/lib/commonjs/utils/useDrawerStatus.js +5 -6
  17. package/lib/commonjs/utils/useDrawerStatus.js.map +1 -1
  18. package/lib/commonjs/views/DrawerContent.js +7 -8
  19. package/lib/commonjs/views/DrawerContent.js.map +1 -1
  20. package/lib/commonjs/views/DrawerContentScrollView.js +12 -10
  21. package/lib/commonjs/views/DrawerContentScrollView.js.map +1 -1
  22. package/lib/commonjs/views/DrawerItem.js +14 -64
  23. package/lib/commonjs/views/DrawerItem.js.map +1 -1
  24. package/lib/commonjs/views/DrawerItemList.js +6 -7
  25. package/lib/commonjs/views/DrawerItemList.js.map +1 -1
  26. package/lib/commonjs/views/DrawerToggleButton.js +5 -7
  27. package/lib/commonjs/views/DrawerToggleButton.js.map +1 -1
  28. package/lib/commonjs/views/DrawerView.js +69 -38
  29. package/lib/commonjs/views/DrawerView.js.map +1 -1
  30. package/lib/commonjs/views/ScreenFallback.js +4 -6
  31. package/lib/commonjs/views/ScreenFallback.js.map +1 -1
  32. package/lib/module/index.js +10 -10
  33. package/lib/module/index.js.map +1 -1
  34. package/lib/module/navigators/createDrawerNavigator.js +7 -3
  35. package/lib/module/navigators/createDrawerNavigator.js.map +1 -1
  36. package/lib/module/types.js.map +1 -1
  37. package/lib/module/utils/DrawerPositionContext.js +1 -1
  38. package/lib/module/utils/DrawerPositionContext.js.map +1 -1
  39. package/lib/module/utils/DrawerStatusContext.js +1 -2
  40. package/lib/module/utils/DrawerStatusContext.js.map +1 -1
  41. package/lib/module/utils/addCancelListener.js +12 -0
  42. package/lib/module/utils/addCancelListener.js.map +1 -0
  43. package/lib/module/utils/addCancelListener.native.js +8 -0
  44. package/lib/module/utils/addCancelListener.native.js.map +1 -0
  45. package/lib/module/utils/getDrawerStatusFromState.js +2 -2
  46. package/lib/module/utils/getDrawerStatusFromState.js.map +1 -1
  47. package/lib/module/utils/useDrawerStatus.js +2 -2
  48. package/lib/module/utils/useDrawerStatus.js.map +1 -1
  49. package/lib/module/views/DrawerContent.js +3 -3
  50. package/lib/module/views/DrawerContent.js.map +1 -1
  51. package/lib/module/views/DrawerContentScrollView.js +9 -5
  52. package/lib/module/views/DrawerContentScrollView.js.map +1 -1
  53. package/lib/module/views/DrawerItem.js +14 -64
  54. package/lib/module/views/DrawerItem.js.map +1 -1
  55. package/lib/module/views/DrawerItemList.js +4 -4
  56. package/lib/module/views/DrawerItemList.js.map +1 -1
  57. package/lib/module/views/DrawerToggleButton.js +3 -5
  58. package/lib/module/views/DrawerToggleButton.js.map +1 -1
  59. package/lib/module/views/DrawerView.js +65 -34
  60. package/lib/module/views/DrawerView.js.map +1 -1
  61. package/lib/module/views/ScreenFallback.js +2 -4
  62. package/lib/module/views/ScreenFallback.js.map +1 -1
  63. package/lib/typescript/src/index.d.ts +10 -10
  64. package/lib/typescript/src/index.d.ts.map +1 -1
  65. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts +6 -6
  66. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts.map +1 -1
  67. package/lib/typescript/src/types.d.ts +34 -10
  68. package/lib/typescript/src/types.d.ts.map +1 -1
  69. package/lib/typescript/src/utils/DrawerPositionContext.d.ts +1 -2
  70. package/lib/typescript/src/utils/DrawerPositionContext.d.ts.map +1 -1
  71. package/lib/typescript/src/utils/DrawerStatusContext.d.ts +1 -2
  72. package/lib/typescript/src/utils/DrawerStatusContext.d.ts.map +1 -1
  73. package/lib/typescript/src/utils/addCancelListener.d.ts +2 -0
  74. package/lib/typescript/src/utils/addCancelListener.d.ts.map +1 -0
  75. package/lib/typescript/src/utils/addCancelListener.native.d.ts +2 -0
  76. package/lib/typescript/src/utils/addCancelListener.native.d.ts.map +1 -0
  77. package/lib/typescript/src/utils/getDrawerStatusFromState.d.ts +1 -1
  78. package/lib/typescript/src/utils/getDrawerStatusFromState.d.ts.map +1 -1
  79. package/lib/typescript/src/utils/useDrawerStatus.d.ts +1 -1
  80. package/lib/typescript/src/utils/useDrawerStatus.d.ts.map +1 -1
  81. package/lib/typescript/src/views/DrawerContent.d.ts +2 -2
  82. package/lib/typescript/src/views/DrawerContent.d.ts.map +1 -1
  83. package/lib/typescript/src/views/DrawerContentScrollView.d.ts +2 -3
  84. package/lib/typescript/src/views/DrawerContentScrollView.d.ts.map +1 -1
  85. package/lib/typescript/src/views/DrawerItem.d.ts +3 -3
  86. package/lib/typescript/src/views/DrawerItem.d.ts.map +1 -1
  87. package/lib/typescript/src/views/DrawerItemList.d.ts +2 -2
  88. package/lib/typescript/src/views/DrawerItemList.d.ts.map +1 -1
  89. package/lib/typescript/src/views/DrawerToggleButton.d.ts +2 -2
  90. package/lib/typescript/src/views/DrawerToggleButton.d.ts.map +1 -1
  91. package/lib/typescript/src/views/DrawerView.d.ts +3 -3
  92. package/lib/typescript/src/views/DrawerView.d.ts.map +1 -1
  93. package/lib/typescript/src/views/ScreenFallback.d.ts +3 -3
  94. package/lib/typescript/src/views/ScreenFallback.d.ts.map +1 -1
  95. package/package.json +24 -24
  96. package/src/index.tsx +10 -10
  97. package/src/navigators/createDrawerNavigator.tsx +11 -7
  98. package/src/types.tsx +22 -12
  99. package/src/utils/DrawerPositionContext.tsx +3 -1
  100. package/src/utils/DrawerStatusContext.tsx +3 -5
  101. package/src/utils/addCancelListener.native.tsx +12 -0
  102. package/src/utils/addCancelListener.tsx +13 -0
  103. package/src/utils/getDrawerStatusFromState.tsx +1 -1
  104. package/src/utils/useDrawerStatus.tsx +2 -2
  105. package/src/views/DrawerContent.tsx +3 -3
  106. package/src/views/DrawerContentScrollView.tsx +12 -12
  107. package/src/views/DrawerItem.tsx +12 -85
  108. package/src/views/DrawerItemList.tsx +8 -12
  109. package/src/views/DrawerToggleButton.tsx +3 -5
  110. package/src/views/DrawerView.tsx +75 -40
  111. package/src/views/ScreenFallback.tsx +6 -1
package/src/types.tsx CHANGED
@@ -35,16 +35,6 @@ export type DrawerNavigationConfig = {
35
35
  * Defaults to `true`.
36
36
  */
37
37
  detachInactiveScreens?: boolean;
38
- /**
39
- * Whether to use the legacy implementation based on Reanimated 1.
40
- * The new implementation based on Reanimated 2 will perform better,
41
- * but it's not possible to use Chrome remote debugger.
42
- *
43
- * This defaults to `true` if Reanimated 2 is not configured.
44
- *
45
- * Otherwise, it defaults to `false`
46
- */
47
- useLegacyImplementation?: boolean;
48
38
  };
49
39
 
50
40
  export type DrawerNavigationOptions = HeaderOptions & {
@@ -258,6 +248,26 @@ export type DrawerNavigationEventMap = {
258
248
  * Event which fires on tapping on the item in the drawer menu.
259
249
  */
260
250
  drawerItemPress: { data: undefined; canPreventDefault: true };
251
+ /**
252
+ * Event which fires when a transition animation starts.
253
+ */
254
+ transitionStart: { data: { closing: boolean } };
255
+ /**
256
+ * Event which fires when a transition animation ends.
257
+ */
258
+ transitionEnd: { data: { closing: boolean } };
259
+ /**
260
+ * Event which fires when navigation gesture starts.
261
+ */
262
+ gestureStart: { data: undefined };
263
+ /**
264
+ * Event which fires when navigation gesture is completed.
265
+ */
266
+ gestureEnd: { data: undefined };
267
+ /**
268
+ * Event which fires when navigation gesture is canceled.
269
+ */
270
+ gestureCancel: { data: undefined };
261
271
  };
262
272
 
263
273
  export type DrawerNavigationHelpers = NavigationHelpers<
@@ -269,7 +279,7 @@ export type DrawerNavigationHelpers = NavigationHelpers<
269
279
  export type DrawerNavigationProp<
270
280
  ParamList extends ParamListBase,
271
281
  RouteName extends keyof ParamList = keyof ParamList,
272
- NavigatorID extends string | undefined = undefined
282
+ NavigatorID extends string | undefined = undefined,
273
283
  > = NavigationProp<
274
284
  ParamList,
275
285
  RouteName,
@@ -283,7 +293,7 @@ export type DrawerNavigationProp<
283
293
  export type DrawerScreenProps<
284
294
  ParamList extends ParamListBase,
285
295
  RouteName extends keyof ParamList = keyof ParamList,
286
- NavigatorID extends string | undefined = undefined
296
+ NavigatorID extends string | undefined = undefined,
287
297
  > = {
288
298
  navigation: DrawerNavigationProp<ParamList, RouteName, NavigatorID>;
289
299
  route: RouteProp<ParamList, RouteName>;
@@ -1,3 +1,5 @@
1
1
  import * as React from 'react';
2
2
 
3
- export default React.createContext<'left' | 'right' | undefined>(undefined);
3
+ export const DrawerPositionContext = React.createContext<
4
+ 'left' | 'right' | undefined
5
+ >(undefined);
@@ -1,8 +1,6 @@
1
1
  import type { DrawerStatus } from '@react-navigation/native';
2
2
  import * as React from 'react';
3
3
 
4
- const DrawerStatusContext = React.createContext<DrawerStatus | undefined>(
5
- undefined
6
- );
7
-
8
- export default DrawerStatusContext;
4
+ export const DrawerStatusContext = React.createContext<
5
+ DrawerStatus | undefined
6
+ >(undefined);
@@ -0,0 +1,12 @@
1
+ import { BackHandler } from 'react-native';
2
+
3
+ export const addCancelListener = (callback: () => boolean) => {
4
+ const subscription = BackHandler.addEventListener(
5
+ 'hardwareBackPress',
6
+ callback
7
+ );
8
+
9
+ return () => {
10
+ subscription.remove();
11
+ };
12
+ };
@@ -0,0 +1,13 @@
1
+ export const addCancelListener = (callback: () => boolean) => {
2
+ const handleEscape = (e: KeyboardEvent) => {
3
+ if (e.key === 'Escape') {
4
+ callback();
5
+ }
6
+ };
7
+
8
+ document?.body?.addEventListener?.('keyup', handleEscape);
9
+
10
+ return () => {
11
+ document?.body?.removeEventListener?.('keyup', handleEscape);
12
+ };
13
+ };
@@ -4,7 +4,7 @@ import type {
4
4
  ParamListBase,
5
5
  } from '@react-navigation/native';
6
6
 
7
- export default function getDrawerStatusFromState(
7
+ export function getDrawerStatusFromState(
8
8
  state: DrawerNavigationState<ParamListBase>
9
9
  ): DrawerStatus {
10
10
  if (state.history == null) {
@@ -1,13 +1,13 @@
1
1
  import type { DrawerStatus } from '@react-navigation/native';
2
2
  import * as React from 'react';
3
3
 
4
- import DrawerStatusContext from './DrawerStatusContext';
4
+ import { DrawerStatusContext } from './DrawerStatusContext';
5
5
 
6
6
  /**
7
7
  * Hook to detect if the drawer's status in a parent navigator.
8
8
  * Returns 'open' if the drawer is open, 'closed' if the drawer is closed.
9
9
  */
10
- export default function useDrawerStatus(): DrawerStatus {
10
+ export function useDrawerStatus(): DrawerStatus {
11
11
  const drawerStatus = React.useContext(DrawerStatusContext);
12
12
 
13
13
  if (drawerStatus === undefined) {
@@ -1,10 +1,10 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import type { DrawerContentComponentProps } from '../types';
4
- import DrawerContentScrollView from './DrawerContentScrollView';
5
- import DrawerItemList from './DrawerItemList';
4
+ import { DrawerContentScrollView } from './DrawerContentScrollView';
5
+ import { DrawerItemList } from './DrawerItemList';
6
6
 
7
- export default function DrawerContent({
7
+ export function DrawerContent({
8
8
  descriptors,
9
9
  state,
10
10
  ...rest
@@ -1,28 +1,26 @@
1
+ import { useLocale } from '@react-navigation/native';
1
2
  import * as React from 'react';
2
- import {
3
- I18nManager,
4
- ScrollView,
5
- ScrollViewProps,
6
- StyleSheet,
7
- } from 'react-native';
3
+ import { ScrollView, type ScrollViewProps, StyleSheet } from 'react-native';
8
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
9
5
 
10
- import DrawerPositionContext from '../utils/DrawerPositionContext';
6
+ import { DrawerPositionContext } from '../utils/DrawerPositionContext';
11
7
 
12
8
  type Props = ScrollViewProps & {
13
9
  children: React.ReactNode;
14
10
  };
15
11
 
16
- function DrawerContentScrollView(
12
+ function DrawerContentScrollViewInner(
17
13
  { contentContainerStyle, style, children, ...rest }: Props,
18
14
  ref?: React.Ref<ScrollView>
19
15
  ) {
20
16
  const drawerPosition = React.useContext(DrawerPositionContext);
21
17
  const insets = useSafeAreaInsets();
18
+ const { direction } = useLocale();
22
19
 
23
- const isRight = I18nManager.getConstants().isRTL
24
- ? drawerPosition === 'left'
25
- : drawerPosition === 'right';
20
+ const isRight =
21
+ direction === 'rtl'
22
+ ? drawerPosition === 'left'
23
+ : drawerPosition === 'right';
26
24
 
27
25
  return (
28
26
  <ScrollView
@@ -43,7 +41,9 @@ function DrawerContentScrollView(
43
41
  );
44
42
  }
45
43
 
46
- export default React.forwardRef(DrawerContentScrollView);
44
+ export const DrawerContentScrollView = React.forwardRef(
45
+ DrawerContentScrollViewInner
46
+ );
47
47
 
48
48
  const styles = StyleSheet.create({
49
49
  container: {
@@ -1,15 +1,13 @@
1
- import { PlatformPressable } from '@react-navigation/elements';
2
- import { CommonActions, Link, Route, useTheme } from '@react-navigation/native';
1
+ import { PlatformPressable, Text } from '@react-navigation/elements';
2
+ import { type Route, useTheme } from '@react-navigation/native';
3
3
  import Color from 'color';
4
4
  import * as React from 'react';
5
5
  import {
6
- Platform,
7
- StyleProp,
6
+ type StyleProp,
8
7
  StyleSheet,
9
- Text,
10
- TextStyle,
8
+ type TextStyle,
11
9
  View,
12
- ViewStyle,
10
+ type ViewStyle,
13
11
  } from 'react-native';
14
12
 
15
13
  type Props = {
@@ -96,73 +94,13 @@ type Props = {
96
94
  testID?: string;
97
95
  };
98
96
 
99
- const LinkPressable = ({
100
- route,
101
- href,
102
- children,
103
- style,
104
- onPress,
105
- onLongPress,
106
- onPressIn,
107
- onPressOut,
108
- accessibilityRole,
109
- ...rest
110
- }: Omit<React.ComponentProps<typeof PlatformPressable>, 'style'> & {
111
- style: StyleProp<ViewStyle>;
112
- } & {
113
- route: Route<string>;
114
- href?: string;
115
- children: React.ReactNode;
116
- onPress?: () => void;
117
- }) => {
118
- if (Platform.OS === 'web') {
119
- // React Native Web doesn't forward `onClick` if we use `TouchableWithoutFeedback`.
120
- // We need to use `onClick` to be able to prevent default browser handling of links.
121
- return (
122
- <Link
123
- {...rest}
124
- href={href}
125
- action={CommonActions.navigate(route.name, route.params)}
126
- style={[styles.button, style]}
127
- onPress={(e: any) => {
128
- if (
129
- !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) && // ignore clicks with modifier keys
130
- (e.button == null || e.button === 0) // ignore everything but left clicks
131
- ) {
132
- e.preventDefault();
133
- onPress?.(e);
134
- }
135
- }}
136
- // types for PressableProps and TextProps are incompatible with each other by `null` so we
137
- // can't use {...rest} for these 3 props
138
- onLongPress={onLongPress ?? undefined}
139
- onPressIn={onPressIn ?? undefined}
140
- onPressOut={onPressOut ?? undefined}
141
- >
142
- {children}
143
- </Link>
144
- );
145
- } else {
146
- return (
147
- <PlatformPressable
148
- {...rest}
149
- accessibilityRole={accessibilityRole}
150
- onPress={onPress}
151
- >
152
- <View style={style}>{children}</View>
153
- </PlatformPressable>
154
- );
155
- }
156
- };
157
-
158
97
  /**
159
98
  * A component used to show an action item with an icon and a label in a navigation drawer.
160
99
  */
161
- export default function DrawerItem(props: Props) {
162
- const { colors } = useTheme();
100
+ export function DrawerItem(props: Props) {
101
+ const { colors, fonts } = useTheme();
163
102
 
164
103
  const {
165
- route,
166
104
  href,
167
105
  icon,
168
106
  label,
@@ -196,19 +134,17 @@ export default function DrawerItem(props: Props) {
196
134
  {...rest}
197
135
  style={[styles.container, { borderRadius, backgroundColor }, style]}
198
136
  >
199
- <LinkPressable
137
+ <PlatformPressable
200
138
  testID={testID}
201
139
  onPress={onPress}
202
- style={[styles.wrapper, { borderRadius }]}
203
140
  accessibilityLabel={accessibilityLabel}
204
141
  accessibilityRole="button"
205
142
  accessibilityState={{ selected: focused }}
206
143
  pressColor={pressColor}
207
144
  pressOpacity={pressOpacity}
208
- route={route}
209
145
  href={href}
210
146
  >
211
- <React.Fragment>
147
+ <View style={[styles.wrapper, { borderRadius }]}>
212
148
  {iconNode}
213
149
  <View
214
150
  style={[
@@ -220,13 +156,7 @@ export default function DrawerItem(props: Props) {
220
156
  <Text
221
157
  numberOfLines={1}
222
158
  allowFontScaling={allowFontScaling}
223
- style={[
224
- {
225
- color,
226
- fontWeight: '500',
227
- },
228
- labelStyle,
229
- ]}
159
+ style={[{ color }, fonts.medium, labelStyle]}
230
160
  >
231
161
  {label}
232
162
  </Text>
@@ -234,8 +164,8 @@ export default function DrawerItem(props: Props) {
234
164
  label({ color, focused })
235
165
  )}
236
166
  </View>
237
- </React.Fragment>
238
- </LinkPressable>
167
+ </View>
168
+ </PlatformPressable>
239
169
  </View>
240
170
  );
241
171
  }
@@ -255,7 +185,4 @@ const styles = StyleSheet.create({
255
185
  marginRight: 32,
256
186
  flex: 1,
257
187
  },
258
- button: {
259
- display: 'flex',
260
- },
261
188
  });
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  CommonActions,
3
3
  DrawerActions,
4
- DrawerNavigationState,
5
- ParamListBase,
6
- useLinkTools,
4
+ type DrawerNavigationState,
5
+ type ParamListBase,
6
+ useLinkBuilder,
7
7
  } from '@react-navigation/native';
8
8
  import * as React from 'react';
9
9
 
10
10
  import type { DrawerDescriptorMap, DrawerNavigationHelpers } from '../types';
11
- import DrawerItem from './DrawerItem';
11
+ import { DrawerItem } from './DrawerItem';
12
12
 
13
13
  type Props = {
14
14
  state: DrawerNavigationState<ParamListBase>;
@@ -19,12 +19,8 @@ type Props = {
19
19
  /**
20
20
  * Component that renders the navigation list in the drawer.
21
21
  */
22
- export default function DrawerItemList({
23
- state,
24
- navigation,
25
- descriptors,
26
- }: Props) {
27
- const { buildHref } = useLinkTools();
22
+ export function DrawerItemList({ state, navigation, descriptors }: Props) {
23
+ const { buildHref } = useLinkBuilder();
28
24
 
29
25
  const focusedRoute = state.routes[state.index];
30
26
  const focusedDescriptor = descriptors[focusedRoute.key];
@@ -75,8 +71,8 @@ export default function DrawerItemList({
75
71
  drawerLabel !== undefined
76
72
  ? drawerLabel
77
73
  : title !== undefined
78
- ? title
79
- : route.name
74
+ ? title
75
+ : route.name
80
76
  }
81
77
  icon={drawerIcon}
82
78
  focused={focused}
@@ -1,7 +1,7 @@
1
1
  import { PlatformPressable } from '@react-navigation/elements';
2
2
  import {
3
3
  DrawerActions,
4
- ParamListBase,
4
+ type ParamListBase,
5
5
  useNavigation,
6
6
  } from '@react-navigation/native';
7
7
  import * as React from 'react';
@@ -16,14 +16,12 @@ type Props = {
16
16
  tintColor?: string;
17
17
  };
18
18
 
19
- export default function DrawerToggleButton({ tintColor, ...rest }: Props) {
19
+ export function DrawerToggleButton({ tintColor, ...rest }: Props) {
20
20
  const navigation = useNavigation<DrawerNavigationProp<ParamListBase>>();
21
21
 
22
22
  return (
23
23
  <PlatformPressable
24
24
  {...rest}
25
- accessible
26
- accessibilityRole="button"
27
25
  android_ripple={{ borderless: true }}
28
26
  onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
29
27
  style={styles.touchable}
@@ -34,6 +32,7 @@ export default function DrawerToggleButton({ tintColor, ...rest }: Props) {
34
32
  >
35
33
  <Image
36
34
  style={[styles.icon, tintColor ? { tintColor } : null]}
35
+ resizeMode="contain"
37
36
  source={require('./assets/toggle-drawer-icon.png')}
38
37
  fadeDuration={0}
39
38
  />
@@ -46,7 +45,6 @@ const styles = StyleSheet.create({
46
45
  height: 24,
47
46
  width: 24,
48
47
  margin: 3,
49
- resizeMode: 'contain',
50
48
  },
51
49
  touchable: {
52
50
  marginHorizontal: 11,
@@ -1,4 +1,5 @@
1
1
  import {
2
+ getDefaultSidebarWidth,
2
3
  getHeaderTitle,
3
4
  Header,
4
5
  SafeAreaProviderCompat,
@@ -6,15 +7,17 @@ import {
6
7
  } from '@react-navigation/elements';
7
8
  import {
8
9
  DrawerActions,
9
- DrawerNavigationState,
10
- DrawerStatus,
11
- ParamListBase,
10
+ type DrawerNavigationState,
11
+ type DrawerStatus,
12
+ type ParamListBase,
13
+ useLocale,
12
14
  useTheme,
13
15
  } from '@react-navigation/native';
14
16
  import * as React from 'react';
15
- import { BackHandler, I18nManager, Platform, StyleSheet } from 'react-native';
17
+ import { Platform, StyleSheet } from 'react-native';
16
18
  import { Drawer } from 'react-native-drawer-layout';
17
19
  import { useSafeAreaFrame } from 'react-native-safe-area-context';
20
+ import useLatestCallback from 'use-latest-callback';
18
21
 
19
22
  import type {
20
23
  DrawerContentComponentProps,
@@ -24,11 +27,12 @@ import type {
24
27
  DrawerNavigationHelpers,
25
28
  DrawerNavigationProp,
26
29
  } from '../types';
27
- import DrawerPositionContext from '../utils/DrawerPositionContext';
28
- import DrawerStatusContext from '../utils/DrawerStatusContext';
29
- import getDrawerStatusFromState from '../utils/getDrawerStatusFromState';
30
- import DrawerContent from './DrawerContent';
31
- import DrawerToggleButton from './DrawerToggleButton';
30
+ import { addCancelListener } from '../utils/addCancelListener';
31
+ import { DrawerPositionContext } from '../utils/DrawerPositionContext';
32
+ import { DrawerStatusContext } from '../utils/DrawerStatusContext';
33
+ import { getDrawerStatusFromState } from '../utils/getDrawerStatusFromState';
34
+ import { DrawerContent } from './DrawerContent';
35
+ import { DrawerToggleButton } from './DrawerToggleButton';
32
36
  import { MaybeScreen, MaybeScreenContainer } from './ScreenFallback';
33
37
 
34
38
  type Props = DrawerNavigationConfig & {
@@ -50,10 +54,12 @@ function DrawerViewBase({
50
54
  Platform.OS === 'android' ||
51
55
  Platform.OS === 'ios',
52
56
  }: Props) {
57
+ const { direction } = useLocale();
58
+
53
59
  const focusedRouteKey = state.routes[state.index].key;
54
60
  const {
55
61
  drawerHideStatusBarOnOpen,
56
- drawerPosition = I18nManager.getConstants().isRTL ? 'right' : 'left',
62
+ drawerPosition = direction === 'rtl' ? 'right' : 'left',
57
63
  drawerStatusBarAnimation,
58
64
  drawerStyle,
59
65
  drawerType,
@@ -80,19 +86,56 @@ function DrawerViewBase({
80
86
 
81
87
  const drawerStatus = getDrawerStatusFromState(state);
82
88
 
83
- const handleDrawerOpen = React.useCallback(() => {
89
+ const handleDrawerOpen = useLatestCallback(() => {
84
90
  navigation.dispatch({
85
91
  ...DrawerActions.openDrawer(),
86
92
  target: state.key,
87
93
  });
88
- }, [navigation, state.key]);
94
+ });
89
95
 
90
- const handleDrawerClose = React.useCallback(() => {
96
+ const handleDrawerClose = useLatestCallback(() => {
91
97
  navigation.dispatch({
92
98
  ...DrawerActions.closeDrawer(),
93
99
  target: state.key,
94
100
  });
95
- }, [navigation, state.key]);
101
+ });
102
+
103
+ const handleGestureStart = useLatestCallback(() => {
104
+ navigation.emit({
105
+ type: 'gestureStart',
106
+ target: state.key,
107
+ });
108
+ });
109
+
110
+ const handleGestureEnd = useLatestCallback(() => {
111
+ navigation.emit({
112
+ type: 'gestureEnd',
113
+ target: state.key,
114
+ });
115
+ });
116
+
117
+ const handleGestureCancel = useLatestCallback(() => {
118
+ navigation.emit({
119
+ type: 'gestureCancel',
120
+ target: state.key,
121
+ });
122
+ });
123
+
124
+ const handleTransitionStart = useLatestCallback((closing: boolean) => {
125
+ navigation.emit({
126
+ type: 'transitionStart',
127
+ data: { closing },
128
+ target: state.key,
129
+ });
130
+ });
131
+
132
+ const handleTransitionEnd = useLatestCallback((closing: boolean) => {
133
+ navigation.emit({
134
+ type: 'transitionEnd',
135
+ data: { closing },
136
+ target: state.key,
137
+ });
138
+ });
96
139
 
97
140
  React.useEffect(() => {
98
141
  if (drawerStatus === defaultStatus || drawerType === 'permanent') {
@@ -115,31 +158,10 @@ function DrawerViewBase({
115
158
  return true;
116
159
  };
117
160
 
118
- const handleEscape = (e: KeyboardEvent) => {
119
- if (e.key === 'Escape') {
120
- handleHardwareBack();
121
- }
122
- };
123
-
124
161
  // We only add the listeners when drawer opens
125
162
  // This way we can make sure that the listener is added as late as possible
126
163
  // This will make sure that our handler will run first when back button is pressed
127
- const subscription = BackHandler.addEventListener(
128
- 'hardwareBackPress',
129
- handleHardwareBack
130
- );
131
-
132
- if (Platform.OS === 'web') {
133
- document?.body?.addEventListener?.('keyup', handleEscape);
134
- }
135
-
136
- return () => {
137
- subscription.remove();
138
-
139
- if (Platform.OS === 'web') {
140
- document?.body?.removeEventListener?.('keyup', handleEscape);
141
- }
142
- };
164
+ return addCancelListener(handleHardwareBack);
143
165
  }, [
144
166
  defaultStatus,
145
167
  drawerStatus,
@@ -177,8 +199,13 @@ function DrawerViewBase({
177
199
  return null;
178
200
  }
179
201
 
180
- if (lazy && !loaded.includes(route.key) && !isFocused) {
181
- // Don't render a lazy screen if we've never navigated to it
202
+ if (
203
+ lazy &&
204
+ !loaded.includes(route.key) &&
205
+ !isFocused &&
206
+ !state.preloadedRouteKeys.includes(route.key)
207
+ ) {
208
+ // Don't render a lazy screen if we've never navigated to it or it wasn't preloaded
182
209
  return null;
183
210
  }
184
211
 
@@ -240,6 +267,11 @@ function DrawerViewBase({
240
267
  open={drawerStatus !== 'closed'}
241
268
  onOpen={handleDrawerOpen}
242
269
  onClose={handleDrawerClose}
270
+ onGestureStart={handleGestureStart}
271
+ onGestureEnd={handleGestureEnd}
272
+ onGestureCancel={handleGestureCancel}
273
+ onTransitionStart={handleTransitionStart}
274
+ onTransitionEnd={handleTransitionEnd}
243
275
  layout={dimensions}
244
276
  gestureHandlerProps={gestureHandlerProps}
245
277
  swipeEnabled={swipeEnabled}
@@ -252,7 +284,10 @@ function DrawerViewBase({
252
284
  overlayAccessibilityLabel={overlayAccessibilityLabel}
253
285
  drawerPosition={drawerPosition}
254
286
  drawerStyle={[
255
- { backgroundColor: colors.card },
287
+ {
288
+ backgroundColor: colors.card,
289
+ width: getDefaultSidebarWidth(dimensions),
290
+ },
256
291
  drawerType === 'permanent' &&
257
292
  (drawerPosition === 'left'
258
293
  ? {
@@ -274,7 +309,7 @@ function DrawerViewBase({
274
309
  );
275
310
  }
276
311
 
277
- export default function DrawerView({ navigation, ...rest }: Props) {
312
+ export function DrawerView({ navigation, ...rest }: Props) {
278
313
  return (
279
314
  <SafeAreaProviderCompat>
280
315
  <DrawerViewBase navigation={navigation} {...rest} />
@@ -1,6 +1,11 @@
1
1
  import { ResourceSavingView } from '@react-navigation/elements';
2
2
  import * as React from 'react';
3
- import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
3
+ import {
4
+ type StyleProp,
5
+ View,
6
+ type ViewProps,
7
+ type ViewStyle,
8
+ } from 'react-native';
4
9
 
5
10
  type Props = {
6
11
  visible: boolean;