react-native-drawer-layout 4.0.0-alpha.0 → 4.0.0-alpha.2

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 (83) hide show
  1. package/lib/commonjs/constants.js +5 -9
  2. package/lib/commonjs/constants.js.map +1 -1
  3. package/lib/commonjs/index.js.map +1 -1
  4. package/lib/commonjs/types.js.map +1 -1
  5. package/lib/commonjs/utils/DrawerGestureContext.js +3 -4
  6. package/lib/commonjs/utils/DrawerGestureContext.js.map +1 -1
  7. package/lib/commonjs/utils/DrawerProgressContext.js +3 -4
  8. package/lib/commonjs/utils/DrawerProgressContext.js.map +1 -1
  9. package/lib/commonjs/utils/useDrawerProgress.js +2 -2
  10. package/lib/commonjs/utils/useDrawerProgress.js.map +1 -1
  11. package/lib/commonjs/views/Drawer.js +285 -36
  12. package/lib/commonjs/views/Drawer.js.map +1 -1
  13. package/lib/commonjs/views/GestureHandler.android.js.map +1 -1
  14. package/lib/commonjs/views/GestureHandler.ios.js.map +1 -1
  15. package/lib/commonjs/views/GestureHandler.js +8 -12
  16. package/lib/commonjs/views/GestureHandler.js.map +1 -1
  17. package/lib/commonjs/views/GestureHandlerNative.js +2 -2
  18. package/lib/commonjs/views/GestureHandlerNative.js.map +1 -1
  19. package/lib/commonjs/views/{modern/Overlay.js → Overlay.js} +3 -4
  20. package/lib/commonjs/views/Overlay.js.map +1 -0
  21. package/lib/module/constants.js +1 -1
  22. package/lib/module/constants.js.map +1 -1
  23. package/lib/module/index.js.map +1 -1
  24. package/lib/module/types.js.map +1 -1
  25. package/lib/module/utils/DrawerGestureContext.js.map +1 -1
  26. package/lib/module/utils/DrawerProgressContext.js.map +1 -1
  27. package/lib/module/utils/useDrawerProgress.js.map +1 -1
  28. package/lib/module/views/Drawer.js +285 -37
  29. package/lib/module/views/Drawer.js.map +1 -1
  30. package/lib/module/views/GestureHandler.android.js.map +1 -1
  31. package/lib/module/views/GestureHandler.ios.js.map +1 -1
  32. package/lib/module/views/GestureHandler.js +3 -3
  33. package/lib/module/views/GestureHandler.js.map +1 -1
  34. package/lib/module/views/GestureHandlerNative.js.map +1 -1
  35. package/lib/module/views/Overlay.js.map +1 -0
  36. package/lib/typescript/src/constants.d.ts +1 -1
  37. package/lib/typescript/src/constants.d.ts.map +1 -1
  38. package/lib/typescript/src/types.d.ts +4 -0
  39. package/lib/typescript/src/types.d.ts.map +1 -1
  40. package/lib/typescript/src/utils/DrawerProgressContext.d.ts +1 -1
  41. package/lib/typescript/src/utils/DrawerProgressContext.d.ts.map +1 -1
  42. package/lib/typescript/src/utils/useDrawerProgress.d.ts +1 -1
  43. package/lib/typescript/src/utils/useDrawerProgress.d.ts.map +1 -1
  44. package/lib/typescript/src/views/Drawer.d.ts +2 -17
  45. package/lib/typescript/src/views/Drawer.d.ts.map +1 -1
  46. package/lib/typescript/src/views/GestureHandlerNative.d.ts +3 -2
  47. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +1 -1
  48. package/lib/typescript/src/views/Overlay.d.ts +106 -0
  49. package/lib/typescript/src/views/Overlay.d.ts.map +1 -0
  50. package/package.json +10 -10
  51. package/src/constants.tsx +1 -1
  52. package/src/types.tsx +5 -0
  53. package/src/utils/DrawerProgressContext.tsx +1 -1
  54. package/src/utils/useDrawerProgress.tsx +1 -3
  55. package/src/views/Drawer.tsx +424 -62
  56. package/src/views/GestureHandlerNative.tsx +1 -1
  57. package/lib/commonjs/views/legacy/Drawer.js +0 -452
  58. package/lib/commonjs/views/legacy/Drawer.js.map +0 -1
  59. package/lib/commonjs/views/legacy/Overlay.js +0 -73
  60. package/lib/commonjs/views/legacy/Overlay.js.map +0 -1
  61. package/lib/commonjs/views/modern/Drawer.js +0 -304
  62. package/lib/commonjs/views/modern/Drawer.js.map +0 -1
  63. package/lib/commonjs/views/modern/Overlay.js.map +0 -1
  64. package/lib/module/views/legacy/Drawer.js +0 -442
  65. package/lib/module/views/legacy/Drawer.js.map +0 -1
  66. package/lib/module/views/legacy/Overlay.js +0 -63
  67. package/lib/module/views/legacy/Overlay.js.map +0 -1
  68. package/lib/module/views/modern/Drawer.js +0 -295
  69. package/lib/module/views/modern/Drawer.js.map +0 -1
  70. package/lib/module/views/modern/Overlay.js.map +0 -1
  71. package/lib/typescript/src/views/legacy/Drawer.d.ts +0 -51
  72. package/lib/typescript/src/views/legacy/Drawer.d.ts.map +0 -1
  73. package/lib/typescript/src/views/legacy/Overlay.d.ts +0 -104
  74. package/lib/typescript/src/views/legacy/Overlay.d.ts.map +0 -1
  75. package/lib/typescript/src/views/modern/Drawer.d.ts +0 -9
  76. package/lib/typescript/src/views/modern/Drawer.d.ts.map +0 -1
  77. package/lib/typescript/src/views/modern/Overlay.d.ts +0 -104
  78. package/lib/typescript/src/views/modern/Overlay.d.ts.map +0 -1
  79. package/src/views/legacy/Drawer.tsx +0 -690
  80. package/src/views/legacy/Overlay.tsx +0 -85
  81. package/src/views/modern/Drawer.tsx +0 -441
  82. /package/lib/module/views/{modern/Overlay.js → Overlay.js} +0 -0
  83. /package/src/views/{modern/Overlay.tsx → Overlay.tsx} +0 -0
@@ -1,32 +1,45 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  I18nManager,
4
+ InteractionManager,
5
+ Keyboard,
4
6
  Platform,
5
- StyleProp,
7
+ StatusBar,
6
8
  StyleSheet,
7
9
  useWindowDimensions,
8
- ViewStyle,
10
+ View,
9
11
  } from 'react-native';
10
- import * as Reanimated from 'react-native-reanimated';
12
+ import Animated, {
13
+ interpolate,
14
+ runOnJS,
15
+ useAnimatedGestureHandler,
16
+ useAnimatedStyle,
17
+ useDerivedValue,
18
+ useSharedValue,
19
+ withSpring,
20
+ } from 'react-native-reanimated';
21
+ import useLatestCallback from 'use-latest-callback';
11
22
 
12
- import { SWIPE_MIN_DISTANCE, SWIPE_MIN_VELOCITY } from '../constants';
23
+ import {
24
+ SWIPE_EDGE_WIDTH,
25
+ SWIPE_MIN_DISTANCE,
26
+ SWIPE_MIN_OFFSET,
27
+ SWIPE_MIN_VELOCITY,
28
+ } from '../constants';
13
29
  import type { DrawerProps } from '../types';
14
- import { GestureHandlerRootView } from './GestureHandler';
15
-
16
- type Props = DrawerProps & {
17
- /**
18
- * Whether to use the legacy implementation of the drawer.
19
- * The legacy implementation uses v1 of Reanimated.
20
- * The modern implementation uses v2 of Reanimated.
21
- *
22
- * By default, the appropriate implementation is used based on whether Reanimated v2 is configured.
23
- */
24
- useLegacyImplementation?: boolean;
30
+ import { DrawerProgressContext } from '../utils/DrawerProgressContext';
31
+ import {
32
+ GestureHandlerRootView,
33
+ GestureState,
34
+ PanGestureHandler,
35
+ type PanGestureHandlerGestureEvent,
36
+ } from './GestureHandler';
37
+ import { Overlay } from './Overlay';
25
38
 
26
- /**
27
- * Style object for the wrapper view.
28
- */
29
- style?: StyleProp<ViewStyle>;
39
+ const minmax = (value: number, start: number, end: number) => {
40
+ 'worklet';
41
+
42
+ return Math.min(Math.max(value, start), end);
30
43
  };
31
44
 
32
45
  const getDefaultDrawerWidth = ({
@@ -51,63 +64,397 @@ const getDefaultDrawerWidth = ({
51
64
  };
52
65
 
53
66
  export function Drawer({
54
- // Reanimated 2 is not configured
55
- // @ts-expect-error: the type definitions are incomplete
56
- useLegacyImplementation = !Reanimated.isConfigured?.(),
57
67
  layout: customLayout,
58
- drawerType = Platform.select({ ios: 'slide', default: 'front' }),
59
68
  drawerPosition = I18nManager.getConstants().isRTL ? 'right' : 'left',
60
69
  drawerStyle,
70
+ drawerType = Platform.select({ ios: 'slide', default: 'front' }),
71
+ gestureHandlerProps,
72
+ hideStatusBarOnOpen = false,
73
+ keyboardDismissMode = 'on-drag',
74
+ onClose,
75
+ onOpen,
76
+ onGestureStart,
77
+ onGestureCancel,
78
+ onGestureEnd,
79
+ onTransitionStart,
80
+ onTransitionEnd,
81
+ open,
82
+ overlayStyle,
83
+ overlayAccessibilityLabel,
84
+ statusBarAnimation = 'slide',
61
85
  swipeEnabled = Platform.OS !== 'web' &&
62
86
  Platform.OS !== 'windows' &&
63
87
  Platform.OS !== 'macos',
64
- swipeEdgeWidth = 32,
88
+ swipeEdgeWidth = SWIPE_EDGE_WIDTH,
65
89
  swipeMinDistance = SWIPE_MIN_DISTANCE,
66
90
  swipeMinVelocity = SWIPE_MIN_VELOCITY,
67
- keyboardDismissMode = 'on-drag',
68
- hideStatusBarOnOpen = false,
69
- statusBarAnimation = 'slide',
91
+ renderDrawerContent,
92
+ children,
70
93
  style,
71
- ...rest
72
- }: Props) {
73
- // Reanimated v3 dropped legacy v1 API
74
- const legacyImplemenationNotAvailable =
75
- require('react-native-reanimated').abs === undefined;
76
-
77
- if (useLegacyImplementation && legacyImplemenationNotAvailable) {
78
- throw new Error(
79
- 'The `useLegacyImplementation` prop is not available with Reanimated 3 as it no longer includes support for Reanimated 1 legacy API. Remove the `useLegacyImplementation` prop from `Drawer.Navigator` to be able to use it.'
80
- );
81
- }
82
-
83
- const Drawer: typeof import('./modern/Drawer').Drawer =
84
- useLegacyImplementation
85
- ? require('./legacy/Drawer').Drawer
86
- : require('./modern/Drawer').Drawer;
87
-
94
+ }: DrawerProps) {
95
+ // FIXME: temporary workaround for useSafeAreaFrame not updating on Web
88
96
  const windowDimensions = useWindowDimensions();
89
97
  const layout = customLayout ?? windowDimensions;
90
98
 
99
+ const getDrawerWidth = (): number => {
100
+ const { width = getDefaultDrawerWidth(layout) } =
101
+ StyleSheet.flatten(drawerStyle) || {};
102
+
103
+ if (typeof width === 'string' && width.endsWith('%')) {
104
+ // Try to calculate width if a percentage is given
105
+ const percentage = Number(width.replace(/%$/, ''));
106
+
107
+ if (Number.isFinite(percentage)) {
108
+ return layout.width * (percentage / 100);
109
+ }
110
+ }
111
+
112
+ return typeof width === 'number' ? width : 0;
113
+ };
114
+
115
+ const drawerWidth = getDrawerWidth();
116
+
117
+ const isOpen = drawerType === 'permanent' ? true : open;
118
+ const isRight = drawerPosition === 'right';
119
+
120
+ const getDrawerTranslationX = React.useCallback(
121
+ (open: boolean) => {
122
+ 'worklet';
123
+
124
+ if (drawerPosition === 'left') {
125
+ return open ? 0 : -drawerWidth;
126
+ }
127
+
128
+ return open ? 0 : drawerWidth;
129
+ },
130
+ [drawerPosition, drawerWidth]
131
+ );
132
+
133
+ const hideStatusBar = React.useCallback(
134
+ (hide: boolean) => {
135
+ if (hideStatusBarOnOpen) {
136
+ StatusBar.setHidden(hide, statusBarAnimation);
137
+ }
138
+ },
139
+ [hideStatusBarOnOpen, statusBarAnimation]
140
+ );
141
+
142
+ React.useEffect(() => {
143
+ hideStatusBar(isOpen);
144
+
145
+ return () => hideStatusBar(false);
146
+ }, [isOpen, hideStatusBarOnOpen, statusBarAnimation, hideStatusBar]);
147
+
148
+ const interactionHandleRef = React.useRef<number | null>(null);
149
+
150
+ const startInteraction = () => {
151
+ interactionHandleRef.current = InteractionManager.createInteractionHandle();
152
+ };
153
+
154
+ const endInteraction = () => {
155
+ if (interactionHandleRef.current != null) {
156
+ InteractionManager.clearInteractionHandle(interactionHandleRef.current);
157
+ interactionHandleRef.current = null;
158
+ }
159
+ };
160
+
161
+ const hideKeyboard = () => {
162
+ if (keyboardDismissMode === 'on-drag') {
163
+ Keyboard.dismiss();
164
+ }
165
+ };
166
+
167
+ const onGestureBegin = () => {
168
+ onGestureStart?.();
169
+ startInteraction();
170
+ hideKeyboard();
171
+ hideStatusBar(true);
172
+ };
173
+
174
+ const onGestureFinish = () => {
175
+ onGestureEnd?.();
176
+ endInteraction();
177
+ };
178
+
179
+ const onGestureAbort = () => {
180
+ onGestureCancel?.();
181
+ endInteraction();
182
+ };
183
+
184
+ // FIXME: Currently hitSlop is broken when on Android when drawer is on right
185
+ // https://github.com/software-mansion/react-native-gesture-handler/issues/569
186
+ const hitSlop = isRight
187
+ ? // Extend hitSlop to the side of the screen when drawer is closed
188
+ // This lets the user drag the drawer from the side of the screen
189
+ { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
190
+ : { left: 0, width: isOpen ? undefined : swipeEdgeWidth };
191
+
192
+ const touchStartX = useSharedValue(0);
193
+ const touchX = useSharedValue(0);
194
+ const translationX = useSharedValue(getDrawerTranslationX(open));
195
+ const gestureState = useSharedValue<GestureState>(GestureState.UNDETERMINED);
196
+
197
+ const handleAnimationStart = useLatestCallback((open: boolean) => {
198
+ onTransitionStart?.(!open);
199
+ });
200
+
201
+ const handleAnimationEnd = useLatestCallback(
202
+ (open: boolean, finished?: boolean) => {
203
+ if (!finished) return;
204
+ onTransitionEnd?.(!open);
205
+ }
206
+ );
207
+
208
+ const toggleDrawer = React.useCallback(
209
+ (open: boolean, velocity?: number) => {
210
+ 'worklet';
211
+
212
+ const translateX = getDrawerTranslationX(open);
213
+
214
+ if (velocity === undefined) {
215
+ runOnJS(handleAnimationStart)(open);
216
+ }
217
+
218
+ touchStartX.value = 0;
219
+ touchX.value = 0;
220
+ translationX.value = withSpring(
221
+ translateX,
222
+ {
223
+ velocity,
224
+ stiffness: 1000,
225
+ damping: 500,
226
+ mass: 3,
227
+ overshootClamping: true,
228
+ restDisplacementThreshold: 0.01,
229
+ restSpeedThreshold: 0.01,
230
+ },
231
+ (finished) => runOnJS(handleAnimationEnd)(open, finished)
232
+ );
233
+
234
+ if (open) {
235
+ runOnJS(onOpen)();
236
+ } else {
237
+ runOnJS(onClose)();
238
+ }
239
+ },
240
+ [
241
+ getDrawerTranslationX,
242
+ handleAnimationEnd,
243
+ handleAnimationStart,
244
+ onClose,
245
+ onOpen,
246
+ touchStartX,
247
+ touchX,
248
+ translationX,
249
+ ]
250
+ );
251
+
252
+ React.useEffect(() => toggleDrawer(open), [open, toggleDrawer]);
253
+
254
+ const onGestureEvent = useAnimatedGestureHandler<
255
+ PanGestureHandlerGestureEvent,
256
+ { startX: number; hasCalledOnStart: boolean }
257
+ >({
258
+ onStart: (event, ctx) => {
259
+ ctx.hasCalledOnStart = false;
260
+ ctx.startX = translationX.value;
261
+ gestureState.value = event.state;
262
+ touchStartX.value = event.x;
263
+ },
264
+ onCancel: () => {
265
+ runOnJS(onGestureAbort)();
266
+ },
267
+ onActive: (event, ctx) => {
268
+ touchX.value = event.x;
269
+ translationX.value = ctx.startX + event.translationX;
270
+ gestureState.value = event.state;
271
+
272
+ // onStart will _always_ be called, even when the activation
273
+ // criteria isn't met yet. This makes sure onGestureBegin is only
274
+ // called when the criteria is really met.
275
+ if (!ctx.hasCalledOnStart) {
276
+ ctx.hasCalledOnStart = true;
277
+ runOnJS(onGestureBegin)();
278
+ }
279
+ },
280
+ onEnd: (event) => {
281
+ gestureState.value = event.state;
282
+
283
+ const nextOpen =
284
+ (Math.abs(event.translationX) > SWIPE_MIN_OFFSET &&
285
+ Math.abs(event.translationX) > swipeMinVelocity) ||
286
+ Math.abs(event.translationX) > swipeMinDistance
287
+ ? drawerPosition === 'left'
288
+ ? // If swiped to right, open the drawer, otherwise close it
289
+ (event.velocityX === 0 ? event.translationX : event.velocityX) > 0
290
+ : // If swiped to left, open the drawer, otherwise close it
291
+ (event.velocityX === 0 ? event.translationX : event.velocityX) < 0
292
+ : open;
293
+
294
+ toggleDrawer(nextOpen, event.velocityX);
295
+ },
296
+ onFinish: () => {
297
+ runOnJS(onGestureFinish)();
298
+ },
299
+ });
300
+
301
+ const translateX = useDerivedValue(() => {
302
+ // Comment stolen from react-native-gesture-handler/DrawerLayout
303
+ //
304
+ // While closing the drawer when user starts gesture outside of its area (in greyed
305
+ // out part of the window), we want the drawer to follow only once finger reaches the
306
+ // edge of the drawer.
307
+ // E.g. on the diagram below drawer is illustrate by X signs and the greyed out area by
308
+ // dots. The touch gesture starts at '*' and moves left, touch path is indicated by
309
+ // an arrow pointing left
310
+ // 1) +---------------+ 2) +---------------+ 3) +---------------+ 4) +---------------+
311
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
312
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
313
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
314
+ // |XXXXXXXX|......| |XXXXXXXX|.<-*..| |XXXXXXXX|<--*..| |XXXXX|<-----*..|
315
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
316
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
317
+ // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
318
+ // +---------------+ +---------------+ +---------------+ +---------------+
319
+ //
320
+ // For the above to work properly we define animated value that will keep start position
321
+ // of the gesture. Then we use that value to calculate how much we need to subtract from
322
+ // the translationX. If the gesture started on the greyed out area we take the distance from the
323
+ // edge of the drawer to the start position. Otherwise we don't subtract at all and the
324
+ // drawer be pulled back as soon as you start the pan.
325
+ //
326
+ // This is used only when drawerType is "front"
327
+ const touchDistance =
328
+ drawerType === 'front' && gestureState.value === GestureState.ACTIVE
329
+ ? minmax(
330
+ drawerPosition === 'left'
331
+ ? touchStartX.value - drawerWidth
332
+ : layout.width - drawerWidth - touchStartX.value,
333
+ 0,
334
+ layout.width
335
+ )
336
+ : 0;
337
+
338
+ const translateX =
339
+ drawerPosition === 'left'
340
+ ? minmax(translationX.value + touchDistance, -drawerWidth, 0)
341
+ : minmax(translationX.value - touchDistance, 0, drawerWidth);
342
+
343
+ return translateX;
344
+ });
345
+
346
+ const drawerAnimatedStyle = useAnimatedStyle(() => {
347
+ return {
348
+ transform:
349
+ drawerType === 'permanent'
350
+ ? // Reanimated needs the property to be present, but it results in Browser bug
351
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
352
+ []
353
+ : [
354
+ {
355
+ translateX:
356
+ // The drawer stays in place when `drawerType` is `back`
357
+ drawerType === 'back' ? 0 : translateX.value,
358
+ },
359
+ ],
360
+ };
361
+ });
362
+
363
+ const contentAnimatedStyle = useAnimatedStyle(() => {
364
+ return {
365
+ transform:
366
+ drawerType === 'permanent'
367
+ ? // Reanimated needs the property to be present, but it results in Browser bug
368
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
369
+ []
370
+ : [
371
+ {
372
+ translateX:
373
+ // The screen content stays in place when `drawerType` is `front`
374
+ drawerType === 'front'
375
+ ? 0
376
+ : translateX.value +
377
+ drawerWidth * (drawerPosition === 'left' ? 1 : -1),
378
+ },
379
+ ],
380
+ };
381
+ });
382
+
383
+ const progress = useDerivedValue(() => {
384
+ return drawerType === 'permanent'
385
+ ? 1
386
+ : interpolate(
387
+ translateX.value,
388
+ [getDrawerTranslationX(false), getDrawerTranslationX(true)],
389
+ [0, 1]
390
+ );
391
+ });
392
+
91
393
  return (
92
394
  <GestureHandlerRootView style={[styles.container, style]}>
93
- <Drawer
94
- {...rest}
95
- layout={layout}
96
- drawerType={drawerType}
97
- drawerPosition={drawerPosition}
98
- drawerStyle={[
99
- { width: getDefaultDrawerWidth(layout) },
100
- styles.drawer,
101
- drawerStyle,
102
- ]}
103
- swipeEnabled={swipeEnabled}
104
- swipeEdgeWidth={swipeEdgeWidth}
105
- swipeMinDistance={swipeMinDistance}
106
- swipeMinVelocity={swipeMinVelocity}
107
- keyboardDismissMode={keyboardDismissMode}
108
- hideStatusBarOnOpen={hideStatusBarOnOpen}
109
- statusBarAnimation={statusBarAnimation}
110
- />
395
+ <DrawerProgressContext.Provider value={progress}>
396
+ <PanGestureHandler
397
+ activeOffsetX={[-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]}
398
+ failOffsetY={[-SWIPE_MIN_OFFSET, SWIPE_MIN_OFFSET]}
399
+ hitSlop={hitSlop}
400
+ enabled={drawerType !== 'permanent' && swipeEnabled}
401
+ onGestureEvent={onGestureEvent}
402
+ {...gestureHandlerProps}
403
+ >
404
+ {/* Immediate child of gesture handler needs to be an Animated.View */}
405
+ <Animated.View
406
+ style={[
407
+ styles.main,
408
+ {
409
+ flexDirection:
410
+ drawerType === 'permanent' && !isRight
411
+ ? 'row-reverse'
412
+ : 'row',
413
+ },
414
+ ]}
415
+ >
416
+ <Animated.View style={[styles.content, contentAnimatedStyle]}>
417
+ <View
418
+ accessibilityElementsHidden={
419
+ isOpen && drawerType !== 'permanent'
420
+ }
421
+ importantForAccessibility={
422
+ isOpen && drawerType !== 'permanent'
423
+ ? 'no-hide-descendants'
424
+ : 'auto'
425
+ }
426
+ style={styles.content}
427
+ >
428
+ {children}
429
+ </View>
430
+ {drawerType !== 'permanent' ? (
431
+ <Overlay
432
+ progress={progress}
433
+ onPress={() => toggleDrawer(false)}
434
+ style={overlayStyle}
435
+ accessibilityLabel={overlayAccessibilityLabel}
436
+ />
437
+ ) : null}
438
+ </Animated.View>
439
+ <Animated.View
440
+ removeClippedSubviews={Platform.OS !== 'ios'}
441
+ style={[
442
+ styles.drawer,
443
+ {
444
+ width: drawerWidth,
445
+ position:
446
+ drawerType === 'permanent' ? 'relative' : 'absolute',
447
+ zIndex: drawerType === 'back' ? -1 : 0,
448
+ },
449
+ drawerAnimatedStyle,
450
+ drawerStyle,
451
+ ]}
452
+ >
453
+ {renderDrawerContent()}
454
+ </Animated.View>
455
+ </Animated.View>
456
+ </PanGestureHandler>
457
+ </DrawerProgressContext.Provider>
111
458
  </GestureHandlerRootView>
112
459
  );
113
460
  }
@@ -117,6 +464,21 @@ const styles = StyleSheet.create({
117
464
  flex: 1,
118
465
  },
119
466
  drawer: {
467
+ top: 0,
468
+ bottom: 0,
469
+ maxWidth: '100%',
120
470
  backgroundColor: 'white',
121
471
  },
472
+ content: {
473
+ flex: 1,
474
+ },
475
+ main: {
476
+ flex: 1,
477
+ ...Platform.select({
478
+ // FIXME: We need to hide `overflowX` on Web so the translated content doesn't show offscreen.
479
+ // But adding `overflowX: 'hidden'` prevents content from collapsing the URL bar.
480
+ web: null,
481
+ default: { overflow: 'hidden' },
482
+ }),
483
+ },
122
484
  });
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import {
3
3
  PanGestureHandler as PanGestureHandlerNative,
4
- PanGestureHandlerProperties,
4
+ type PanGestureHandlerProperties,
5
5
  } from 'react-native-gesture-handler';
6
6
 
7
7
  import { DrawerGestureContext } from '../utils/DrawerGestureContext';