react-native-drawer-layout 4.0.0-alpha.1 → 4.0.0-alpha.3

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