@react-navigation/drawer 6.6.2 → 7.0.0-alpha.1

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 (167) hide show
  1. package/lib/commonjs/index.js +24 -27
  2. package/lib/commonjs/index.js.map +1 -1
  3. package/lib/commonjs/navigators/createDrawerNavigator.js +8 -49
  4. package/lib/commonjs/navigators/createDrawerNavigator.js.map +1 -1
  5. package/lib/commonjs/utils/DrawerPositionContext.js +3 -3
  6. package/lib/commonjs/utils/DrawerPositionContext.js.map +1 -1
  7. package/lib/commonjs/utils/DrawerStatusContext.js +2 -3
  8. package/lib/commonjs/utils/DrawerStatusContext.js.map +1 -1
  9. package/lib/commonjs/utils/getDrawerStatusFromState.js +1 -1
  10. package/lib/commonjs/utils/getDrawerStatusFromState.js.map +1 -1
  11. package/lib/commonjs/utils/useDrawerStatus.js +3 -4
  12. package/lib/commonjs/utils/useDrawerStatus.js.map +1 -1
  13. package/lib/commonjs/views/DrawerContent.js +5 -6
  14. package/lib/commonjs/views/DrawerContent.js.map +1 -1
  15. package/lib/commonjs/views/DrawerContentScrollView.js +6 -7
  16. package/lib/commonjs/views/DrawerContentScrollView.js.map +1 -1
  17. package/lib/commonjs/views/DrawerItem.js +14 -10
  18. package/lib/commonjs/views/DrawerItem.js.map +1 -1
  19. package/lib/commonjs/views/DrawerItemList.js +9 -10
  20. package/lib/commonjs/views/DrawerItemList.js.map +1 -1
  21. package/lib/commonjs/views/DrawerToggleButton.js +1 -1
  22. package/lib/commonjs/views/DrawerToggleButton.js.map +1 -1
  23. package/lib/commonjs/views/DrawerView.js +78 -73
  24. package/lib/commonjs/views/DrawerView.js.map +1 -1
  25. package/lib/module/index.js +11 -13
  26. package/lib/module/index.js.map +1 -1
  27. package/lib/module/navigators/createDrawerNavigator.js +5 -45
  28. package/lib/module/navigators/createDrawerNavigator.js.map +1 -1
  29. package/lib/module/utils/DrawerPositionContext.js +1 -1
  30. package/lib/module/utils/DrawerPositionContext.js.map +1 -1
  31. package/lib/module/utils/DrawerStatusContext.js +1 -2
  32. package/lib/module/utils/DrawerStatusContext.js.map +1 -1
  33. package/lib/module/utils/getDrawerStatusFromState.js +1 -1
  34. package/lib/module/utils/getDrawerStatusFromState.js.map +1 -1
  35. package/lib/module/utils/useDrawerStatus.js +2 -2
  36. package/lib/module/utils/useDrawerStatus.js.map +1 -1
  37. package/lib/module/views/DrawerContent.js +3 -3
  38. package/lib/module/views/DrawerContent.js.map +1 -1
  39. package/lib/module/views/DrawerContentScrollView.js +3 -3
  40. package/lib/module/views/DrawerContentScrollView.js.map +1 -1
  41. package/lib/module/views/DrawerItem.js +15 -11
  42. package/lib/module/views/DrawerItem.js.map +1 -1
  43. package/lib/module/views/DrawerItemList.js +9 -9
  44. package/lib/module/views/DrawerItemList.js.map +1 -1
  45. package/lib/module/views/DrawerToggleButton.js +1 -1
  46. package/lib/module/views/DrawerToggleButton.js.map +1 -1
  47. package/lib/module/views/DrawerView.js +72 -67
  48. package/lib/module/views/DrawerView.js.map +1 -1
  49. package/lib/typescript/src/index.d.ts +11 -13
  50. package/lib/typescript/src/index.d.ts.map +1 -1
  51. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts +9 -4
  52. package/lib/typescript/src/navigators/createDrawerNavigator.d.ts.map +1 -1
  53. package/lib/typescript/src/types.d.ts +51 -16
  54. package/lib/typescript/src/types.d.ts.map +1 -1
  55. package/lib/typescript/src/utils/DrawerPositionContext.d.ts +1 -2
  56. package/lib/typescript/src/utils/DrawerPositionContext.d.ts.map +1 -1
  57. package/lib/typescript/src/utils/DrawerStatusContext.d.ts +1 -2
  58. package/lib/typescript/src/utils/DrawerStatusContext.d.ts.map +1 -1
  59. package/lib/typescript/src/utils/getDrawerStatusFromState.d.ts +1 -1
  60. package/lib/typescript/src/utils/getDrawerStatusFromState.d.ts.map +1 -1
  61. package/lib/typescript/src/utils/useDrawerStatus.d.ts +1 -1
  62. package/lib/typescript/src/utils/useDrawerStatus.d.ts.map +1 -1
  63. package/lib/typescript/src/views/DrawerContent.d.ts +1 -1
  64. package/lib/typescript/src/views/DrawerContent.d.ts.map +1 -1
  65. package/lib/typescript/src/views/DrawerContentScrollView.d.ts +1 -2
  66. package/lib/typescript/src/views/DrawerContentScrollView.d.ts.map +1 -1
  67. package/lib/typescript/src/views/DrawerItem.d.ts +11 -6
  68. package/lib/typescript/src/views/DrawerItem.d.ts.map +1 -1
  69. package/lib/typescript/src/views/DrawerItemList.d.ts +2 -2
  70. package/lib/typescript/src/views/DrawerItemList.d.ts.map +1 -1
  71. package/lib/typescript/src/views/DrawerToggleButton.d.ts +2 -2
  72. package/lib/typescript/src/views/DrawerToggleButton.d.ts.map +1 -1
  73. package/lib/typescript/src/views/DrawerView.d.ts +2 -2
  74. package/lib/typescript/src/views/DrawerView.d.ts.map +1 -1
  75. package/lib/typescript/src/views/ScreenFallback.d.ts +1 -1
  76. package/lib/typescript/src/views/ScreenFallback.d.ts.map +1 -1
  77. package/package.json +15 -14
  78. package/src/index.tsx +15 -13
  79. package/src/navigators/createDrawerNavigator.tsx +4 -74
  80. package/src/types.tsx +24 -3
  81. package/src/utils/DrawerPositionContext.tsx +3 -1
  82. package/src/utils/DrawerStatusContext.tsx +3 -5
  83. package/src/utils/getDrawerStatusFromState.tsx +1 -1
  84. package/src/utils/useDrawerStatus.tsx +2 -2
  85. package/src/views/DrawerContent.tsx +3 -3
  86. package/src/views/DrawerContentScrollView.tsx +5 -3
  87. package/src/views/DrawerItem.tsx +23 -20
  88. package/src/views/DrawerItemList.tsx +7 -10
  89. package/src/views/DrawerToggleButton.tsx +1 -1
  90. package/src/views/DrawerView.tsx +68 -78
  91. package/lib/commonjs/utils/DrawerGestureContext.js +0 -12
  92. package/lib/commonjs/utils/DrawerGestureContext.js.map +0 -1
  93. package/lib/commonjs/utils/DrawerProgressContext.js +0 -12
  94. package/lib/commonjs/utils/DrawerProgressContext.js.map +0 -1
  95. package/lib/commonjs/utils/useDrawerProgress.js +0 -19
  96. package/lib/commonjs/utils/useDrawerProgress.js.map +0 -1
  97. package/lib/commonjs/views/GestureHandler.android.js +0 -17
  98. package/lib/commonjs/views/GestureHandler.android.js.map +0 -1
  99. package/lib/commonjs/views/GestureHandler.ios.js +0 -17
  100. package/lib/commonjs/views/GestureHandler.ios.js.map +0 -1
  101. package/lib/commonjs/views/GestureHandler.js +0 -32
  102. package/lib/commonjs/views/GestureHandler.js.map +0 -1
  103. package/lib/commonjs/views/GestureHandlerNative.js +0 -37
  104. package/lib/commonjs/views/GestureHandlerNative.js.map +0 -1
  105. package/lib/commonjs/views/legacy/Drawer.js +0 -438
  106. package/lib/commonjs/views/legacy/Drawer.js.map +0 -1
  107. package/lib/commonjs/views/legacy/Overlay.js +0 -74
  108. package/lib/commonjs/views/legacy/Overlay.js.map +0 -1
  109. package/lib/commonjs/views/modern/Drawer.js +0 -304
  110. package/lib/commonjs/views/modern/Drawer.js.map +0 -1
  111. package/lib/commonjs/views/modern/Overlay.js +0 -69
  112. package/lib/commonjs/views/modern/Overlay.js.map +0 -1
  113. package/lib/module/utils/DrawerGestureContext.js +0 -3
  114. package/lib/module/utils/DrawerGestureContext.js.map +0 -1
  115. package/lib/module/utils/DrawerProgressContext.js +0 -3
  116. package/lib/module/utils/DrawerProgressContext.js.map +0 -1
  117. package/lib/module/utils/useDrawerProgress.js +0 -10
  118. package/lib/module/utils/useDrawerProgress.js.map +0 -1
  119. package/lib/module/views/GestureHandler.android.js +0 -2
  120. package/lib/module/views/GestureHandler.android.js.map +0 -1
  121. package/lib/module/views/GestureHandler.ios.js +0 -2
  122. package/lib/module/views/GestureHandler.ios.js.map +0 -1
  123. package/lib/module/views/GestureHandler.js +0 -20
  124. package/lib/module/views/GestureHandler.js.map +0 -1
  125. package/lib/module/views/GestureHandlerNative.js +0 -11
  126. package/lib/module/views/GestureHandlerNative.js.map +0 -1
  127. package/lib/module/views/legacy/Drawer.js +0 -428
  128. package/lib/module/views/legacy/Drawer.js.map +0 -1
  129. package/lib/module/views/legacy/Overlay.js +0 -64
  130. package/lib/module/views/legacy/Overlay.js.map +0 -1
  131. package/lib/module/views/modern/Drawer.js +0 -295
  132. package/lib/module/views/modern/Drawer.js.map +0 -1
  133. package/lib/module/views/modern/Overlay.js +0 -60
  134. package/lib/module/views/modern/Overlay.js.map +0 -1
  135. package/lib/typescript/src/utils/DrawerGestureContext.d.ts +0 -4
  136. package/lib/typescript/src/utils/DrawerGestureContext.d.ts.map +0 -1
  137. package/lib/typescript/src/utils/DrawerProgressContext.d.ts +0 -5
  138. package/lib/typescript/src/utils/DrawerProgressContext.d.ts.map +0 -1
  139. package/lib/typescript/src/utils/useDrawerProgress.d.ts +0 -3
  140. package/lib/typescript/src/utils/useDrawerProgress.d.ts.map +0 -1
  141. package/lib/typescript/src/views/GestureHandler.android.d.ts +0 -2
  142. package/lib/typescript/src/views/GestureHandler.android.d.ts.map +0 -1
  143. package/lib/typescript/src/views/GestureHandler.d.ts +0 -15
  144. package/lib/typescript/src/views/GestureHandler.d.ts.map +0 -1
  145. package/lib/typescript/src/views/GestureHandler.ios.d.ts +0 -2
  146. package/lib/typescript/src/views/GestureHandler.ios.d.ts.map +0 -1
  147. package/lib/typescript/src/views/GestureHandlerNative.d.ts +0 -6
  148. package/lib/typescript/src/views/GestureHandlerNative.d.ts.map +0 -1
  149. package/lib/typescript/src/views/legacy/Drawer.d.ts +0 -45
  150. package/lib/typescript/src/views/legacy/Drawer.d.ts.map +0 -1
  151. package/lib/typescript/src/views/legacy/Overlay.d.ts +0 -75
  152. package/lib/typescript/src/views/legacy/Overlay.d.ts.map +0 -1
  153. package/lib/typescript/src/views/modern/Drawer.d.ts +0 -4
  154. package/lib/typescript/src/views/modern/Drawer.d.ts.map +0 -1
  155. package/lib/typescript/src/views/modern/Overlay.d.ts +0 -75
  156. package/lib/typescript/src/views/modern/Overlay.d.ts.map +0 -1
  157. package/src/utils/DrawerGestureContext.tsx +0 -3
  158. package/src/utils/DrawerProgressContext.tsx +0 -6
  159. package/src/utils/useDrawerProgress.tsx +0 -18
  160. package/src/views/GestureHandler.android.tsx +0 -1
  161. package/src/views/GestureHandler.ios.tsx +0 -1
  162. package/src/views/GestureHandler.tsx +0 -29
  163. package/src/views/GestureHandlerNative.tsx +0 -24
  164. package/src/views/legacy/Drawer.tsx +0 -672
  165. package/src/views/legacy/Overlay.tsx +0 -87
  166. package/src/views/modern/Drawer.tsx +0 -425
  167. package/src/views/modern/Overlay.tsx +0 -82
@@ -1,672 +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
- overlayAccessibilityLabel,
496
- } = this.props;
497
-
498
- const isOpen = drawerType === 'permanent' ? true : open;
499
- const isRight = drawerPosition === 'right';
500
-
501
- const contentTranslateX =
502
- drawerType === 'front' ? ANIMATED_ZERO : this.translateX;
503
-
504
- const drawerTranslateX =
505
- drawerType === 'back'
506
- ? I18nManager.getConstants().isRTL
507
- ? multiply(
508
- sub(this.containerWidth, this.drawerWidth),
509
- isRight ? 1 : -1
510
- )
511
- : ANIMATED_ZERO
512
- : this.translateX;
513
-
514
- const offset =
515
- drawerType === 'back'
516
- ? 0
517
- : I18nManager.getConstants().isRTL
518
- ? '100%'
519
- : multiply(this.drawerWidth, -1);
520
-
521
- // FIXME: Currently hitSlop is broken when on Android when drawer is on right
522
- // https://github.com/software-mansion/react-native-gesture-handler/issues/569
523
- const hitSlop = isRight
524
- ? // Extend hitSlop to the side of the screen when drawer is closed
525
- // This lets the user drag the drawer from the side of the screen
526
- { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
527
- : { left: 0, width: isOpen ? undefined : swipeEdgeWidth };
528
-
529
- const progress = drawerType === 'permanent' ? ANIMATED_ONE : this.progress;
530
-
531
- return (
532
- <DrawerProgressContext.Provider value={progress}>
533
- <PanGestureHandler
534
- activeOffsetX={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
535
- failOffsetY={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
536
- onGestureEvent={this.handleGestureEvent}
537
- onHandlerStateChange={this.handleGestureStateChange}
538
- hitSlop={hitSlop}
539
- enabled={drawerType !== 'permanent' && swipeEnabled}
540
- {...gestureHandlerProps}
541
- >
542
- <Animated.View
543
- onLayout={this.handleContainerLayout}
544
- style={[
545
- styles.main,
546
- {
547
- flexDirection:
548
- drawerType === 'permanent' && !isRight
549
- ? 'row-reverse'
550
- : 'row',
551
- },
552
- ]}
553
- >
554
- <Animated.View
555
- style={[
556
- styles.content,
557
- {
558
- transform:
559
- drawerType === 'permanent'
560
- ? // Reanimated needs the property to be present, but it results in Browser bug
561
- // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
562
- []
563
- : [{ translateX: contentTranslateX }],
564
- },
565
- ]}
566
- >
567
- <View
568
- accessibilityElementsHidden={
569
- isOpen && drawerType !== 'permanent'
570
- }
571
- importantForAccessibility={
572
- isOpen && drawerType !== 'permanent'
573
- ? 'no-hide-descendants'
574
- : 'auto'
575
- }
576
- style={styles.content}
577
- >
578
- {renderSceneContent()}
579
- </View>
580
- {
581
- // Disable overlay if sidebar is permanent
582
- drawerType === 'permanent' ? null : (
583
- <Overlay
584
- progress={progress}
585
- onPress={() => this.toggleDrawer(false)}
586
- accessibilityLabel={overlayAccessibilityLabel}
587
- style={overlayStyle as any}
588
- accessibilityElementsHidden={!isOpen}
589
- importantForAccessibility={
590
- isOpen ? 'auto' : 'no-hide-descendants'
591
- }
592
- />
593
- )
594
- }
595
- </Animated.View>
596
- <Animated.Code
597
- // This is needed to make sure that container width updates with `setValue`
598
- // Without this, it won't update when not used in styles
599
- exec={this.containerWidth}
600
- />
601
- {drawerType === 'permanent' ? null : (
602
- <Animated.Code
603
- exec={block([
604
- onChange(this.manuallyTriggerSpring, [
605
- cond(eq(this.manuallyTriggerSpring, TRUE), [
606
- set(this.nextIsOpen, FALSE),
607
- call([], () => (this.currentOpenValue = false)),
608
- ]),
609
- ]),
610
- ])}
611
- />
612
- )}
613
- <Animated.View
614
- removeClippedSubviews={Platform.OS !== 'ios'}
615
- onLayout={this.handleDrawerLayout}
616
- style={[
617
- styles.container,
618
- {
619
- transform:
620
- drawerType === 'permanent'
621
- ? // Reanimated needs the property to be present, but it results in Browser bug
622
- // https://bugs.chromium.org/p/chromium/issues/detail?id=20574
623
- []
624
- : [{ translateX: drawerTranslateX }],
625
- opacity: this.drawerOpacity,
626
- },
627
- drawerType === 'permanent'
628
- ? // Without this, the `left`/`right` values don't get reset
629
- isRight
630
- ? { right: 0 }
631
- : { left: 0 }
632
- : [
633
- styles.nonPermanent,
634
- isRight ? { right: offset } : { left: offset },
635
- { zIndex: drawerType === 'back' ? -1 : 0 },
636
- ],
637
- drawerStyle as any,
638
- ]}
639
- >
640
- {renderDrawerContent()}
641
- </Animated.View>
642
- </Animated.View>
643
- </PanGestureHandler>
644
- </DrawerProgressContext.Provider>
645
- );
646
- }
647
- }
648
-
649
- const styles = StyleSheet.create({
650
- container: {
651
- backgroundColor: 'white',
652
- maxWidth: '100%',
653
- },
654
- nonPermanent: {
655
- position: 'absolute',
656
- top: 0,
657
- bottom: 0,
658
- width: DEFAULT_DRAWER_WIDTH,
659
- },
660
- content: {
661
- flex: 1,
662
- },
663
- main: {
664
- flex: 1,
665
- ...Platform.select({
666
- // FIXME: We need to hide `overflowX` on Web so the translated content doesn't show offscreen.
667
- // But adding `overflowX: 'hidden'` prevents content from collapsing the URL bar.
668
- web: null,
669
- default: { overflow: 'hidden' },
670
- }),
671
- },
672
- });