@wavemaker/app-rn-runtime 11.13.0-rc.222 → 11.13.0-rc.6277

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.
@@ -4,8 +4,9 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
4
4
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
5
  import React, { createRef } from 'react';
6
6
  import { BaseComponent, BaseComponentState } from '@wavemaker/app-rn-runtime/core/base.component';
7
- import { View, Animated, PanResponder, Dimensions, TouchableWithoutFeedback, Platform, StatusBar, BackHandler, KeyboardAvoidingView, Keyboard, Modal, Pressable } from 'react-native';
7
+ import { View, PanResponder, Dimensions, TouchableWithoutFeedback, Platform, StatusBar, BackHandler, KeyboardAvoidingView, Keyboard, Modal, Pressable } from 'react-native';
8
8
  import { ScrollView } from 'react-native-gesture-handler';
9
+ import Animated, { useAnimatedStyle, withTiming, runOnJS, Easing, makeMutable, cancelAnimation } from 'react-native-reanimated';
9
10
  import WmBottomsheetProps from './bottomsheet.props';
10
11
  import { DEFAULT_CLASS } from './bottomsheet.styles';
11
12
  import { createSkeleton } from '../skeleton/skeleton.component';
@@ -18,10 +19,6 @@ const {
18
19
  export class WmBottomsheetState extends BaseComponentState {
19
20
  constructor(...args) {
20
21
  super(...args);
21
- _defineProperty(this, "translateY", new Animated.Value(SCREEN_HEIGHT));
22
- _defineProperty(this, "backdropOpacity", new Animated.Value(0));
23
- _defineProperty(this, "sheetHeight", new Animated.Value(0));
24
- _defineProperty(this, "lastGestureDy", 0);
25
22
  _defineProperty(this, "scrollViewRef", /*#__PURE__*/createRef());
26
23
  _defineProperty(this, "isScrolling", false);
27
24
  _defineProperty(this, "scrollOffset", 0);
@@ -29,15 +26,71 @@ export class WmBottomsheetState extends BaseComponentState {
29
26
  _defineProperty(this, "isBottomsheetVisible", false);
30
27
  _defineProperty(this, "keyboardHeight", 0);
31
28
  _defineProperty(this, "localModalsOpened", []);
29
+ _defineProperty(this, "lastGestureDy", 0);
32
30
  }
33
31
  }
32
+
33
+ // Animated wrapper component that uses hooks
34
+ const AnimatedBottomsheetContent = ({
35
+ translateY,
36
+ backdropOpacity,
37
+ sheetHeight,
38
+ lastGestureDy,
39
+ styles,
40
+ props,
41
+ children,
42
+ panHandlers,
43
+ dragHandlePanHandlers,
44
+ onBackdropPress,
45
+ onDragHandlePress,
46
+ getTestProps,
47
+ enabledragsettle
48
+ }) => {
49
+ const backdropAnimatedStyle = useAnimatedStyle(() => ({
50
+ opacity: backdropOpacity.value
51
+ }));
52
+ const containerAnimatedStyle = useAnimatedStyle(() => ({
53
+ height: sheetHeight.value,
54
+ transform: [{
55
+ translateY: translateY.value
56
+ }]
57
+ }));
58
+ const contentStyle = useAnimatedStyle(() => {
59
+ if (enabledragsettle && lastGestureDy.value > 0) {
60
+ return {
61
+ paddingBottom: lastGestureDy.value
62
+ };
63
+ }
64
+ return {};
65
+ });
66
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TouchableWithoutFeedback, {
67
+ onPress: onBackdropPress
68
+ }, /*#__PURE__*/React.createElement(Animated.View, _extends({
69
+ style: [styles.backdrop, backdropAnimatedStyle]
70
+ }, getTestProps('backdrop'), getAccessibilityProps(AccessibilityWidgetType.BOTTOMSHEET, props)))), /*#__PURE__*/React.createElement(Animated.View, _extends({
71
+ style: [styles.container, containerAnimatedStyle]
72
+ }, panHandlers), /*#__PURE__*/React.createElement(View, _extends({
73
+ style: styles.dragHandleContainer
74
+ }, dragHandlePanHandlers), /*#__PURE__*/React.createElement(Pressable, {
75
+ onPress: onDragHandlePress
76
+ }, /*#__PURE__*/React.createElement(View, _extends({
77
+ style: styles.dragIconHandle
78
+ }, getTestProps('draghandle'))))), children(contentStyle)));
79
+ };
34
80
  export default class WmBottomsheet extends BaseComponent {
81
+ // Helper method to calculate animation duration based on distance and velocity
82
+ getAnimationDuration(distance, velocity) {
83
+ // Base duration on distance, but cap it between 200-500ms
84
+ // Higher velocity = shorter duration for snappier feel
85
+ const velocityFactor = Math.max(0.3, Math.min(1, 1 - Math.abs(velocity) / 2));
86
+ const calculatedDuration = Math.abs(distance) * velocityFactor;
87
+ return Math.min(500, Math.max(200, calculatedDuration));
88
+ }
35
89
  calculateSheetHeight(bottomsheetheightratio) {
36
90
  // Use default height if ratio not provided, but ensure it's not below minimum
37
91
  const effectiveRatio = bottomsheetheightratio || this.defaultHeight;
38
92
  this.maxHeightRatio = Math.max(this.minimumHeight, Math.min(effectiveRatio, this.maxHeight));
39
93
  const screenHeight = Dimensions.get('screen').height;
40
- const windowHeight = Dimensions.get('window').height;
41
94
  let calculatedHeight = screenHeight * this.maxHeightRatio;
42
95
  if (Platform.OS === 'ios') {
43
96
  // Subtract top inset bar height for ios only if bottomsheetheightratio is 0.9
@@ -72,8 +125,8 @@ export default class WmBottomsheet extends BaseComponent {
72
125
  _defineProperty(this, "minimumHeight", 0.01);
73
126
  _defineProperty(this, "minimumExpandedHeight", 0.5);
74
127
  _defineProperty(this, "maxHeight", 1.0);
75
- // Allow full screen height
76
128
  _defineProperty(this, "animationDuration", 400);
129
+ _defineProperty(this, "keyboardAnimationDuration", Platform.OS === 'ios' ? 250 : 275);
77
130
  _defineProperty(this, "statusBarHeight", StatusBar.currentHeight || 0);
78
131
  _defineProperty(this, "defaultTopInset", 44);
79
132
  _defineProperty(this, "maxHeightRatio", 0);
@@ -83,51 +136,75 @@ export default class WmBottomsheet extends BaseComponent {
83
136
  _defineProperty(this, "iosKeyboardHeight", 0);
84
137
  _defineProperty(this, "isIosKeyboardHeightSet", false);
85
138
  _defineProperty(this, "sheetModalService", void 0);
139
+ _defineProperty(this, "isDragHandleExpanding", false);
140
+ // Reanimated shared values - created once and reused
141
+ _defineProperty(this, "translateY", void 0);
142
+ _defineProperty(this, "backdropOpacity", void 0);
143
+ _defineProperty(this, "sheetHeight", void 0);
144
+ _defineProperty(this, "lastGestureDyShared", void 0);
86
145
  _defineProperty(this, "isSheetExpanded", () => {
87
146
  return this.state.isExpanded;
88
147
  });
89
148
  _defineProperty(this, "expandBottomSheet", () => {
90
149
  const targetHeight = Math.min(this.expandedHeight, SCREEN_HEIGHT);
150
+ const callback = () => {
151
+ this.updateState({
152
+ isExpanded: true,
153
+ lastGestureDy: 0
154
+ });
155
+ this.invokeEventCallback('onExpand', [null, this]);
156
+ };
91
157
 
92
- // For drag and settle behavior, we need to reset translateY to 0 when expanding
158
+ // Reset drag settle value immediately on UI thread
159
+ this.lastGestureDyShared.value = 0;
93
160
  if (this.props.enabledragsettle) {
94
- Animated.parallel([Animated.timing(this.state.sheetHeight, {
95
- toValue: targetHeight,
161
+ // Synchronize both animations to complete together
162
+ this.sheetHeight.value = withTiming(targetHeight, {
96
163
  duration: this.animationDuration,
97
- useNativeDriver: false
98
- }), Animated.timing(this.state.translateY, {
99
- toValue: 0,
164
+ easing: Easing.out(Easing.ease)
165
+ });
166
+ this.translateY.value = withTiming(0, {
100
167
  duration: this.animationDuration,
101
- useNativeDriver: false
102
- })]).start();
168
+ easing: Easing.out(Easing.ease)
169
+ }, finished => {
170
+ if (finished) {
171
+ runOnJS(callback)();
172
+ }
173
+ });
103
174
  } else {
104
- // Original behavior for non drag-and-settle mode
105
- Animated.timing(this.state.sheetHeight, {
106
- toValue: targetHeight,
175
+ // Only animate height for non-drag-settle mode
176
+ this.sheetHeight.value = withTiming(targetHeight, {
107
177
  duration: this.animationDuration,
108
- useNativeDriver: false
109
- }).start();
178
+ easing: Easing.out(Easing.ease)
179
+ }, finished => {
180
+ if (finished) {
181
+ runOnJS(callback)();
182
+ }
183
+ });
110
184
  }
111
- this.updateState({
112
- isExpanded: true,
113
- lastGestureDy: 0 // Reset to start from top when expanded
114
- });
115
185
  });
116
186
  _defineProperty(this, "collapseBottomSheet", () => {
117
- Animated.parallel([Animated.timing(this.state.translateY, {
118
- toValue: 0,
119
- // Keep sheet open
187
+ const callback = () => {
188
+ this.updateState({
189
+ isExpanded: false,
190
+ lastGestureDy: 0
191
+ });
192
+ this.invokeEventCallback('onCollapse', [null, this]);
193
+ };
194
+
195
+ // Reset drag settle value immediately on UI thread
196
+ this.lastGestureDyShared.value = 0;
197
+ this.translateY.value = withTiming(0, {
120
198
  duration: this.animationDuration,
121
- useNativeDriver: false
122
- }), Animated.timing(this.state.sheetHeight, {
123
- //use bottom sheet minimum height if disableswipedownclose is set to true or use calcluated height
124
- toValue: this.calculatedHeight,
199
+ easing: Easing.out(Easing.ease)
200
+ });
201
+ this.sheetHeight.value = withTiming(this.calculatedHeight, {
125
202
  duration: this.animationDuration,
126
- useNativeDriver: false
127
- })]).start();
128
- this.updateState({
129
- isExpanded: false,
130
- lastGestureDy: 0 // Reset to start from original position when collapsed
203
+ easing: Easing.out(Easing.ease)
204
+ }, finished => {
205
+ if (finished) {
206
+ runOnJS(callback)();
207
+ }
131
208
  });
132
209
  });
133
210
  _defineProperty(this, "handleBackPress", () => {
@@ -160,23 +237,25 @@ export default class WmBottomsheet extends BaseComponent {
160
237
  // Leave some buffer space for the drag handle and safe area
161
238
  const bufferSpace = (Platform.OS === 'ios' ? this.topInset : this.statusBarHeight) + 20;
162
239
  const adjustedHeight = availableHeight - bufferSpace;
163
- // Animate the sheet height adjustment
164
- Animated.timing(this.state.sheetHeight, {
165
- toValue: adjustedHeight,
166
- duration: 100,
167
- useNativeDriver: false
168
- }).start();
240
+ if (this.sheetHeight && Platform.OS == 'android' && this.props.modal) {
241
+ // Use platform-specific keyboard animation duration for smooth synchronization
242
+ this.sheetHeight.value = withTiming(adjustedHeight, {
243
+ duration: this.keyboardAnimationDuration,
244
+ easing: Easing.out(Easing.ease)
245
+ });
246
+ }
169
247
  this.updateState({
170
248
  keyboardHeight: keyboardHeight
171
249
  });
172
250
  });
173
251
  _defineProperty(this, "onKeyboardHide", () => {
174
- // Restore the original sheet height when keyboard hides
175
- Animated.timing(this.state.sheetHeight, {
176
- toValue: this.state.isExpanded ? this.expandedHeight : this.calculatedHeight,
177
- duration: 100,
178
- useNativeDriver: false
179
- }).start();
252
+ if (this.sheetHeight && Platform.OS == 'android' && this.props.modal) {
253
+ // Use platform-specific keyboard animation duration for smooth synchronization
254
+ this.sheetHeight.value = withTiming(this.state.isExpanded ? this.expandedHeight : this.calculatedHeight, {
255
+ duration: this.keyboardAnimationDuration,
256
+ easing: Easing.out(Easing.ease)
257
+ });
258
+ }
180
259
  this.updateState({
181
260
  keyboardHeight: 0
182
261
  });
@@ -187,21 +266,21 @@ export default class WmBottomsheet extends BaseComponent {
187
266
  this.updateState({
188
267
  lastGestureDy: 0
189
268
  });
269
+ if (this.lastGestureDyShared) {
270
+ this.lastGestureDyShared.value = 0;
271
+ }
190
272
  }
191
-
192
- // New drag and settle behavior
193
273
  if (this.props.enabledragsettle && gestureState.dy > 0) {
194
- // Get current translateY value and settle the sheet at this position
195
- const currentTranslateY = this.state.translateY._value || 0;
196
- // If dragged too far down, close the sheet
274
+ var _this$translateY;
275
+ const currentTranslateY = ((_this$translateY = this.translateY) === null || _this$translateY === void 0 ? void 0 : _this$translateY.value) || 0;
197
276
  if (gestureState.vy > 0.5 && !this.props.disableswipedownclose) {
198
277
  this.closeSheet();
199
278
  return;
200
279
  }
201
- // Settle at the current position without changing the sheet height
202
- // The sheet height should remain constant to maintain proper positioning
203
- this.state.translateY.setValue(currentTranslateY);
204
- // This ensures subsequent drags start from the current position
280
+ if (this.translateY && this.lastGestureDyShared) {
281
+ this.translateY.value = currentTranslateY;
282
+ this.lastGestureDyShared.value = currentTranslateY;
283
+ }
205
284
  this.updateState({
206
285
  isExpanded: false,
207
286
  lastGestureDy: currentTranslateY
@@ -210,24 +289,33 @@ export default class WmBottomsheet extends BaseComponent {
210
289
  }
211
290
  if (gestureState.dy > 0) {
212
291
  if (this.state.isExpanded || this.props.disableswipedownclose) {
213
- // Expand the bottom sheet threshold is 25% of the fully expanded height
214
- // If the user swipe distance is below the threshold, revert to the original sheet height
215
292
  if (gestureState.dy < this.expandedHeight / 4 || this.props.disableswipedownclose) {
293
+ var _this$sheetHeight;
216
294
  let sheetMinimumHeight = this.props.bottomsheetminimumheight || 0.1;
217
- Animated.parallel([Animated.timing(this.state.translateY, {
218
- toValue: 0,
219
- // Keep sheet open
220
- duration: this.animationDuration,
221
- useNativeDriver: false
222
- }), Animated.timing(this.state.sheetHeight, {
223
- //use bottom sheet minimum height if disableswipedownclose is set to true or use calcluated height
224
- toValue: this.props.disableswipedownclose ? sheetMinimumHeight * SCREEN_HEIGHT : this.calculatedHeight,
225
- duration: this.animationDuration,
226
- useNativeDriver: false
227
- })]).start();
228
- this.updateState({
229
- isExpanded: false
230
- });
295
+ const targetHeight = this.props.disableswipedownclose ? sheetMinimumHeight * SCREEN_HEIGHT : this.calculatedHeight;
296
+ const currentHeight = ((_this$sheetHeight = this.sheetHeight) === null || _this$sheetHeight === void 0 ? void 0 : _this$sheetHeight.value) || this.expandedHeight;
297
+ const distance = Math.abs(currentHeight - targetHeight);
298
+ const duration = this.getAnimationDuration(distance, gestureState.vy);
299
+ const callback = () => {
300
+ this.updateState({
301
+ isExpanded: false
302
+ });
303
+ this.invokeEventCallback('onCollapse', [null, this]);
304
+ };
305
+ if (this.translateY && this.sheetHeight) {
306
+ this.translateY.value = withTiming(0, {
307
+ duration: duration,
308
+ easing: Easing.out(Easing.ease)
309
+ });
310
+ this.sheetHeight.value = withTiming(targetHeight, {
311
+ duration: duration,
312
+ easing: Easing.out(Easing.ease)
313
+ }, finished => {
314
+ if (finished) {
315
+ runOnJS(callback)();
316
+ }
317
+ });
318
+ }
231
319
  } else if ((gestureState.dy > this.expandedHeight / 4 || gestureState.vy > 0.5) && !this.props.disableswipedownclose) {
232
320
  this.closeSheet();
233
321
  }
@@ -254,10 +342,16 @@ export default class WmBottomsheet extends BaseComponent {
254
342
  // Only handle the gesture if we're at the top and swiping down
255
343
  return gestureState.dy > 0 && this.state.scrollOffset <= 0;
256
344
  },
345
+ onPanResponderGrant: () => {
346
+ // Cancel any ongoing animations when user starts dragging
347
+ if (this.translateY) {
348
+ cancelAnimation(this.translateY);
349
+ }
350
+ },
257
351
  onPanResponderMove: (_, gestureState) => {
258
- if (gestureState.dy > 0) {
259
- const newTranslateY = Math.max(0, this.state.lastGestureDy + gestureState.dy);
260
- this.state.translateY.setValue(newTranslateY);
352
+ if (gestureState.dy > 0 && this.translateY && this.lastGestureDyShared) {
353
+ const newTranslateY = Math.max(0, this.lastGestureDyShared.value + gestureState.dy);
354
+ this.translateY.value = newTranslateY;
261
355
  }
262
356
  },
263
357
  onPanResponderRelease: (_, gestureState) => {
@@ -271,18 +365,28 @@ export default class WmBottomsheet extends BaseComponent {
271
365
  _defineProperty(this, "dragHandlePanResponder", PanResponder.create({
272
366
  onStartShouldSetPanResponder: () => true,
273
367
  onMoveShouldSetPanResponder: () => true,
368
+ onPanResponderGrant: () => {
369
+ // Cancel any ongoing animations when user starts dragging
370
+ if (this.translateY) {
371
+ cancelAnimation(this.translateY);
372
+ }
373
+ // Reset the expand flag
374
+ this.isDragHandleExpanding = false;
375
+ },
274
376
  onPanResponderMove: (_, gestureState) => {
275
- if (gestureState.dy > 0) {
276
- // Handle downward drag
277
- const newTranslateY = Math.max(0, this.state.lastGestureDy + gestureState.dy);
278
- this.state.translateY.setValue(newTranslateY);
279
- } else if (gestureState.dy < 0 && this.props.expand && this.props.bottomsheetheightratio !== 1) {
280
- // Handle upward drag - expand to full height
281
- // Allow expansion to full screen height
377
+ if (gestureState.dy > 0 && this.translateY && this.lastGestureDyShared) {
378
+ const newTranslateY = Math.max(0, this.lastGestureDyShared.value + gestureState.dy);
379
+ this.translateY.value = newTranslateY;
380
+ // Reset expand flag if dragging down
381
+ this.isDragHandleExpanding = false;
382
+ } else if (gestureState.dy < -50 && this.props.expand && this.props.bottomsheetheightratio !== 1 && !this.isDragHandleExpanding && !this.state.isExpanded) {
383
+ // Only trigger expand once with threshold of -50px upward drag
384
+ this.isDragHandleExpanding = true;
282
385
  this.expandBottomSheet();
283
386
  }
284
387
  },
285
388
  onPanResponderRelease: (_, gestureState) => {
389
+ this.isDragHandleExpanding = false;
286
390
  this.handleSwipeGesture(gestureState);
287
391
  }
288
392
  }));
@@ -295,20 +399,32 @@ export default class WmBottomsheet extends BaseComponent {
295
399
  });
296
400
  });
297
401
  _defineProperty(this, "openSheet", () => {
298
- this.updateState({
299
- lastGestureDy: 0
300
- });
301
- Animated.parallel([Animated.timing(this.state.translateY, {
302
- toValue: 0,
303
- duration: this.animationDuration,
304
- useNativeDriver: false
305
- }), Animated.timing(this.state.backdropOpacity, {
306
- toValue: 1,
307
- duration: this.animationDuration,
308
- useNativeDriver: false
309
- })]).start(() => {
402
+ const callback = () => {
403
+ this.updateState({
404
+ lastGestureDy: 0
405
+ });
310
406
  this.invokeEventCallback('onOpened', [null, this]);
311
- });
407
+ };
408
+
409
+ // Reset drag settle value immediately on UI thread
410
+ if (this.lastGestureDyShared) {
411
+ this.lastGestureDyShared.value = 0;
412
+ }
413
+ if (this.translateY && this.backdropOpacity) {
414
+ this.translateY.value = withTiming(0, {
415
+ duration: this.animationDuration,
416
+ easing: Easing.out(Easing.ease)
417
+ }, finished => {
418
+ if (finished) {
419
+ runOnJS(callback)();
420
+ }
421
+ });
422
+ // Backdrop animation synchronized with sheet animation
423
+ this.backdropOpacity.value = withTiming(1, {
424
+ duration: this.animationDuration,
425
+ easing: Easing.out(Easing.ease)
426
+ });
427
+ }
312
428
  });
313
429
  _defineProperty(this, "handleClose", () => {
314
430
  this.updateState({
@@ -317,28 +433,39 @@ export default class WmBottomsheet extends BaseComponent {
317
433
  this.invokeEventCallback('onClose', [null, this]);
318
434
  });
319
435
  _defineProperty(this, "closeSheet", () => {
320
- Animated.parallel([Animated.timing(this.state.translateY, {
321
- toValue: SCREEN_HEIGHT,
322
- duration: this.animationDuration,
323
- useNativeDriver: false
324
- }), Animated.timing(this.state.backdropOpacity, {
325
- toValue: 0,
326
- duration: this.animationDuration,
327
- useNativeDriver: false
328
- })]).start(() => {
329
- requestAnimationFrame(() => {
330
- this.state.sheetHeight.setValue(this.calculatedHeight);
331
- this.updateState({
332
- isExpanded: false,
333
- localModalsOpened: []
334
- });
335
- this.handleClose();
436
+ const callback = () => {
437
+ // Reset sheet height after close
438
+ if (this.sheetHeight) {
439
+ this.sheetHeight.value = this.calculatedHeight;
440
+ }
441
+ this.updateState({
442
+ isExpanded: false,
443
+ localModalsOpened: []
336
444
  });
337
- });
445
+ this.handleClose();
446
+ };
447
+ if (this.translateY && this.backdropOpacity) {
448
+ this.translateY.value = withTiming(SCREEN_HEIGHT, {
449
+ duration: this.animationDuration,
450
+ easing: Easing.out(Easing.ease)
451
+ }, finished => {
452
+ if (finished) {
453
+ runOnJS(callback)();
454
+ }
455
+ });
456
+ // Backdrop animation synchronized with sheet animation
457
+ this.backdropOpacity.value = withTiming(0, {
458
+ duration: this.animationDuration,
459
+ easing: Easing.out(Easing.ease)
460
+ });
461
+ }
338
462
  });
339
463
  _defineProperty(this, "closeSheetImmediate", () => {
340
- this.state.translateY.setValue(SCREEN_HEIGHT);
341
- this.state.backdropOpacity.setValue(0);
464
+ if (this.translateY && this.backdropOpacity && this.lastGestureDyShared) {
465
+ this.translateY.value = SCREEN_HEIGHT;
466
+ this.backdropOpacity.value = 0;
467
+ this.lastGestureDyShared.value = 0;
468
+ }
342
469
  this.updateState({
343
470
  lastGestureDy: 0,
344
471
  isExpanded: false,
@@ -346,44 +473,58 @@ export default class WmBottomsheet extends BaseComponent {
346
473
  localModalsOpened: []
347
474
  });
348
475
  requestAnimationFrame(() => {
349
- this.state.sheetHeight.setValue(this.calculatedHeight);
476
+ if (this.sheetHeight) {
477
+ this.sheetHeight.value = this.calculatedHeight;
478
+ }
350
479
  });
351
480
  });
481
+ // Class methods to prevent recreation on every render
482
+ _defineProperty(this, "handleBackdropPress", () => {
483
+ if (this.props.autoclose !== 'disabled') {
484
+ this.closeSheet();
485
+ }
486
+ });
487
+ _defineProperty(this, "handleDragHandlePress", () => {
488
+ this.invokeEventCallback('onDraghandleiconclick', [null, this]);
489
+ });
352
490
  _defineProperty(this, "renderContent", props => {
491
+ // Don't render if shared values aren't initialized yet
492
+ if (!this.translateY || !this.backdropOpacity || !this.sheetHeight || !this.lastGestureDyShared) {
493
+ return null;
494
+ }
353
495
  return /*#__PURE__*/React.createElement(SafeAreaInsetsContext.Consumer, null, (insets = {
354
496
  top: 0,
355
497
  bottom: 0,
356
498
  left: 0,
357
499
  right: 0
358
500
  }) => {
359
- this.topInset = (insets === null || insets === void 0 ? void 0 : insets.top) || 0;
501
+ // Store topInset for later use (avoid mutation during render)
502
+ const topInset = (insets === null || insets === void 0 ? void 0 : insets.top) || 0;
503
+ // Update the instance variable outside of render cycle
504
+ if (this.topInset !== topInset) {
505
+ requestAnimationFrame(() => {
506
+ this.topInset = topInset;
507
+ });
508
+ }
360
509
  return /*#__PURE__*/React.createElement(View, _extends({
361
510
  style: this.styles.root
362
- }, this.getTestProps('keyboardview')), this._background, /*#__PURE__*/React.createElement(TouchableWithoutFeedback, {
363
- onPress: () => props.autoclose !== 'disabled' ? this.closeSheet() : null
364
- }, /*#__PURE__*/React.createElement(Animated.View, _extends({
365
- style: [this.styles.backdrop, {
366
- opacity: this.state.backdropOpacity
367
- }]
368
- }, this.getTestProps('backdrop'), getAccessibilityProps(AccessibilityWidgetType.BOTTOMSHEET, props)))), /*#__PURE__*/React.createElement(Animated.View, _extends({
369
- style: [this.styles.container, {
370
- height: this.state.sheetHeight,
371
- transform: [{
372
- translateY: this.state.translateY
373
- }]
374
- }]
375
- }, this.panResponder.panHandlers), /*#__PURE__*/React.createElement(View, _extends({
376
- style: this.styles.dragHandleContainer
377
- }, this.dragHandlePanResponder.panHandlers), /*#__PURE__*/React.createElement(Pressable, {
378
- onPress: () => this.invokeEventCallback('onDraghandleiconclick', [null, this])
379
- }, /*#__PURE__*/React.createElement(View, _extends({
380
- style: this.styles.dragIconHandle
381
- }, this.getTestProps('draghandle'))))), /*#__PURE__*/React.createElement(ScrollView, _extends({
511
+ }, this.getTestProps('keyboardview')), this._background, /*#__PURE__*/React.createElement(AnimatedBottomsheetContent, {
512
+ translateY: this.translateY,
513
+ backdropOpacity: this.backdropOpacity,
514
+ sheetHeight: this.sheetHeight,
515
+ lastGestureDy: this.lastGestureDyShared,
516
+ styles: this.styles,
517
+ props: props,
518
+ panHandlers: this.panResponder.panHandlers,
519
+ dragHandlePanHandlers: this.dragHandlePanResponder.panHandlers,
520
+ onBackdropPress: this.handleBackdropPress,
521
+ onDragHandlePress: this.handleDragHandlePress,
522
+ getTestProps: this.getTestProps.bind(this),
523
+ enabledragsettle: props.enabledragsettle
524
+ }, contentStyle => /*#__PURE__*/React.createElement(ScrollView, _extends({
382
525
  ref: this.state.scrollViewRef,
383
526
  style: this.styles.sheetContentContainer,
384
- contentContainerStyle: [this.styles.sheetScrollContent, props.enabledragsettle && this.state.lastGestureDy > 0 && {
385
- paddingBottom: this.state.lastGestureDy
386
- }],
527
+ contentContainerStyle: [this.styles.sheetScrollContent],
387
528
  alwaysBounceVertical: false,
388
529
  alwaysBounceHorizontal: false,
389
530
  bounces: false,
@@ -391,10 +532,14 @@ export default class WmBottomsheet extends BaseComponent {
391
532
  scrollEventThrottle: 16,
392
533
  onScroll: this.handleScroll,
393
534
  nestedScrollEnabled: true,
394
- scrollEnabled: true
535
+ scrollEnabled: !props.issticky && (!props.disablescrollonrest || this.state.isExpanded)
395
536
  }, this.getTestProps('scorllview')), props.enablemodalsupport ? /*#__PURE__*/React.createElement(ModalProvider, {
396
537
  value: this.sheetModalService
397
- }, props.children) : props.children)), props.enablemodalsupport && this.state.localModalsOpened && this.state.localModalsOpened.map((o, i) => /*#__PURE__*/React.createElement(View, {
538
+ }, /*#__PURE__*/React.createElement(Animated.View, {
539
+ style: contentStyle
540
+ }, props.children)) : /*#__PURE__*/React.createElement(Animated.View, {
541
+ style: contentStyle
542
+ }, props.children))), props.enablemodalsupport && this.state.localModalsOpened && this.state.localModalsOpened.map((o, i) => /*#__PURE__*/React.createElement(View, {
398
543
  key: (o.name || '') + i,
399
544
  onStartShouldSetResponder: () => true,
400
545
  onResponderEnd: () => o.isModal && this.sheetModalService.hideModal(o),
@@ -425,14 +570,21 @@ export default class WmBottomsheet extends BaseComponent {
425
570
  this.expandedHeight -= this.defaultTopInset;
426
571
  }
427
572
  }
428
- this.state.sheetHeight.setValue(this.calculatedHeight);
573
+
574
+ // Initialize shared values in constructor using makeMutable (not hooks)
575
+ // makeMutable can be called outside of React components
576
+ this.translateY = makeMutable(SCREEN_HEIGHT);
577
+ this.backdropOpacity = makeMutable(0);
578
+ this.sheetHeight = makeMutable(this.calculatedHeight);
579
+ this.lastGestureDyShared = makeMutable(0);
429
580
  this.updateState({
430
581
  isBottomsheetVisible: this.props.showonrender || false
431
582
  });
432
- if (this.state.isBottomsheetVisible) {
433
- this.openSheet();
434
- } else {
435
- this.closeSheetImmediate();
583
+
584
+ // Initialize values immediately to prevent flicker
585
+ if (this.props.showonrender) {
586
+ this.translateY.value = 0;
587
+ this.backdropOpacity.value = 1;
436
588
  }
437
589
 
438
590
  // Local ModalService for content rendered inside Bottomsheet
@@ -467,6 +619,14 @@ export default class WmBottomsheet extends BaseComponent {
467
619
  }
468
620
  componentDidMount() {
469
621
  super.componentDidMount();
622
+
623
+ // Trigger animation after mount if showonrender is true
624
+ if (this.state.isBottomsheetVisible) {
625
+ // Use requestAnimationFrame to ensure animation happens after initial render
626
+ requestAnimationFrame(() => {
627
+ this.openSheet();
628
+ });
629
+ }
470
630
  if (Platform.OS === 'android') {
471
631
  BackHandler.addEventListener('hardwareBackPress', this.handleBackPress);
472
632
  }
@@ -478,13 +638,19 @@ export default class WmBottomsheet extends BaseComponent {
478
638
  if (Platform.OS === 'android') {
479
639
  BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
480
640
  }
481
- this.keyboardDidShowListener.remove();
482
- this.keyboardDidHideListener.remove();
641
+ if (this.keyboardDidShowListener) {
642
+ this.keyboardDidShowListener.remove();
643
+ }
644
+ if (this.keyboardDidHideListener) {
645
+ this.keyboardDidHideListener.remove();
646
+ }
483
647
  }
484
648
  componentDidUpdate(prevProps) {
485
649
  if (prevProps.bottomsheetheightratio !== this.props.bottomsheetheightratio) {
486
650
  this.calculatedHeight = this.calculateSheetHeight(this.props.bottomsheetheightratio);
487
- this.state.sheetHeight.setValue(this.calculatedHeight);
651
+ if (this.sheetHeight) {
652
+ this.sheetHeight.value = this.calculatedHeight;
653
+ }
488
654
  }
489
655
  }
490
656
  onPropertyChange(name, $new, $old) {
@@ -523,12 +689,12 @@ export default class WmBottomsheet extends BaseComponent {
523
689
  this.closeSheet();
524
690
  }
525
691
  },
526
- statusBarTranslucent: true
692
+ statusBarTranslucent: false
527
693
  }, /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
528
694
  style: {
529
695
  flex: 1
530
696
  },
531
- behavior: Platform.OS === 'ios' ? 'padding' : undefined,
697
+ behavior: 'padding',
532
698
  keyboardVerticalOffset: Platform.OS === 'ios' ? 0 : undefined
533
699
  }, this.renderContent(props)));
534
700
  } else {