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

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 (120) hide show
  1. package/lib/commonjs/index.js +4 -6
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/navigators/createDrawerNavigator.js +3 -43
  4. package/lib/commonjs/navigators/createDrawerNavigator.js.map +1 -1
  5. package/lib/commonjs/views/DrawerItem.js +13 -5
  6. package/lib/commonjs/views/DrawerItem.js.map +1 -1
  7. package/lib/commonjs/views/DrawerItemList.js +6 -6
  8. package/lib/commonjs/views/DrawerItemList.js.map +1 -1
  9. package/lib/commonjs/views/DrawerView.js +23 -58
  10. package/lib/commonjs/views/DrawerView.js.map +1 -1
  11. package/lib/module/index.js +1 -3
  12. package/lib/module/index.js.map +1 -1
  13. package/lib/module/navigators/createDrawerNavigator.js +3 -43
  14. package/lib/module/navigators/createDrawerNavigator.js.map +1 -1
  15. package/lib/module/views/DrawerItem.js +14 -6
  16. package/lib/module/views/DrawerItem.js.map +1 -1
  17. package/lib/module/views/DrawerItemList.js +7 -7
  18. package/lib/module/views/DrawerItemList.js.map +1 -1
  19. package/lib/module/views/DrawerView.js +23 -58
  20. package/lib/module/views/DrawerView.js.map +1 -1
  21. package/lib/typescript/src/index.d.ts +1 -3
  22. package/lib/typescript/src/index.d.ts.map +1 -1
  23. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts +8 -3
  24. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts.map +1 -1
  25. package/lib/typescript/src/types.d.ts +20 -14
  26. package/lib/typescript/src/types.d.ts.map +1 -1
  27. package/lib/typescript/src/views/DrawerItem.d.ts +18 -5
  28. package/lib/typescript/src/views/DrawerItem.d.ts.map +1 -1
  29. package/lib/typescript/src/views/DrawerItemList.d.ts +1 -1
  30. package/lib/typescript/src/views/DrawerItemList.d.ts.map +1 -1
  31. package/lib/typescript/src/views/DrawerToggleButton.d.ts +1 -1
  32. package/lib/typescript/src/views/DrawerToggleButton.d.ts.map +1 -1
  33. package/lib/typescript/src/views/DrawerView.d.ts +1 -1
  34. package/lib/typescript/src/views/DrawerView.d.ts.map +1 -1
  35. package/lib/typescript/src/views/ScreenFallback.d.ts +1 -1
  36. package/lib/typescript/src/views/ScreenFallback.d.ts.map +1 -1
  37. package/package.json +14 -14
  38. package/src/index.tsx +5 -3
  39. package/src/navigators/createDrawerNavigator.tsx +2 -72
  40. package/src/types.tsx +8 -1
  41. package/src/views/DrawerItem.tsx +33 -11
  42. package/src/views/DrawerItemList.tsx +5 -4
  43. package/src/views/DrawerView.tsx +17 -68
  44. package/lib/commonjs/utils/DrawerGestureContext.js +0 -12
  45. package/lib/commonjs/utils/DrawerGestureContext.js.map +0 -1
  46. package/lib/commonjs/utils/DrawerProgressContext.js +0 -12
  47. package/lib/commonjs/utils/DrawerProgressContext.js.map +0 -1
  48. package/lib/commonjs/utils/useDrawerProgress.js +0 -19
  49. package/lib/commonjs/utils/useDrawerProgress.js.map +0 -1
  50. package/lib/commonjs/views/GestureHandler.android.js +0 -17
  51. package/lib/commonjs/views/GestureHandler.android.js.map +0 -1
  52. package/lib/commonjs/views/GestureHandler.ios.js +0 -17
  53. package/lib/commonjs/views/GestureHandler.ios.js.map +0 -1
  54. package/lib/commonjs/views/GestureHandler.js +0 -32
  55. package/lib/commonjs/views/GestureHandler.js.map +0 -1
  56. package/lib/commonjs/views/GestureHandlerNative.js +0 -37
  57. package/lib/commonjs/views/GestureHandlerNative.js.map +0 -1
  58. package/lib/commonjs/views/legacy/Drawer.js +0 -419
  59. package/lib/commonjs/views/legacy/Drawer.js.map +0 -1
  60. package/lib/commonjs/views/legacy/Overlay.js +0 -71
  61. package/lib/commonjs/views/legacy/Overlay.js.map +0 -1
  62. package/lib/commonjs/views/modern/Drawer.js +0 -303
  63. package/lib/commonjs/views/modern/Drawer.js.map +0 -1
  64. package/lib/commonjs/views/modern/Overlay.js +0 -66
  65. package/lib/commonjs/views/modern/Overlay.js.map +0 -1
  66. package/lib/module/utils/DrawerGestureContext.js +0 -3
  67. package/lib/module/utils/DrawerGestureContext.js.map +0 -1
  68. package/lib/module/utils/DrawerProgressContext.js +0 -3
  69. package/lib/module/utils/DrawerProgressContext.js.map +0 -1
  70. package/lib/module/utils/useDrawerProgress.js +0 -10
  71. package/lib/module/utils/useDrawerProgress.js.map +0 -1
  72. package/lib/module/views/GestureHandler.android.js +0 -2
  73. package/lib/module/views/GestureHandler.android.js.map +0 -1
  74. package/lib/module/views/GestureHandler.ios.js +0 -2
  75. package/lib/module/views/GestureHandler.ios.js.map +0 -1
  76. package/lib/module/views/GestureHandler.js +0 -20
  77. package/lib/module/views/GestureHandler.js.map +0 -1
  78. package/lib/module/views/GestureHandlerNative.js +0 -11
  79. package/lib/module/views/GestureHandlerNative.js.map +0 -1
  80. package/lib/module/views/legacy/Drawer.js +0 -409
  81. package/lib/module/views/legacy/Drawer.js.map +0 -1
  82. package/lib/module/views/legacy/Overlay.js +0 -61
  83. package/lib/module/views/legacy/Overlay.js.map +0 -1
  84. package/lib/module/views/modern/Drawer.js +0 -294
  85. package/lib/module/views/modern/Drawer.js.map +0 -1
  86. package/lib/module/views/modern/Overlay.js +0 -57
  87. package/lib/module/views/modern/Overlay.js.map +0 -1
  88. package/lib/typescript/src/utils/DrawerGestureContext.d.ts +0 -4
  89. package/lib/typescript/src/utils/DrawerGestureContext.d.ts.map +0 -1
  90. package/lib/typescript/src/utils/DrawerProgressContext.d.ts +0 -5
  91. package/lib/typescript/src/utils/DrawerProgressContext.d.ts.map +0 -1
  92. package/lib/typescript/src/utils/useDrawerProgress.d.ts +0 -3
  93. package/lib/typescript/src/utils/useDrawerProgress.d.ts.map +0 -1
  94. package/lib/typescript/src/views/GestureHandler.android.d.ts +0 -2
  95. package/lib/typescript/src/views/GestureHandler.android.d.ts.map +0 -1
  96. package/lib/typescript/src/views/GestureHandler.d.ts +0 -15
  97. package/lib/typescript/src/views/GestureHandler.d.ts.map +0 -1
  98. package/lib/typescript/src/views/GestureHandler.ios.d.ts +0 -2
  99. package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +0 -1
  100. package/lib/typescript/src/views/GestureHandlerNative.d.ts +0 -6
  101. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +0 -1
  102. package/lib/typescript/src/views/legacy/Drawer.d.ts +0 -45
  103. package/lib/typescript/src/views/legacy/Drawer.d.ts.map +0 -1
  104. package/lib/typescript/src/views/legacy/Overlay.d.ts +0 -74
  105. package/lib/typescript/src/views/legacy/Overlay.d.ts.map +0 -1
  106. package/lib/typescript/src/views/modern/Drawer.d.ts +0 -4
  107. package/lib/typescript/src/views/modern/Drawer.d.ts.map +0 -1
  108. package/lib/typescript/src/views/modern/Overlay.d.ts +0 -74
  109. package/lib/typescript/src/views/modern/Overlay.d.ts.map +0 -1
  110. package/src/utils/DrawerGestureContext.tsx +0 -3
  111. package/src/utils/DrawerProgressContext.tsx +0 -6
  112. package/src/utils/useDrawerProgress.tsx +0 -18
  113. package/src/views/GestureHandler.android.tsx +0 -1
  114. package/src/views/GestureHandler.ios.tsx +0 -1
  115. package/src/views/GestureHandler.tsx +0 -29
  116. package/src/views/GestureHandlerNative.tsx +0 -24
  117. package/src/views/legacy/Drawer.tsx +0 -671
  118. package/src/views/legacy/Overlay.tsx +0 -75
  119. package/src/views/modern/Drawer.tsx +0 -424
  120. package/src/views/modern/Overlay.tsx +0 -70
@@ -1,671 +0,0 @@
1
- import * as React from 'react';
2
- import {
3
- I18nManager,
4
- InteractionManager,
5
- Keyboard,
6
- LayoutChangeEvent,
7
- Platform,
8
- StatusBar,
9
- StyleSheet,
10
- View,
11
- } from 'react-native';
12
- import Animated from 'react-native-reanimated';
13
-
14
- import type { DrawerProps } from '../../types';
15
- import DrawerProgressContext from '../../utils/DrawerProgressContext';
16
- import { GestureState, PanGestureHandler } from '../GestureHandler';
17
- import Overlay from './Overlay';
18
-
19
- const {
20
- Clock,
21
- Value,
22
- onChange,
23
- clockRunning,
24
- startClock,
25
- stopClock,
26
- spring,
27
- abs,
28
- add,
29
- and,
30
- block,
31
- call,
32
- cond,
33
- divide,
34
- eq,
35
- event,
36
- greaterThan,
37
- lessThan,
38
- max,
39
- min,
40
- multiply,
41
- neq,
42
- or,
43
- set,
44
- sub,
45
- } = Animated;
46
-
47
- const TRUE = 1;
48
- const FALSE = 0;
49
- const NOOP = 0;
50
- const UNSET = -1;
51
-
52
- const DIRECTION_LEFT = 1;
53
- const DIRECTION_RIGHT = -1;
54
-
55
- const SWIPE_DISTANCE_MINIMUM = 5;
56
-
57
- const DEFAULT_DRAWER_WIDTH = '80%';
58
-
59
- const SPRING_CONFIG = {
60
- stiffness: 1000,
61
- damping: 500,
62
- mass: 3,
63
- overshootClamping: true,
64
- restDisplacementThreshold: 0.01,
65
- restSpeedThreshold: 0.01,
66
- };
67
-
68
- const ANIMATED_ZERO = new Animated.Value(0);
69
- const ANIMATED_ONE = new Animated.Value(1);
70
-
71
- type Binary = 0 | 1;
72
-
73
- export default class DrawerView extends React.Component<DrawerProps> {
74
- componentDidUpdate(prevProps: DrawerProps) {
75
- const {
76
- open,
77
- drawerPosition,
78
- drawerType,
79
- swipeDistanceThreshold,
80
- swipeVelocityThreshold,
81
- hideStatusBarOnOpen: hideStatusBar,
82
- } = this.props;
83
-
84
- if (
85
- // If we're not in the middle of a transition, sync the drawer's open state
86
- typeof this.pendingOpenValue !== 'boolean' ||
87
- open !== this.pendingOpenValue
88
- ) {
89
- this.toggleDrawer(open);
90
- }
91
-
92
- this.pendingOpenValue = undefined;
93
-
94
- if (open !== prevProps.open && hideStatusBar) {
95
- this.toggleStatusBar(open);
96
- }
97
-
98
- if (prevProps.drawerPosition !== drawerPosition) {
99
- this.drawerPosition.setValue(
100
- drawerPosition === 'right' ? DIRECTION_RIGHT : DIRECTION_LEFT
101
- );
102
- }
103
-
104
- if (prevProps.drawerType !== drawerType) {
105
- this.isDrawerTypeFront.setValue(drawerType === 'front' ? TRUE : FALSE);
106
- }
107
-
108
- if (prevProps.swipeDistanceThreshold !== swipeDistanceThreshold) {
109
- this.swipeDistanceThreshold.setValue(swipeDistanceThreshold);
110
- }
111
-
112
- if (prevProps.swipeVelocityThreshold !== swipeVelocityThreshold) {
113
- this.swipeVelocityThreshold.setValue(swipeVelocityThreshold);
114
- }
115
- }
116
-
117
- componentWillUnmount() {
118
- this.toggleStatusBar(false);
119
- this.handleEndInteraction();
120
- }
121
-
122
- private handleEndInteraction = () => {
123
- if (this.interactionHandle !== undefined) {
124
- InteractionManager.clearInteractionHandle(this.interactionHandle);
125
- this.interactionHandle = undefined;
126
- }
127
- };
128
-
129
- private handleStartInteraction = () => {
130
- if (this.interactionHandle === undefined) {
131
- this.interactionHandle = InteractionManager.createInteractionHandle();
132
- }
133
- };
134
-
135
- private getDrawerWidth = (): number => {
136
- const { drawerStyle, dimensions } = this.props;
137
- const { width = DEFAULT_DRAWER_WIDTH } =
138
- StyleSheet.flatten(drawerStyle) || {};
139
-
140
- if (typeof width === 'string' && width.endsWith('%')) {
141
- // Try to calculate width if a percentage is given
142
- const percentage = Number(width.replace(/%$/, ''));
143
-
144
- if (Number.isFinite(percentage)) {
145
- return dimensions.width * (percentage / 100);
146
- }
147
- }
148
-
149
- return typeof width === 'number' ? width : 0;
150
- };
151
-
152
- private clock = new Clock();
153
- private interactionHandle: number | undefined;
154
-
155
- private isDrawerTypeFront = new Value<Binary>(
156
- this.props.drawerType === 'front' ? TRUE : FALSE
157
- );
158
-
159
- private isOpen = new Value<Binary>(this.props.open ? TRUE : FALSE);
160
- private nextIsOpen = new Value<Binary | -1>(UNSET);
161
- private isSwiping = new Value<Binary>(FALSE);
162
-
163
- private initialDrawerWidth = this.getDrawerWidth();
164
-
165
- private gestureState = new Value<number>(GestureState.UNDETERMINED);
166
- private touchX = new Value<number>(0);
167
- private velocityX = new Value<number>(0);
168
- private gestureX = new Value<number>(0);
169
- private offsetX = new Value<number>(0);
170
- private position = new Value<number>(
171
- this.props.open
172
- ? this.initialDrawerWidth *
173
- (this.props.drawerPosition === 'right'
174
- ? DIRECTION_RIGHT
175
- : DIRECTION_LEFT)
176
- : 0
177
- );
178
-
179
- private containerWidth = new Value<number>(this.props.dimensions.width);
180
- private drawerWidth = new Value<number>(this.initialDrawerWidth);
181
- private drawerOpacity = new Value<number>(
182
- this.props.drawerType === 'permanent' ? 1 : 0
183
- );
184
- private drawerPosition = new Value<number>(
185
- this.props.drawerPosition === 'right' ? DIRECTION_RIGHT : DIRECTION_LEFT
186
- );
187
-
188
- // Comment stolen from react-native-gesture-handler/DrawerLayout
189
- //
190
- // While closing the drawer when user starts gesture outside of its area (in greyed
191
- // out part of the window), we want the drawer to follow only once finger reaches the
192
- // edge of the drawer.
193
- // E.g. on the diagram below drawer is illustrate by X signs and the greyed out area by
194
- // dots. The touch gesture starts at '*' and moves left, touch path is indicated by
195
- // an arrow pointing left
196
- // 1) +---------------+ 2) +---------------+ 3) +---------------+ 4) +---------------+
197
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
198
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
199
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
200
- // |XXXXXXXX|......| |XXXXXXXX|.<-*..| |XXXXXXXX|<--*..| |XXXXX|<-----*..|
201
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
202
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
203
- // |XXXXXXXX|......| |XXXXXXXX|......| |XXXXXXXX|......| |XXXXX|.........|
204
- // +---------------+ +---------------+ +---------------+ +---------------+
205
- //
206
- // For the above to work properly we define animated value that will keep start position
207
- // of the gesture. Then we use that value to calculate how much we need to subtract from
208
- // the dragX. If the gesture started on the greyed out area we take the distance from the
209
- // edge of the drawer to the start position. Otherwise we don't subtract at all and the
210
- // drawer be pulled back as soon as you start the pan.
211
- //
212
- // This is used only when drawerType is "front"
213
- private touchDistanceFromDrawer = cond(
214
- this.isDrawerTypeFront,
215
- cond(
216
- eq(this.drawerPosition, DIRECTION_LEFT),
217
- max(
218
- // Distance of touch start from left screen edge - Drawer width
219
- sub(sub(this.touchX, this.gestureX), this.drawerWidth),
220
- 0
221
- ),
222
- min(
223
- multiply(
224
- // Distance of drawer from left screen edge - Touch start point
225
- sub(
226
- sub(this.containerWidth, this.drawerWidth),
227
- sub(this.touchX, this.gestureX)
228
- ),
229
- DIRECTION_RIGHT
230
- ),
231
- 0
232
- )
233
- ),
234
- 0
235
- );
236
-
237
- private swipeDistanceThreshold = new Value<number>(
238
- this.props.swipeDistanceThreshold
239
- );
240
- private swipeVelocityThreshold = new Value<number>(
241
- this.props.swipeVelocityThreshold
242
- );
243
-
244
- private currentOpenValue: boolean = this.props.open;
245
- private pendingOpenValue: boolean | undefined;
246
-
247
- private isStatusBarHidden: boolean = false;
248
-
249
- private manuallyTriggerSpring = new Value<Binary>(FALSE);
250
-
251
- private transitionTo = (isOpen: number | Animated.Node<number>) => {
252
- const toValue = new Value(0);
253
- const frameTime = new Value(0);
254
-
255
- const state = {
256
- position: this.position,
257
- time: new Value(0),
258
- finished: new Value(FALSE),
259
- velocity: new Value(0),
260
- };
261
-
262
- return block([
263
- cond(clockRunning(this.clock), NOOP, [
264
- // Animation wasn't running before
265
- // Set the initial values and start the clock
266
- set(toValue, multiply(isOpen, this.drawerWidth, this.drawerPosition)),
267
- set(frameTime, 0),
268
- set(state.time, 0),
269
- set(state.finished, FALSE),
270
- set(state.velocity, this.velocityX),
271
- set(this.isOpen, isOpen),
272
- startClock(this.clock),
273
- call([], this.handleStartInteraction),
274
- set(this.manuallyTriggerSpring, FALSE),
275
- ]),
276
- spring(this.clock, state, { ...SPRING_CONFIG, toValue }),
277
- cond(state.finished, [
278
- // Reset gesture and velocity from previous gesture
279
- set(this.touchX, 0),
280
- set(this.gestureX, 0),
281
- set(this.velocityX, 0),
282
- set(this.offsetX, 0),
283
- // When the animation finishes, stop the clock
284
- stopClock(this.clock),
285
- call([this.isOpen], ([value]: readonly Binary[]) => {
286
- const open = Boolean(value);
287
- this.handleEndInteraction();
288
-
289
- if (open !== this.props.open) {
290
- // Sync drawer's state after animation finished
291
- // This shouldn't be necessary, but there seems to be an issue on iOS
292
- this.toggleDrawer(this.props.open);
293
- }
294
- }),
295
- ]),
296
- ]);
297
- };
298
-
299
- private dragX = block([
300
- onChange(
301
- this.isOpen,
302
- call([this.isOpen], ([value]: readonly Binary[]) => {
303
- const open = Boolean(value);
304
-
305
- this.currentOpenValue = open;
306
-
307
- // Without this check, the drawer can go to an infinite update <-> animate loop for sync updates
308
- if (open !== this.props.open) {
309
- // If the mode changed, update state
310
- if (open) {
311
- this.props.onOpen();
312
- } else {
313
- this.props.onClose();
314
- }
315
-
316
- this.pendingOpenValue = open;
317
-
318
- // Force componentDidUpdate to fire, whether user does a setState or not
319
- // This allows us to detect when the user drops the update and revert back
320
- // It's necessary to make sure that the state stays in sync
321
- this.forceUpdate();
322
- }
323
- })
324
- ),
325
- onChange(
326
- this.nextIsOpen,
327
- cond(neq(this.nextIsOpen, UNSET), [
328
- // Stop any running animations
329
- cond(clockRunning(this.clock), stopClock(this.clock)),
330
- // Update the open value to trigger the transition
331
- set(this.isOpen, this.nextIsOpen),
332
- set(this.gestureX, 0),
333
- set(this.nextIsOpen, UNSET),
334
- ])
335
- ),
336
- // This block must be after the this.isOpen listener since we check for current value
337
- onChange(
338
- this.isSwiping,
339
- // Listen to updates for this value only when it changes
340
- // Without `onChange`, this will fire even if the value didn't change
341
- // We don't want to call the listeners if the value didn't change
342
- call([this.isSwiping], ([value]: readonly Binary[]) => {
343
- const { keyboardDismissMode } = this.props;
344
-
345
- if (value === TRUE) {
346
- if (keyboardDismissMode === 'on-drag') {
347
- Keyboard.dismiss();
348
- }
349
-
350
- this.toggleStatusBar(true);
351
- } else {
352
- this.toggleStatusBar(this.currentOpenValue);
353
- }
354
- })
355
- ),
356
- onChange(
357
- this.gestureState,
358
- cond(
359
- eq(this.gestureState, GestureState.ACTIVE),
360
- call([], this.handleStartInteraction)
361
- )
362
- ),
363
- cond(
364
- eq(this.gestureState, GestureState.ACTIVE),
365
- [
366
- cond(this.isSwiping, NOOP, [
367
- // We weren't dragging before, set it to true
368
- set(this.isSwiping, TRUE),
369
- // Also update the drag offset to the last position
370
- set(this.offsetX, this.position),
371
- ]),
372
- // Update position with previous offset + gesture distance
373
- set(
374
- this.position,
375
- add(this.offsetX, this.gestureX, this.touchDistanceFromDrawer)
376
- ),
377
- // Stop animations while we're dragging
378
- stopClock(this.clock),
379
- ],
380
- [
381
- set(this.isSwiping, FALSE),
382
- set(this.touchX, 0),
383
- this.transitionTo(
384
- cond(
385
- this.manuallyTriggerSpring,
386
- this.isOpen,
387
- cond(
388
- or(
389
- and(
390
- greaterThan(abs(this.gestureX), SWIPE_DISTANCE_MINIMUM),
391
- greaterThan(abs(this.velocityX), this.swipeVelocityThreshold)
392
- ),
393
- greaterThan(abs(this.gestureX), this.swipeDistanceThreshold)
394
- ),
395
- cond(
396
- eq(this.drawerPosition, DIRECTION_LEFT),
397
- // If swiped to right, open the drawer, otherwise close it
398
- greaterThan(
399
- cond(eq(this.velocityX, 0), this.gestureX, this.velocityX),
400
- 0
401
- ),
402
- // If swiped to left, open the drawer, otherwise close it
403
- lessThan(
404
- cond(eq(this.velocityX, 0), this.gestureX, this.velocityX),
405
- 0
406
- )
407
- ),
408
- this.isOpen
409
- )
410
- )
411
- ),
412
- ]
413
- ),
414
- this.position,
415
- ]);
416
-
417
- private translateX = cond(
418
- eq(this.drawerPosition, DIRECTION_RIGHT),
419
- min(max(multiply(this.drawerWidth, -1), this.dragX), 0),
420
- max(min(this.drawerWidth, this.dragX), 0)
421
- );
422
-
423
- private progress = cond(
424
- // Check if the drawer width is available to avoid division by zero
425
- eq(this.drawerWidth, 0),
426
- 0,
427
- abs(divide(this.translateX, this.drawerWidth))
428
- );
429
-
430
- private handleGestureEvent = event([
431
- {
432
- nativeEvent: {
433
- x: this.touchX,
434
- translationX: this.gestureX,
435
- velocityX: this.velocityX,
436
- },
437
- },
438
- ]);
439
-
440
- private handleGestureStateChange = event([
441
- {
442
- nativeEvent: {
443
- state: (s: Animated.Value<number>) => set(this.gestureState, s),
444
- },
445
- },
446
- ]);
447
-
448
- private handleContainerLayout = (e: LayoutChangeEvent) =>
449
- this.containerWidth.setValue(e.nativeEvent.layout.width);
450
-
451
- private handleDrawerLayout = (e: LayoutChangeEvent) => {
452
- this.drawerWidth.setValue(e.nativeEvent.layout.width);
453
- this.toggleDrawer(this.props.open);
454
-
455
- // Until layout is available, drawer is hidden with opacity: 0 by default
456
- // Show it in the next frame when layout is available
457
- // If we don't delay it until the next frame, there's a visible flicker
458
- requestAnimationFrame(() =>
459
- requestAnimationFrame(() => this.drawerOpacity.setValue(1))
460
- );
461
- };
462
-
463
- private toggleDrawer = (open: boolean) => {
464
- if (this.currentOpenValue !== open) {
465
- this.nextIsOpen.setValue(open ? TRUE : FALSE);
466
-
467
- // This value will also be set shortly after as changing this.nextIsOpen changes this.isOpen
468
- // However, there's a race condition on Android, so we need to set a bit earlier
469
- this.currentOpenValue = open;
470
- }
471
- };
472
-
473
- private toggleStatusBar = (hidden: boolean) => {
474
- const { hideStatusBarOnOpen: hideStatusBar, statusBarAnimation } =
475
- this.props;
476
-
477
- if (hideStatusBar && this.isStatusBarHidden !== hidden) {
478
- this.isStatusBarHidden = hidden;
479
- StatusBar.setHidden(hidden, statusBarAnimation);
480
- }
481
- };
482
-
483
- render() {
484
- const {
485
- open,
486
- swipeEnabled,
487
- drawerPosition,
488
- drawerType,
489
- swipeEdgeWidth,
490
- drawerStyle,
491
- overlayStyle,
492
- renderDrawerContent,
493
- renderSceneContent,
494
- gestureHandlerProps,
495
- } = this.props;
496
-
497
- const isOpen = drawerType === 'permanent' ? true : open;
498
- const isRight = drawerPosition === 'right';
499
-
500
- const contentTranslateX =
501
- drawerType === 'front' ? ANIMATED_ZERO : this.translateX;
502
-
503
- const drawerTranslateX =
504
- drawerType === 'back'
505
- ? I18nManager.getConstants().isRTL
506
- ? multiply(
507
- sub(this.containerWidth, this.drawerWidth),
508
- isRight ? 1 : -1
509
- )
510
- : ANIMATED_ZERO
511
- : this.translateX;
512
-
513
- const offset =
514
- drawerType === 'back'
515
- ? 0
516
- : I18nManager.getConstants().isRTL
517
- ? '100%'
518
- : multiply(this.drawerWidth, -1);
519
-
520
- // FIXME: Currently hitSlop is broken when on Android when drawer is on right
521
- // https://github.com/software-mansion/react-native-gesture-handler/issues/569
522
- const hitSlop = isRight
523
- ? // Extend hitSlop to the side of the screen when drawer is closed
524
- // This lets the user drag the drawer from the side of the screen
525
- { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
526
- : { left: 0, width: isOpen ? undefined : swipeEdgeWidth };
527
-
528
- const progress = drawerType === 'permanent' ? ANIMATED_ONE : this.progress;
529
-
530
- return (
531
- <DrawerProgressContext.Provider value={progress}>
532
- <PanGestureHandler
533
- activeOffsetX={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
534
- failOffsetY={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
535
- onGestureEvent={this.handleGestureEvent}
536
- onHandlerStateChange={this.handleGestureStateChange}
537
- hitSlop={hitSlop}
538
- enabled={drawerType !== 'permanent' && swipeEnabled}
539
- {...gestureHandlerProps}
540
- >
541
- <Animated.View
542
- onLayout={this.handleContainerLayout}
543
- style={[
544
- styles.main,
545
- {
546
- flexDirection:
547
- drawerType === 'permanent' && !isRight
548
- ? 'row-reverse'
549
- : 'row',
550
- },
551
- ]}
552
- >
553
- <Animated.View
554
- style={[
555
- styles.content,
556
- {
557
- transform:
558
- drawerType === 'permanent'
559
- ? // Reanimated needs the property to be present, but it results in Browser bug
560
- // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
561
- []
562
- : [{ translateX: contentTranslateX }],
563
- },
564
- ]}
565
- >
566
- <View
567
- accessibilityElementsHidden={
568
- isOpen && drawerType !== 'permanent'
569
- }
570
- importantForAccessibility={
571
- isOpen && drawerType !== 'permanent'
572
- ? 'no-hide-descendants'
573
- : 'auto'
574
- }
575
- style={styles.content}
576
- >
577
- {renderSceneContent()}
578
- </View>
579
- {
580
- // Disable overlay if sidebar is permanent
581
- drawerType === 'permanent' ? null : (
582
- <Overlay
583
- progress={progress}
584
- onPress={() => this.toggleDrawer(false)}
585
- style={overlayStyle as any}
586
- accessibilityElementsHidden={!isOpen}
587
- importantForAccessibility={
588
- isOpen ? 'auto' : 'no-hide-descendants'
589
- }
590
- />
591
- )
592
- }
593
- </Animated.View>
594
- <Animated.Code
595
- // This is needed to make sure that container width updates with `setValue`
596
- // Without this, it won't update when not used in styles
597
- exec={this.containerWidth}
598
- />
599
- {drawerType === 'permanent' ? null : (
600
- <Animated.Code
601
- exec={block([
602
- onChange(this.manuallyTriggerSpring, [
603
- cond(eq(this.manuallyTriggerSpring, TRUE), [
604
- set(this.nextIsOpen, FALSE),
605
- call([], () => (this.currentOpenValue = false)),
606
- ]),
607
- ]),
608
- ])}
609
- />
610
- )}
611
- <Animated.View
612
- accessibilityViewIsModal={isOpen && drawerType !== 'permanent'}
613
- removeClippedSubviews={Platform.OS !== 'ios'}
614
- onLayout={this.handleDrawerLayout}
615
- style={[
616
- styles.container,
617
- {
618
- transform:
619
- drawerType === 'permanent'
620
- ? // Reanimated needs the property to be present, but it results in Browser bug
621
- // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
622
- []
623
- : [{ translateX: drawerTranslateX }],
624
- opacity: this.drawerOpacity,
625
- },
626
- drawerType === 'permanent'
627
- ? // Without this, the `left`/`right` values don't get reset
628
- isRight
629
- ? { right: 0 }
630
- : { left: 0 }
631
- : [
632
- styles.nonPermanent,
633
- isRight ? { right: offset } : { left: offset },
634
- { zIndex: drawerType === 'back' ? -1 : 0 },
635
- ],
636
- drawerStyle as any,
637
- ]}
638
- >
639
- {renderDrawerContent()}
640
- </Animated.View>
641
- </Animated.View>
642
- </PanGestureHandler>
643
- </DrawerProgressContext.Provider>
644
- );
645
- }
646
- }
647
-
648
- const styles = StyleSheet.create({
649
- container: {
650
- backgroundColor: 'white',
651
- maxWidth: '100%',
652
- },
653
- nonPermanent: {
654
- position: 'absolute',
655
- top: 0,
656
- bottom: 0,
657
- width: DEFAULT_DRAWER_WIDTH,
658
- },
659
- content: {
660
- flex: 1,
661
- },
662
- main: {
663
- flex: 1,
664
- ...Platform.select({
665
- // FIXME: We need to hide `overflowX` on Web so the translated content doesn't show offscreen.
666
- // But adding `overflowX: 'hidden'` prevents content from collapsing the URL bar.
667
- web: null,
668
- default: { overflow: 'hidden' },
669
- }),
670
- },
671
- });