@react-navigation/drawer 8.0.0-alpha.3 → 8.0.0-alpha.31

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 (55) hide show
  1. package/lib/module/index.js.map +1 -1
  2. package/lib/module/navigators/createDrawerNavigator.js +3 -7
  3. package/lib/module/navigators/createDrawerNavigator.js.map +1 -1
  4. package/lib/module/utils/useDrawerStatus.js +1 -1
  5. package/lib/module/utils/useDrawerStatus.js.map +1 -1
  6. package/lib/module/views/DrawerContentScrollView.js +30 -13
  7. package/lib/module/views/DrawerContentScrollView.js.map +1 -1
  8. package/lib/module/views/DrawerItem.js +50 -8
  9. package/lib/module/views/DrawerItem.js.map +1 -1
  10. package/lib/module/views/DrawerItemList.js +3 -1
  11. package/lib/module/views/DrawerItemList.js.map +1 -1
  12. package/lib/module/views/DrawerToggleButton.js +37 -7
  13. package/lib/module/views/DrawerToggleButton.js.map +1 -1
  14. package/lib/module/views/DrawerView.js +14 -15
  15. package/lib/module/views/DrawerView.js.map +1 -1
  16. package/lib/typescript/src/index.d.ts +1 -1
  17. package/lib/typescript/src/index.d.ts.map +1 -1
  18. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts +8 -14
  19. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts.map +1 -1
  20. package/lib/typescript/src/types.d.ts +20 -17
  21. package/lib/typescript/src/types.d.ts.map +1 -1
  22. package/lib/typescript/src/views/DrawerContentScrollView.d.ts +5 -2
  23. package/lib/typescript/src/views/DrawerContentScrollView.d.ts.map +1 -1
  24. package/lib/typescript/src/views/DrawerItem.d.ts +18 -17
  25. package/lib/typescript/src/views/DrawerItem.d.ts.map +1 -1
  26. package/lib/typescript/src/views/DrawerItemList.d.ts.map +1 -1
  27. package/lib/typescript/src/views/DrawerToggleButton.d.ts +12 -7
  28. package/lib/typescript/src/views/DrawerToggleButton.d.ts.map +1 -1
  29. package/lib/typescript/src/views/DrawerView.d.ts.map +1 -1
  30. package/package.json +24 -24
  31. package/src/index.tsx +1 -0
  32. package/src/navigators/createDrawerNavigator.tsx +9 -40
  33. package/src/types.tsx +26 -20
  34. package/src/utils/useDrawerStatus.tsx +1 -1
  35. package/src/views/DrawerContentScrollView.tsx +31 -15
  36. package/src/views/DrawerItem.tsx +84 -23
  37. package/src/views/DrawerItemList.tsx +2 -0
  38. package/src/views/DrawerToggleButton.tsx +66 -22
  39. package/src/views/DrawerView.tsx +18 -18
  40. package/lib/module/views/assets/toggle-drawer-icon@1x.android.png +0 -0
  41. package/lib/module/views/assets/toggle-drawer-icon@1x.ios.png +0 -0
  42. package/lib/module/views/assets/toggle-drawer-icon@2x.android.png +0 -0
  43. package/lib/module/views/assets/toggle-drawer-icon@2x.ios.png +0 -0
  44. package/lib/module/views/assets/toggle-drawer-icon@3x.android.png +0 -0
  45. package/lib/module/views/assets/toggle-drawer-icon@3x.ios.png +0 -0
  46. package/lib/module/views/assets/toggle-drawer-icon@4x.android.png +0 -0
  47. package/lib/module/views/assets/toggle-drawer-icon@4x.ios.png +0 -0
  48. package/src/views/assets/toggle-drawer-icon@1x.android.png +0 -0
  49. package/src/views/assets/toggle-drawer-icon@1x.ios.png +0 -0
  50. package/src/views/assets/toggle-drawer-icon@2x.android.png +0 -0
  51. package/src/views/assets/toggle-drawer-icon@2x.ios.png +0 -0
  52. package/src/views/assets/toggle-drawer-icon@3x.android.png +0 -0
  53. package/src/views/assets/toggle-drawer-icon@3x.ios.png +0 -0
  54. package/src/views/assets/toggle-drawer-icon@4x.android.png +0 -0
  55. package/src/views/assets/toggle-drawer-icon@4x.ios.png +0 -0
@@ -1,9 +1,15 @@
1
- import { PlatformPressable, Text } from '@react-navigation/elements';
1
+ import { type Icon, PlatformPressable, Text } from '@react-navigation/elements';
2
2
  import { Color } from '@react-navigation/elements/internal';
3
- import { type Route, useTheme } from '@react-navigation/native';
4
- import * as React from 'react';
3
+ import {
4
+ MaterialSymbol,
5
+ type Route,
6
+ SFSymbol,
7
+ useTheme,
8
+ } from '@react-navigation/native';
9
+ import React from 'react';
5
10
  import {
6
11
  type ColorValue,
12
+ Image,
7
13
  Platform,
8
14
  type StyleProp,
9
15
  StyleSheet,
@@ -16,11 +22,11 @@ type Props = {
16
22
  /**
17
23
  * The route object which should be specified by the drawer item.
18
24
  */
19
- route?: Route<string>;
25
+ route?: Route<string> | undefined;
20
26
  /**
21
27
  * The `href` to use for the anchor tag on web
22
28
  */
23
- href?: string;
29
+ href?: string | undefined;
24
30
  /**
25
31
  * The label text of the item.
26
32
  */
@@ -30,15 +36,18 @@ type Props = {
30
36
  /**
31
37
  * Icon to display for the `DrawerItem`.
32
38
  */
33
- icon?: (props: {
34
- focused: boolean;
35
- size: number;
36
- color: ColorValue;
37
- }) => React.ReactNode;
39
+ icon?:
40
+ | Icon
41
+ | ((props: {
42
+ focused: boolean;
43
+ size: number;
44
+ color: ColorValue;
45
+ }) => Icon | React.ReactNode)
46
+ | undefined;
38
47
  /**
39
48
  * Whether to highlight the drawer item as active.
40
49
  */
41
- focused?: boolean;
50
+ focused?: boolean | undefined;
42
51
  /**
43
52
  * Function to execute on press.
44
53
  */
@@ -46,54 +55,54 @@ type Props = {
46
55
  /**
47
56
  * Color for the icon and label when the item is active.
48
57
  */
49
- activeTintColor?: ColorValue;
58
+ activeTintColor?: ColorValue | undefined;
50
59
  /**
51
60
  * Color for the icon and label when the item is inactive.
52
61
  */
53
- inactiveTintColor?: ColorValue;
62
+ inactiveTintColor?: ColorValue | undefined;
54
63
  /**
55
64
  * Background color for item when its active.
56
65
  */
57
- activeBackgroundColor?: ColorValue;
66
+ activeBackgroundColor?: ColorValue | undefined;
58
67
  /**
59
68
  * Background color for item when its inactive.
60
69
  */
61
- inactiveBackgroundColor?: ColorValue;
70
+ inactiveBackgroundColor?: ColorValue | undefined;
62
71
  /**
63
72
  * Color of the touchable effect on press.
64
73
  * Only supported on Android.
65
74
  *
66
75
  * @platform android
67
76
  */
68
- pressColor?: ColorValue;
77
+ pressColor?: ColorValue | undefined;
69
78
  /**
70
79
  * Opacity of the touchable effect on press.
71
80
  * Only supported on iOS.
72
81
  *
73
82
  * @platform ios
74
83
  */
75
- pressOpacity?: number;
84
+ pressOpacity?: number | undefined;
76
85
  /**
77
86
  * Style object for the label element.
78
87
  */
79
- labelStyle?: StyleProp<TextStyle>;
88
+ labelStyle?: StyleProp<TextStyle> | undefined;
80
89
  /**
81
90
  * Style object for the wrapper element.
82
91
  */
83
- style?: StyleProp<ViewStyle>;
92
+ style?: StyleProp<ViewStyle> | undefined;
84
93
  /**
85
94
  * Whether label font should scale to respect Text Size accessibility settings.
86
95
  */
87
- allowFontScaling?: boolean;
96
+ allowFontScaling?: boolean | undefined;
88
97
 
89
98
  /**
90
99
  * Accessibility label for drawer item.
91
100
  */
92
- accessibilityLabel?: string;
101
+ accessibilityLabel?: string | undefined;
93
102
  /**
94
103
  * ID to locate this drawer item in tests.
95
104
  */
96
- testID?: string;
105
+ testID?: string | undefined;
97
106
  };
98
107
 
99
108
  /**
@@ -134,7 +143,59 @@ export function DrawerItem(props: Props) {
134
143
  'rgba(0, 0, 0, 0.06)')
135
144
  : inactiveBackgroundColor;
136
145
 
137
- const iconNode = icon ? icon({ size: 24, focused, color }) : null;
146
+ const iconNode = React.useMemo(() => {
147
+ if (!icon) {
148
+ return null;
149
+ }
150
+
151
+ const size = 24;
152
+
153
+ const iconValue =
154
+ typeof icon === 'function' ? icon({ size, focused, color }) : icon;
155
+
156
+ if (React.isValidElement(iconValue)) {
157
+ return iconValue;
158
+ }
159
+
160
+ if (
161
+ typeof iconValue === 'object' &&
162
+ iconValue != null &&
163
+ 'type' in iconValue
164
+ ) {
165
+ switch (iconValue.type) {
166
+ case 'image':
167
+ return (
168
+ <Image
169
+ source={iconValue.source}
170
+ style={{
171
+ width: size,
172
+ height: size,
173
+ tintColor: iconValue.tinted === false ? undefined : color,
174
+ }}
175
+ />
176
+ );
177
+ case 'sfSymbol':
178
+ return <SFSymbol name={iconValue.name} size={size} color={color} />;
179
+ case 'materialSymbol':
180
+ return (
181
+ <MaterialSymbol
182
+ name={iconValue.name}
183
+ variant={iconValue.variant}
184
+ weight={iconValue.weight}
185
+ size={size}
186
+ color={color}
187
+ />
188
+ );
189
+ default: {
190
+ const _exhaustiveCheck: never = iconValue;
191
+
192
+ return _exhaustiveCheck;
193
+ }
194
+ }
195
+ }
196
+
197
+ return null;
198
+ }, [icon, focused, color]);
138
199
 
139
200
  return (
140
201
  <View
@@ -59,6 +59,7 @@ export function DrawerItemList({ state, navigation, descriptors }: Props) {
59
59
  drawerIcon,
60
60
  drawerLabelStyle,
61
61
  drawerItemStyle,
62
+ drawerItemTestID,
62
63
  drawerAllowFontScaling,
63
64
  } = descriptors[route.key].options;
64
65
 
@@ -84,6 +85,7 @@ export function DrawerItemList({ state, navigation, descriptors }: Props) {
84
85
  labelStyle={drawerLabelStyle}
85
86
  style={drawerItemStyle}
86
87
  onPress={onPress}
88
+ testID={drawerItemTestID}
87
89
  />
88
90
  );
89
91
  }) as React.ReactNode as React.ReactElement;
@@ -1,51 +1,95 @@
1
- import { HeaderButton } from '@react-navigation/elements';
2
- import { DrawerActions, useNavigation } from '@react-navigation/native';
1
+ import { HeaderButton, type Icon } from '@react-navigation/elements';
3
2
  import {
4
- type ColorValue,
5
- Image,
6
- type ImageSourcePropType,
7
- StyleSheet,
8
- } from 'react-native';
3
+ DrawerActions,
4
+ MaterialSymbol,
5
+ SFSymbol,
6
+ useNavigation,
7
+ } from '@react-navigation/native';
8
+ import * as React from 'react';
9
+ import { type ColorValue, Image, Platform, StyleSheet } from 'react-native';
9
10
 
10
11
  import toggleDrawerIcon from './assets/toggle-drawer-icon.png';
11
12
 
12
13
  type Props = {
13
- accessibilityLabel?: string;
14
- pressColor?: ColorValue;
15
- pressOpacity?: number;
16
- tintColor?: ColorValue;
17
- imageSource?: ImageSourcePropType;
14
+ icon?:
15
+ | Icon
16
+ | ((props: { tintColor: ColorValue | undefined }) => React.ReactNode)
17
+ | undefined;
18
+ accessibilityLabel?: string | undefined;
19
+ pressColor?: ColorValue | undefined;
20
+ pressOpacity?: number | undefined;
21
+ tintColor?: ColorValue | undefined;
22
+ testID?: string | undefined;
18
23
  };
19
24
 
20
25
  export function DrawerToggleButton({
26
+ icon,
21
27
  tintColor,
22
28
  accessibilityLabel = 'Show navigation menu',
23
- imageSource = toggleDrawerIcon,
24
29
  ...rest
25
30
  }: Props) {
26
31
  const navigation = useNavigation();
27
32
 
33
+ const drawerIcon =
34
+ icon ??
35
+ Platform.select<Icon>({
36
+ ios: {
37
+ type: 'sfSymbol',
38
+ name: 'line.3.horizontal',
39
+ },
40
+ android: {
41
+ type: 'materialSymbol',
42
+ name: 'menu',
43
+ },
44
+ default: {
45
+ type: 'image',
46
+ source: toggleDrawerIcon,
47
+ },
48
+ });
49
+
28
50
  return (
29
51
  <HeaderButton
30
52
  {...rest}
31
53
  accessibilityLabel={accessibilityLabel}
32
54
  onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
33
55
  >
34
- <Image
35
- resizeMode="contain"
36
- source={imageSource}
37
- fadeDuration={0}
38
- tintColor={tintColor}
39
- style={styles.icon}
40
- />
56
+ {typeof drawerIcon === 'function' ? (
57
+ drawerIcon({ tintColor })
58
+ ) : drawerIcon.type === 'sfSymbol' ? (
59
+ <SFSymbol
60
+ name={drawerIcon.name}
61
+ size={ICON_SIZE}
62
+ color={tintColor}
63
+ style={styles.icon}
64
+ />
65
+ ) : drawerIcon.type === 'materialSymbol' ? (
66
+ <MaterialSymbol
67
+ name={drawerIcon.name}
68
+ variant={drawerIcon.variant}
69
+ weight={drawerIcon.weight}
70
+ size={ICON_SIZE}
71
+ color={tintColor}
72
+ style={styles.icon}
73
+ />
74
+ ) : (
75
+ <Image
76
+ resizeMode="contain"
77
+ source={drawerIcon.source}
78
+ fadeDuration={0}
79
+ tintColor={tintColor}
80
+ style={styles.icon}
81
+ />
82
+ )}
41
83
  </HeaderButton>
42
84
  );
43
85
  }
44
86
 
87
+ const ICON_SIZE = 24;
88
+
45
89
  const styles = StyleSheet.create({
46
90
  icon: {
47
- height: 24,
48
- width: 24,
91
+ height: ICON_SIZE,
92
+ width: ICON_SIZE,
49
93
  marginVertical: 8,
50
94
  marginHorizontal: 5,
51
95
  },
@@ -1,5 +1,7 @@
1
1
  import { getHeaderTitle, Header } from '@react-navigation/elements';
2
2
  import {
3
+ ActivityView,
4
+ Container,
3
5
  SafeAreaProviderCompat,
4
6
  Screen as ScreenContent,
5
7
  } from '@react-navigation/elements/internal';
@@ -15,7 +17,6 @@ import {
15
17
  import * as React from 'react';
16
18
  import { Platform, StyleSheet } from 'react-native';
17
19
  import { Drawer } from 'react-native-drawer-layout';
18
- import { Screen, ScreenContainer } from 'react-native-screens';
19
20
  import useLatestCallback from 'use-latest-callback';
20
21
 
21
22
  import type {
@@ -52,9 +53,6 @@ function DrawerViewBase({
52
53
  descriptors,
53
54
  defaultStatus,
54
55
  drawerContent = renderDrawerContentDefault,
55
- detachInactiveScreens = Platform.OS === 'web' ||
56
- Platform.OS === 'android' ||
57
- Platform.OS === 'ios',
58
56
  }: Props) {
59
57
  const { direction } = useLocale();
60
58
 
@@ -209,11 +207,7 @@ function DrawerViewBase({
209
207
 
210
208
  const renderSceneContent = () => {
211
209
  return (
212
- <ScreenContainer
213
- enabled={detachInactiveScreens}
214
- hasTwoStates
215
- style={styles.content}
216
- >
210
+ <Container style={styles.content}>
217
211
  {state.routes.map((route, index) => {
218
212
  const descriptor = descriptors[route.key];
219
213
  const { lazy = true } = descriptor.options;
@@ -231,7 +225,7 @@ function DrawerViewBase({
231
225
  }
232
226
 
233
227
  const {
234
- freezeOnBlur,
228
+ inactiveBehavior = 'pause',
235
229
  header = ({ options }: DrawerHeaderProps) => (
236
230
  <Header
237
231
  {...options}
@@ -254,14 +248,20 @@ function DrawerViewBase({
254
248
  sceneStyle,
255
249
  } = descriptor.options;
256
250
 
251
+ // For preloaded screens and if lazy is false,
252
+ // Keep them active so that the effects can run
253
+ const isActive =
254
+ inactiveBehavior === 'none' ||
255
+ isFocused ||
256
+ isPreloaded ||
257
+ (lazy === false && !loaded.includes(route.key));
258
+
257
259
  return (
258
- <Screen
260
+ <ActivityView
259
261
  key={route.key}
260
- style={[StyleSheet.absoluteFill, { zIndex: isFocused ? 0 : -1 }]}
261
- activityState={isFocused ? 2 : 0}
262
- enabled={detachInactiveScreens}
263
- freezeOnBlur={freezeOnBlur}
264
- shouldFreeze={!isFocused && !isPreloaded}
262
+ mode={isFocused ? 'normal' : isActive ? 'inert' : 'paused'}
263
+ visible={isFocused}
264
+ style={{ ...StyleSheet.absoluteFill, zIndex: isFocused ? 0 : -1 }}
265
265
  >
266
266
  <ScreenContent
267
267
  focused={isFocused}
@@ -280,10 +280,10 @@ function DrawerViewBase({
280
280
  >
281
281
  {descriptor.render()}
282
282
  </ScreenContent>
283
- </Screen>
283
+ </ActivityView>
284
284
  );
285
285
  })}
286
- </ScreenContainer>
286
+ </Container>
287
287
  );
288
288
  };
289
289