@wavemaker/app-rn-runtime 11.14.1-22.647453 → 11.14.1-22.647491

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.
@@ -5,14 +5,44 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
5
5
  import React, { createRef } from 'react';
6
6
  import { BaseComponent, BaseComponentState } from '@wavemaker/app-rn-runtime/core/base.component';
7
7
  import { View, PanResponder, Dimensions, TouchableWithoutFeedback, Platform, StatusBar, BackHandler, KeyboardAvoidingView, Keyboard, Modal, Pressable } from 'react-native';
8
- import { ScrollView } from 'react-native-gesture-handler';
8
+ import { Gesture, GestureDetector, GestureHandlerRootView, ScrollView } from 'react-native-gesture-handler';
9
9
  import Animated, { useAnimatedStyle, withTiming, runOnJS, Easing, makeMutable, cancelAnimation } from 'react-native-reanimated';
10
10
  import WmBottomsheetProps from './bottomsheet.props';
11
11
  import { DEFAULT_CLASS } from './bottomsheet.styles';
12
12
  import { createSkeleton } from '../skeleton/skeleton.component';
13
13
  import { AccessibilityWidgetType, getAccessibilityProps } from '@wavemaker/app-rn-runtime/core/accessibility';
14
14
  import { ModalProvider } from '@wavemaker/app-rn-runtime/core/modal.service';
15
- import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
15
+ import { SafeAreaInsetsContext, SafeAreaView } from 'react-native-safe-area-context';
16
+
17
+ // Web-only: Runs all bottom sheet animations on the JS thread (sets useNativeDriver to false)
18
+ // Prevents errors on web where native driver animations are not supported
19
+ // Web - Animated api is used from animation
20
+ if (Platform.OS === 'web') {
21
+ try {
22
+ const RN = require('react-native');
23
+ const RNAnimated = RN && RN.Animated;
24
+ if (RNAnimated && !RNAnimated.__wmPatchedNoNativeDriver) {
25
+ const wrap = name => {
26
+ const original = RNAnimated[name];
27
+ if (typeof original === 'function') {
28
+ RNAnimated[name] = (value, config) => {
29
+ const patched = {
30
+ ...(config || {}),
31
+ useNativeDriver: false
32
+ };
33
+ return original(value, patched);
34
+ };
35
+ }
36
+ };
37
+ wrap('timing');
38
+ wrap('spring');
39
+ wrap('decay');
40
+ RNAnimated.__wmPatchedNoNativeDriver = true;
41
+ }
42
+ } catch (_) {
43
+ // noop
44
+ }
45
+ }
16
46
  const {
17
47
  height: SCREEN_HEIGHT
18
48
  } = Dimensions.get('screen');
@@ -44,8 +74,32 @@ const AnimatedBottomsheetContent = ({
44
74
  onBackdropPress,
45
75
  onDragHandlePress,
46
76
  getTestProps,
47
- enabledragsettle
77
+ enabledragsettle,
78
+ scrollRef,
79
+ containerScrollRef,
80
+ configurePanGesture
48
81
  }) => {
82
+ // Simple RNGH GestureDetector attached to the same view as the PanResponder (panHandlers).
83
+ // No thresholds/validation: logs translationY directly during pan.
84
+ const panGesture = React.useMemo(() => {
85
+ // Create base Pan gesture
86
+ const pan = Gesture.Pan().runOnJS(true);
87
+
88
+ // Add external gestures for ScrollViews (container widget scrollview)
89
+ if (scrollRef && containerScrollRef) {
90
+ pan.simultaneousWithExternalGesture(scrollRef, containerScrollRef);
91
+ } else if (scrollRef) {
92
+ pan.simultaneousWithExternalGesture(scrollRef);
93
+ } else if (containerScrollRef) {
94
+ pan.simultaneousWithExternalGesture(containerScrollRef);
95
+ }
96
+
97
+ // Apply custom logic from parent BottomSheet class
98
+ if (configurePanGesture) {
99
+ configurePanGesture(pan);
100
+ }
101
+ return pan;
102
+ }, [scrollRef, containerScrollRef, configurePanGesture]);
49
103
  const backdropAnimatedStyle = useAnimatedStyle(() => ({
50
104
  opacity: backdropOpacity.value
51
105
  }));
@@ -67,15 +121,18 @@ const AnimatedBottomsheetContent = ({
67
121
  onPress: onBackdropPress
68
122
  }, /*#__PURE__*/React.createElement(Animated.View, _extends({
69
123
  style: [styles.backdrop, backdropAnimatedStyle]
70
- }, getTestProps('backdrop'), getAccessibilityProps(AccessibilityWidgetType.BOTTOMSHEET, props)))), /*#__PURE__*/React.createElement(Animated.View, _extends({
124
+ }, getTestProps('backdrop'), getAccessibilityProps(AccessibilityWidgetType.BOTTOMSHEET, props)))), /*#__PURE__*/React.createElement(Animated.View, {
71
125
  style: [styles.container, containerAnimatedStyle]
72
- }, panHandlers), /*#__PURE__*/React.createElement(View, _extends({
126
+ // {...panHandlers}
127
+ }, /*#__PURE__*/React.createElement(View, _extends({
73
128
  style: styles.dragHandleContainer
74
129
  }, dragHandlePanHandlers), /*#__PURE__*/React.createElement(Pressable, {
75
130
  onPress: onDragHandlePress
76
131
  }, /*#__PURE__*/React.createElement(View, _extends({
77
132
  style: styles.dragIconHandle
78
- }, getTestProps('draghandle'))))), children(contentStyle)));
133
+ }, getTestProps('draghandle'))))), /*#__PURE__*/React.createElement(GestureDetector, {
134
+ gesture: panGesture
135
+ }, children(contentStyle))));
79
136
  };
80
137
  export default class WmBottomsheet extends BaseComponent {
81
138
  // Helper method to calculate animation duration based on distance and velocity
@@ -138,6 +195,9 @@ export default class WmBottomsheet extends BaseComponent {
138
195
  _defineProperty(this, "isIosKeyboardHeightSet", false);
139
196
  _defineProperty(this, "sheetModalService", void 0);
140
197
  _defineProperty(this, "isDragHandleExpanding", false);
198
+ //container widget scrollview ref and y offset value
199
+ _defineProperty(this, "containerscrollViewRef", null);
200
+ _defineProperty(this, "containerscrollYoffset", 0);
141
201
  // Reanimated shared values - created once and reused
142
202
  _defineProperty(this, "translateY", void 0);
143
203
  _defineProperty(this, "backdropOpacity", void 0);
@@ -292,6 +352,20 @@ export default class WmBottomsheet extends BaseComponent {
292
352
  if (this.state.isExpanded || this.props.disableswipedownclose) {
293
353
  if (gestureState.dy < this.expandedHeight / 4 || this.props.disableswipedownclose) {
294
354
  var _this$sheetHeight;
355
+ //reseting bottom sheet scrollview offset value to fix scrollview automatic scroll issue while collpsing the bottom sheet
356
+ setTimeout(() => {
357
+ var _this$state$scrollVie;
358
+ if ((_this$state$scrollVie = this.state.scrollViewRef) !== null && _this$state$scrollVie !== void 0 && _this$state$scrollVie.current) {
359
+ this.state.scrollViewRef.current.scrollTo({
360
+ x: 0,
361
+ y: 0,
362
+ animated: false
363
+ });
364
+ this.updateState({
365
+ scrollOffset: 0
366
+ });
367
+ }
368
+ }, this.animationDuration);
295
369
  let sheetMinimumHeight = this.props.bottomsheetminimumheight || 0.1;
296
370
  const targetHeight = this.props.disableswipedownclose ? sheetMinimumHeight * SCREEN_HEIGHT : this.calculatedHeight;
297
371
  const currentHeight = ((_this$sheetHeight = this.sheetHeight) === null || _this$sheetHeight === void 0 ? void 0 : _this$sheetHeight.value) || this.expandedHeight;
@@ -333,13 +407,60 @@ export default class WmBottomsheet extends BaseComponent {
333
407
  }
334
408
  }
335
409
  });
410
+ _defineProperty(this, "configurePanGesture", pan => {
411
+ pan.enabled(true).onUpdate(event => {
412
+ // ← Add : any
413
+ const gestureState = {
414
+ dy: event.translationY,
415
+ vy: event.velocityY,
416
+ moveX: event.x,
417
+ moveY: event.y,
418
+ vx: event.velocityX
419
+ };
420
+ if (gestureState.dy > 0 && this.translateY && this.lastGestureDyShared && this.state.scrollOffset <= 0 && this.containerscrollYoffset <= 0) {
421
+ const newTranslateY = Math.max(0, this.lastGestureDyShared.value + gestureState.dy);
422
+ this.translateY.value = newTranslateY;
423
+ // Reset expand flag if dragging down
424
+ this.isDragHandleExpanding = false;
425
+ } else if (gestureState.dy < 0 && this.props.expand && this.props.bottomsheetheightratio !== 1 && !this.isDragHandleExpanding && !this.state.isExpanded && this.props.disablescrollonrest) {
426
+ // Only trigger expand once with threshold of -50px upward drag
427
+ this.isDragHandleExpanding = true;
428
+ this.expandBottomSheet();
429
+ }
430
+ // ... rest of logic
431
+ }).onEnd(event => {
432
+ // ← Add : any
433
+ const gestureState = {
434
+ dy: event.translationY,
435
+ vy: event.velocityY,
436
+ moveX: event.x,
437
+ moveY: event.y,
438
+ vx: event.velocityX
439
+ };
440
+ if (gestureState.dy > 0 && this.state.scrollOffset <= 0 && this.containerscrollYoffset <= 0) {
441
+ this.handleSwipeGesture(gestureState);
442
+ }
443
+ }).onFinalize((event, success) => {
444
+ // ← Add types
445
+ if (!success) {
446
+ this.openSheet();
447
+ }
448
+ });
449
+ return pan;
450
+ });
336
451
  // panResponder for bottom sheet scroll view
337
452
  _defineProperty(this, "panResponder", PanResponder.create({
338
453
  onStartShouldSetPanResponder: (_, gestureState) => {
454
+ if (this.props.disablescrollonrest && !this.state.isExpanded) {
455
+ return true;
456
+ }
339
457
  // Only handle the gesture if we're at the top and swiping down
340
458
  return gestureState.dy > 0 && this.state.scrollOffset <= 0;
341
459
  },
342
460
  onMoveShouldSetPanResponder: (_, gestureState) => {
461
+ if (this.props.disablescrollonrest && !this.state.isExpanded) {
462
+ return Math.abs(gestureState.dy) > 2;
463
+ }
343
464
  // Only handle the gesture if we're at the top and swiping down
344
465
  return gestureState.dy > 0 && this.state.scrollOffset <= 0;
345
466
  },
@@ -353,6 +474,12 @@ export default class WmBottomsheet extends BaseComponent {
353
474
  if (gestureState.dy > 0 && this.translateY && this.lastGestureDyShared) {
354
475
  const newTranslateY = Math.max(0, this.lastGestureDyShared.value + gestureState.dy);
355
476
  this.translateY.value = newTranslateY;
477
+ // Reset expand flag if dragging down
478
+ this.isDragHandleExpanding = false;
479
+ } else if (gestureState.dy < 0 && this.props.expand && this.props.bottomsheetheightratio !== 1 && !this.isDragHandleExpanding && !this.state.isExpanded) {
480
+ // Only trigger expand once with threshold of -50px upward drag
481
+ this.isDragHandleExpanding = true;
482
+ this.expandBottomSheet();
356
483
  }
357
484
  },
358
485
  onPanResponderRelease: (_, gestureState) => {
@@ -441,8 +568,10 @@ export default class WmBottomsheet extends BaseComponent {
441
568
  }
442
569
  this.updateState({
443
570
  isExpanded: false,
444
- localModalsOpened: []
571
+ localModalsOpened: [],
572
+ scrollOffset: 0
445
573
  });
574
+ this.containerscrollYoffset = 0;
446
575
  this.handleClose();
447
576
  };
448
577
  if (this.translateY && this.backdropOpacity) {
@@ -501,14 +630,21 @@ export default class WmBottomsheet extends BaseComponent {
501
630
  }) => {
502
631
  // Store topInset for later use (avoid mutation during render)
503
632
  const topInset = (insets === null || insets === void 0 ? void 0 : insets.top) || 0;
633
+ const bottomInset = (insets === null || insets === void 0 ? void 0 : insets.bottom) || 0;
504
634
  // Update the instance variable outside of render cycle
505
635
  if (this.topInset !== topInset) {
506
636
  requestAnimationFrame(() => {
507
637
  this.topInset = topInset;
508
638
  });
509
639
  }
640
+ const absoluteStyle = {
641
+ top: 0,
642
+ left: 0,
643
+ right: 0
644
+ };
645
+ const rootStyle = props.modal ? [this.styles.root, absoluteStyle] : this.styles.root;
510
646
  return /*#__PURE__*/React.createElement(View, _extends({
511
- style: this.styles.root
647
+ style: rootStyle
512
648
  }, this.getTestProps('keyboardview')), this._background, /*#__PURE__*/React.createElement(AnimatedBottomsheetContent, {
513
649
  translateY: this.translateY,
514
650
  backdropOpacity: this.backdropOpacity,
@@ -521,8 +657,21 @@ export default class WmBottomsheet extends BaseComponent {
521
657
  onBackdropPress: this.handleBackdropPress,
522
658
  onDragHandlePress: this.handleDragHandlePress,
523
659
  getTestProps: this.getTestProps.bind(this),
524
- enabledragsettle: props.enabledragsettle
525
- }, contentStyle => /*#__PURE__*/React.createElement(ScrollView, _extends({
660
+ enabledragsettle: props.enabledragsettle,
661
+ scrollRef: this.state.scrollViewRef,
662
+ containerScrollRef: this.containerscrollViewRef,
663
+ configurePanGesture: this.configurePanGesture
664
+ }, contentStyle => props.issticky ? props.enablemodalsupport ? /*#__PURE__*/React.createElement(ModalProvider, {
665
+ value: this.sheetModalService
666
+ }, /*#__PURE__*/React.createElement(Animated.View, {
667
+ style: [contentStyle, this.styles.sheetContentContainer, {
668
+ overflow: 'hidden'
669
+ }]
670
+ }, props.children)) : /*#__PURE__*/React.createElement(Animated.View, {
671
+ style: [contentStyle, this.styles.sheetContentContainer, {
672
+ overflow: 'hidden'
673
+ }]
674
+ }, props.children) : /*#__PURE__*/React.createElement(ScrollView, _extends({
526
675
  ref: this.state.scrollViewRef,
527
676
  style: this.styles.sheetContentContainer,
528
677
  contentContainerStyle: [this.styles.sheetScrollContent],
@@ -540,7 +689,9 @@ export default class WmBottomsheet extends BaseComponent {
540
689
  style: contentStyle
541
690
  }, props.children)) : /*#__PURE__*/React.createElement(Animated.View, {
542
691
  style: contentStyle
543
- }, props.children))), props.enablemodalsupport && this.state.localModalsOpened && this.state.localModalsOpened.map((o, i) => /*#__PURE__*/React.createElement(View, {
692
+ }, props.children))), Platform.OS === 'android' && !this.props.modal && bottomInset > 40 && /*#__PURE__*/React.createElement(SafeAreaView, {
693
+ edges: ['bottom']
694
+ }), props.enablemodalsupport && this.state.localModalsOpened && this.state.localModalsOpened.map((o, i) => /*#__PURE__*/React.createElement(View, {
544
695
  key: (o.name || '') + i,
545
696
  onStartShouldSetResponder: () => true,
546
697
  onResponderEnd: () => o.isModal && this.sheetModalService.hideModal(o),
@@ -556,7 +707,18 @@ export default class WmBottomsheet extends BaseComponent {
556
707
  });
557
708
  });
558
709
  this.calculatedHeight = this.calculateSheetHeight(_props.bottomsheetheightratio);
559
-
710
+ //container srollview ref
711
+ this.subscribe('containerScrollViewReady', ref => {
712
+ if (ref && ref.current && this.containerscrollViewRef !== ref) {
713
+ this.containerscrollViewRef = ref;
714
+ this.forceUpdate();
715
+ }
716
+ });
717
+ //container scrollview y offset value
718
+ this.subscribe('scroll', e => {
719
+ const offsetY = e.nativeEvent.contentOffset.y;
720
+ this.containerscrollYoffset = offsetY;
721
+ });
560
722
  // Use bottomsheetexpandedheightratio if provided, otherwise use expandedDefaultHeight
561
723
  const expandedRatio = _props.bottomsheetexpandedheightratio || this.expandedDefaultHeight;
562
724
  const effectiveExpandedRatio = Math.max(this.minimumExpandedHeight, Math.min(expandedRatio, this.maxHeight));
@@ -681,27 +843,51 @@ export default class WmBottomsheet extends BaseComponent {
681
843
  }
682
844
  renderWidget(props) {
683
845
  if (!this.state.isBottomsheetVisible) return null;
684
- if (props.modal) {
685
- return /*#__PURE__*/React.createElement(Modal, {
686
- visible: this.state.isBottomsheetVisible,
687
- transparent: true,
688
- animationType: "none",
689
- onRequestClose: () => {
690
- if (!this.props.disableswipedownclose && this.props.autoclose !== 'disabled') {
691
- this.closeSheet();
846
+ return /*#__PURE__*/React.createElement(SafeAreaInsetsContext.Consumer, null, (insets = {
847
+ top: 0,
848
+ bottom: 0,
849
+ left: 0,
850
+ right: 0
851
+ }) => {
852
+ // Use SafeAreaView on Android with button navigation to render the bottom sheet above the nav bar (when modal props is true)
853
+ // Button navigation is identified when bottom inset >= 40
854
+ const hasButtonNavigation = Platform.OS === 'android' && ((insets === null || insets === void 0 ? void 0 : insets.bottom) || 0) >= 40;
855
+ const wrapWithSafeArea = children => {
856
+ if (hasButtonNavigation) {
857
+ return /*#__PURE__*/React.createElement(SafeAreaView, {
858
+ style: {
859
+ flex: 1
860
+ }
861
+ }, children);
862
+ }
863
+ return children;
864
+ };
865
+ if (props.modal) {
866
+ return /*#__PURE__*/React.createElement(Modal, {
867
+ visible: this.state.isBottomsheetVisible,
868
+ transparent: true,
869
+ animationType: "none",
870
+ onRequestClose: () => {
871
+ if (!this.props.disableswipedownclose && this.props.autoclose !== 'disabled') {
872
+ this.closeSheet();
873
+ }
874
+ },
875
+ statusBarTranslucent: false
876
+ }, /*#__PURE__*/React.createElement(GestureHandlerRootView, {
877
+ style: {
878
+ flex: 1
692
879
  }
693
- },
694
- statusBarTranslucent: false
695
- }, /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
696
- style: {
697
- flex: 1
698
- },
699
- behavior: 'padding',
700
- keyboardVerticalOffset: Platform.OS === 'ios' ? 0 : undefined
701
- }, this.renderContent(props)));
702
- } else {
703
- return this.renderContent(props);
704
- }
880
+ }, wrapWithSafeArea(/*#__PURE__*/React.createElement(KeyboardAvoidingView, {
881
+ style: {
882
+ flex: 1
883
+ },
884
+ behavior: 'padding',
885
+ keyboardVerticalOffset: Platform.OS === 'ios' ? 0 : undefined
886
+ }, this.renderContent(props)))));
887
+ } else {
888
+ return this.renderContent(props);
889
+ }
890
+ });
705
891
  }
706
892
  }
707
893
  //# sourceMappingURL=bottomsheet.component.js.map