@lodev09/react-native-true-sheet 3.9.6 → 3.9.8

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.
@@ -11,6 +11,7 @@ interface TrueSheetContainerViewDelegate {
11
11
  val eventDispatcher: EventDispatcher?
12
12
  fun containerViewContentDidChangeSize(width: Int, height: Int)
13
13
  fun containerViewContentDidScroll()
14
+ fun containerViewScrollViewDidChange()
14
15
  fun containerViewHeaderDidChangeSize(width: Int, height: Int)
15
16
  fun containerViewFooterDidChangeSize(width: Int, height: Int)
16
17
  }
@@ -124,6 +125,10 @@ class TrueSheetContainerView(reactContext: ThemedReactContext) :
124
125
  delegate?.containerViewContentDidScroll()
125
126
  }
126
127
 
128
+ override fun contentViewScrollViewDidChange() {
129
+ delegate?.containerViewScrollViewDidChange()
130
+ }
131
+
127
132
  override fun headerViewDidChangeSize(width: Int, height: Int) {
128
133
  headerHeight = height
129
134
  delegate?.containerViewHeaderDidChangeSize(width, height)
@@ -18,6 +18,7 @@ import com.lodev09.truesheet.utils.isDescendantOf
18
18
  interface TrueSheetContentViewDelegate {
19
19
  fun contentViewDidChangeSize(width: Int, height: Int)
20
20
  fun contentViewDidScroll()
21
+ fun contentViewScrollViewDidChange()
21
22
  }
22
23
 
23
24
  /**
@@ -32,7 +33,6 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
32
33
  private var lastHeight = 0
33
34
 
34
35
  private var pinnedScrollView: ScrollView? = null
35
- private var cachedScrollView: ScrollView? = null
36
36
  private var originalScrollViewPaddingBottom: Int = 0
37
37
  private var bottomInset: Int = 0
38
38
 
@@ -45,6 +45,22 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
45
45
  keyboardScrollOffset = value?.getDouble("keyboardScrollOffset")?.toFloat()?.dpToPx() ?: 0f
46
46
  }
47
47
 
48
+ override fun addView(child: View?, index: Int) {
49
+ super.addView(child, index)
50
+ checkScrollViewChanged()
51
+ }
52
+
53
+ override fun removeViewAt(index: Int) {
54
+ super.removeViewAt(index)
55
+ checkScrollViewChanged()
56
+ }
57
+
58
+ private fun checkScrollViewChanged() {
59
+ if (pinnedScrollView == null || pinnedScrollView?.isDescendantOf(this) == false) {
60
+ delegate?.contentViewScrollViewDidChange()
61
+ }
62
+ }
63
+
48
64
  override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
49
65
  super.onSizeChanged(w, h, oldw, oldh)
50
66
 
@@ -61,65 +77,63 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
61
77
  return
62
78
  }
63
79
 
64
- this.bottomInset = bottomInset
65
- applyScrollViewBottomInset()
66
- }
80
+ // Check if pinned scroll view is still valid (still in view hierarchy)
81
+ if (pinnedScrollView != null && pinnedScrollView?.isDescendantOf(this) == false) {
82
+ clearScrollable()
83
+ }
67
84
 
68
- private fun applyScrollViewBottomInset() {
69
- val scrollView = findScrollView(this)
85
+ // Already set up with same inset and valid scroll view
86
+ if (pinnedScrollView != null && this.bottomInset == bottomInset) {
87
+ return
88
+ }
70
89
 
71
- if (scrollView != pinnedScrollView) {
72
- // Clean up previous scroll view
73
- pinnedScrollView?.setOnScrollChangeListener(null as View.OnScrollChangeListener?)
74
- pinnedScrollView?.setPadding(
75
- pinnedScrollView!!.paddingLeft,
76
- pinnedScrollView!!.paddingTop,
77
- pinnedScrollView!!.paddingRight,
78
- originalScrollViewPaddingBottom
79
- )
90
+ val scrollView = findScrollView(this) ?: return
80
91
 
92
+ // Only capture originals on first pin
93
+ if (pinnedScrollView == null) {
94
+ originalScrollViewPaddingBottom = scrollView.paddingBottom
81
95
  pinnedScrollView = scrollView
82
- originalScrollViewPaddingBottom = scrollView?.paddingBottom ?: 0
83
96
 
84
- scrollView?.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
97
+ scrollView.setOnScrollChangeListener { _, _, scrollY, _, oldScrollY ->
85
98
  if (scrollY != oldScrollY) {
86
99
  delegate?.contentViewDidScroll()
87
100
  }
88
101
  }
89
102
  }
90
103
 
91
- scrollView?.let {
92
- it.clipToPadding = false
93
- it.setPadding(
94
- it.paddingLeft,
95
- it.paddingTop,
96
- it.paddingRight,
97
- originalScrollViewPaddingBottom + bottomInset
98
- )
104
+ this.bottomInset = bottomInset
105
+
106
+ setScrollViewPaddingBottom(originalScrollViewPaddingBottom + bottomInset)
107
+
108
+ // If keyboard is currently showing, re-apply the keyboard inset to the new ScrollView
109
+ val keyboardHeight = keyboardObserver?.currentHeight ?: 0
110
+ if (keyboardHeight > 0) {
111
+ setScrollViewPaddingBottom(originalScrollViewPaddingBottom + keyboardHeight)
99
112
  }
100
113
  }
101
114
 
115
+ private fun setScrollViewPaddingBottom(paddingBottom: Int) {
116
+ val scrollView = pinnedScrollView ?: return
117
+ scrollView.clipToPadding = false
118
+ scrollView.setPadding(
119
+ scrollView.paddingLeft,
120
+ scrollView.paddingTop,
121
+ scrollView.paddingRight,
122
+ paddingBottom
123
+ )
124
+ }
125
+
102
126
  fun clearScrollable() {
103
127
  pinnedScrollView?.setOnScrollChangeListener(null as View.OnScrollChangeListener?)
104
- pinnedScrollView?.setPadding(
105
- pinnedScrollView!!.paddingLeft,
106
- pinnedScrollView!!.paddingTop,
107
- pinnedScrollView!!.paddingRight,
108
- originalScrollViewPaddingBottom
109
- )
128
+ setScrollViewPaddingBottom(originalScrollViewPaddingBottom)
110
129
  pinnedScrollView = null
111
- cachedScrollView = null
112
130
  originalScrollViewPaddingBottom = 0
113
131
  bottomInset = 0
114
132
  }
115
133
 
116
134
  fun findScrollView(): ScrollView? {
117
- // Return cached if still valid (attached and descendant of this view)
118
- cachedScrollView?.let {
119
- if (it.isAttachedToWindow && it.isDescendantOf(this)) return it
120
- cachedScrollView = null
121
- }
122
- return findScrollView(this as View).also { cachedScrollView = it }
135
+ if (pinnedScrollView != null) return pinnedScrollView
136
+ return findScrollView(this as View)
123
137
  }
124
138
 
125
139
  private fun findScrollView(view: View): ScrollView? {
@@ -175,15 +189,7 @@ class TrueSheetContentView(private val reactContext: ThemedReactContext) : React
175
189
  val scrollView = pinnedScrollView ?: return
176
190
 
177
191
  val totalBottomInset = if (keyboardHeight > 0) keyboardHeight else bottomInset
178
- val newPaddingBottom = originalScrollViewPaddingBottom + totalBottomInset
179
-
180
- scrollView.clipToPadding = false
181
- scrollView.setPadding(
182
- scrollView.paddingLeft,
183
- scrollView.paddingTop,
184
- scrollView.paddingRight,
185
- newPaddingBottom
186
- )
192
+ setScrollViewPaddingBottom(originalScrollViewPaddingBottom + totalBottomInset)
187
193
 
188
194
  // Trigger a scroll to force update
189
195
  scrollView.post {
@@ -592,6 +592,13 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
592
592
  viewController.commitKeyboardDetent()
593
593
  }
594
594
 
595
+ // When the ScrollView changes (e.g. conditional remount), re-pin the new ScrollView
596
+ // and request layout so BottomSheetBehavior re-discovers the nested scrolling child.
597
+ override fun containerViewScrollViewDidChange() {
598
+ setupScrollable()
599
+ viewController.sheetView?.requestLayout()
600
+ }
601
+
595
602
  override fun containerViewHeaderDidChangeSize(width: Int, height: Int) {
596
603
  updateSheetIfNeeded()
597
604
  }
@@ -7,6 +7,7 @@ import android.view.MotionEvent
7
7
  import android.view.ViewConfiguration
8
8
  import android.widget.ScrollView
9
9
  import androidx.coordinatorlayout.widget.CoordinatorLayout
10
+ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
10
11
  import com.facebook.react.uimanager.PointerEvents
11
12
  import com.facebook.react.uimanager.ReactPointerEventsView
12
13
  import com.lodev09.truesheet.utils.isDescendantOf
@@ -65,15 +66,10 @@ class TrueSheetCoordinatorLayout(context: Context) :
65
66
  get() = PointerEvents.BOX_NONE
66
67
 
67
68
  /**
68
- * Clears stale `nestedScrollingChildRef` from BottomSheetBehavior and forces re-discovery.
69
+ * Clears stale `nestedScrollingChildRef` from BottomSheetBehavior.
69
70
  *
70
- * `BottomSheetBehavior.onLayoutChild` calls `findScrollingChild()` which traverses the
71
- * entire sheet subtree. The cached `nestedScrollingChildRef` can become stale when:
72
- * 1. A child sheet with a ScrollView is dismissed and its ScrollView returns to this hierarchy
73
- * 2. A ScrollView is conditionally removed and re-added (e.g. React conditional rendering)
74
- *
75
- * When stale (GC'd target or view no longer in sheet), we clear the ref and request layout
76
- * so `onLayoutChild` re-runs `findScrollingChild()` to discover the current ScrollView.
71
+ * The cached `nestedScrollingChildRef` can become stale when a child sheet
72
+ * with a ScrollView is dismissed and its ScrollView returns to this hierarchy.
77
73
  */
78
74
  private fun clearStaleNestedScrollingChildRef() {
79
75
  val sheet = delegate?.findSheetView() ?: return
@@ -86,7 +82,6 @@ class TrueSheetCoordinatorLayout(context: Context) :
86
82
  val view = ref.get()
87
83
  if (view == null || !view.isDescendantOf(sheet)) {
88
84
  ref.clear()
89
- sheet.requestLayout()
90
85
  }
91
86
  } catch (_: Exception) {}
92
87
  }
@@ -104,7 +99,9 @@ class TrueSheetCoordinatorLayout(context: Context) :
104
99
  }
105
100
 
106
101
  val scrollView = delegate?.findScrollView()
102
+ val hasRefreshControl = scrollView?.parent is SwipeRefreshLayout
107
103
  val cannotScroll = scrollView != null &&
104
+ !hasRefreshControl &&
108
105
  scrollView.scrollY == 0 &&
109
106
  !scrollView.canScrollVertically(1)
110
107
 
@@ -15,18 +15,11 @@ NS_ASSUME_NONNULL_BEGIN
15
15
 
16
16
  @protocol TrueSheetContainerViewDelegate <NSObject>
17
17
 
18
- /**
19
- * Called when the container's content size changes
20
- * @param newSize The new size of the content
21
- */
22
18
  - (void)containerViewContentDidChangeSize:(CGSize)newSize;
19
+ - (void)containerViewScrollViewDidChange;
23
20
 
24
21
  @optional
25
22
 
26
- /**
27
- * Called when the header size changes
28
- * @param newSize The new size of the header
29
- */
30
23
  - (void)containerViewHeaderDidChangeSize:(CGSize)newSize;
31
24
 
32
25
  @end
@@ -175,8 +175,8 @@ using namespace facebook::react;
175
175
  [self.delegate containerViewContentDidChangeSize:newSize];
176
176
  }
177
177
 
178
- - (void)contentViewDidChangeChildren {
179
- [self setupScrollable];
178
+ - (void)contentViewScrollViewDidChange {
179
+ [self.delegate containerViewScrollViewDidChange];
180
180
  }
181
181
 
182
182
  #pragma mark - TrueSheetHeaderViewDelegate
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
22
22
  @protocol TrueSheetContentViewDelegate <NSObject>
23
23
 
24
24
  - (void)contentViewDidChangeSize:(CGSize)newSize;
25
- - (void)contentViewDidChangeChildren;
25
+ - (void)contentViewScrollViewDidChange;
26
26
 
27
27
  @end
28
28
 
@@ -57,29 +57,42 @@ using namespace facebook::react;
57
57
 
58
58
  - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
59
59
  [super mountChildComponentView:childComponentView index:index];
60
- [self.delegate contentViewDidChangeChildren];
60
+ [self checkScrollViewChanged];
61
61
  }
62
62
 
63
63
  - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
64
64
  [super unmountChildComponentView:childComponentView index:index];
65
- [self.delegate contentViewDidChangeChildren];
65
+ [self checkScrollViewChanged];
66
+ }
67
+
68
+ - (void)checkScrollViewChanged {
69
+ if (!_pinnedScrollView || ![_pinnedScrollView isDescendantOfView:self]) {
70
+ [self.delegate contentViewScrollViewDidChange];
71
+ }
66
72
  }
67
73
 
68
74
  #pragma mark - Scrollable
69
75
 
76
+ - (void)setScrollViewContentInset:(CGFloat)contentBottom indicatorInset:(CGFloat)indicatorBottom {
77
+ if (!_pinnedScrollView)
78
+ return;
79
+
80
+ UIEdgeInsets contentInset = _pinnedScrollView.scrollView.contentInset;
81
+ contentInset.bottom = contentBottom;
82
+ _pinnedScrollView.scrollView.contentInset = contentInset;
83
+
84
+ UIEdgeInsets indicatorInsets = _pinnedScrollView.scrollView.verticalScrollIndicatorInsets;
85
+ indicatorInsets.bottom = indicatorBottom;
86
+ _pinnedScrollView.scrollView.verticalScrollIndicatorInsets = indicatorInsets;
87
+ }
88
+
70
89
  - (void)clearScrollable {
71
90
  if (_pinnedScrollView) {
72
91
  CGRect frame = _pinnedScrollView.frame;
73
92
  frame.size.height = _originalScrollViewHeight;
74
93
  _pinnedScrollView.frame = frame;
75
94
 
76
- UIEdgeInsets contentInset = _pinnedScrollView.scrollView.contentInset;
77
- contentInset.bottom = 0;
78
- _pinnedScrollView.scrollView.contentInset = contentInset;
79
-
80
- UIEdgeInsets indicatorInsets = _pinnedScrollView.scrollView.verticalScrollIndicatorInsets;
81
- indicatorInsets.bottom = _originalIndicatorBottomInset;
82
- _pinnedScrollView.scrollView.verticalScrollIndicatorInsets = indicatorInsets;
95
+ [self setScrollViewContentInset:0 indicatorInset:_originalIndicatorBottomInset];
83
96
  }
84
97
  _pinnedScrollView = nil;
85
98
  _bottomInset = 0;
@@ -94,7 +107,6 @@ using namespace facebook::react;
94
107
  }
95
108
 
96
109
  // Check if pinned scroll view is still valid (still in view hierarchy)
97
- // This handles the case where content changes and the old scroll view is unmounted
98
110
  if (_pinnedScrollView && ![_pinnedScrollView isDescendantOfView:self]) {
99
111
  [self clearScrollable];
100
112
  }
@@ -120,13 +132,13 @@ using namespace facebook::react;
120
132
 
121
133
  [self updateScrollViewHeight];
122
134
 
123
- UIEdgeInsets contentInset = scrollView.scrollView.contentInset;
124
- contentInset.bottom = bottomInset;
125
- scrollView.scrollView.contentInset = contentInset;
135
+ [self setScrollViewContentInset:_bottomInset indicatorInset:_originalIndicatorBottomInset];
126
136
 
127
- UIEdgeInsets indicatorInsets = scrollView.scrollView.verticalScrollIndicatorInsets;
128
- indicatorInsets.bottom = _originalIndicatorBottomInset;
129
- scrollView.scrollView.verticalScrollIndicatorInsets = indicatorInsets;
137
+ // If keyboard is currently showing, re-apply the keyboard inset to the new ScrollView
138
+ CGFloat keyboardHeight = _keyboardObserver ? _keyboardObserver.currentHeight : 0;
139
+ if (keyboardHeight > 0) {
140
+ [self setScrollViewContentInset:keyboardHeight indicatorInset:_originalIndicatorBottomInset + keyboardHeight];
141
+ }
130
142
  }
131
143
 
132
144
  - (void)updateScrollViewHeight {
@@ -202,13 +214,8 @@ using namespace facebook::react;
202
214
  delay:0
203
215
  options:curve | UIViewAnimationOptionBeginFromCurrentState
204
216
  animations:^{
205
- UIEdgeInsets contentInset = self->_pinnedScrollView.scrollView.contentInset;
206
- contentInset.bottom = height;
207
- self->_pinnedScrollView.scrollView.contentInset = contentInset;
208
-
209
- UIEdgeInsets indicatorInsets = self->_pinnedScrollView.scrollView.verticalScrollIndicatorInsets;
210
- indicatorInsets.bottom = self->_originalIndicatorBottomInset + height;
211
- self->_pinnedScrollView.scrollView.verticalScrollIndicatorInsets = indicatorInsets;
217
+ [self setScrollViewContentInset:height
218
+ indicatorInset:self->_originalIndicatorBottomInset + height];
212
219
 
213
220
  if (firstResponder) {
214
221
  CGRect responderFrame = [firstResponder convertRect:firstResponder.bounds
@@ -229,13 +236,8 @@ using namespace facebook::react;
229
236
  delay:0
230
237
  options:curve | UIViewAnimationOptionBeginFromCurrentState
231
238
  animations:^{
232
- UIEdgeInsets contentInset = self->_pinnedScrollView.scrollView.contentInset;
233
- contentInset.bottom = self->_bottomInset;
234
- self->_pinnedScrollView.scrollView.contentInset = contentInset;
235
-
236
- UIEdgeInsets indicatorInsets = self->_pinnedScrollView.scrollView.verticalScrollIndicatorInsets;
237
- indicatorInsets.bottom = self->_originalIndicatorBottomInset;
238
- self->_pinnedScrollView.scrollView.verticalScrollIndicatorInsets = indicatorInsets;
239
+ [self setScrollViewContentInset:self->_bottomInset
240
+ indicatorInset:self->_originalIndicatorBottomInset];
239
241
  }
240
242
  completion:nil];
241
243
  }
@@ -574,6 +574,11 @@ using namespace facebook::react;
574
574
  [self setupSheetDetentsForSizeChange];
575
575
  }
576
576
 
577
+ // When the ScrollView changes (e.g. conditional remount), re-pin the new ScrollView.
578
+ - (void)containerViewScrollViewDidChange {
579
+ [_containerView setupScrollable];
580
+ }
581
+
577
582
  #pragma mark - TrueSheetViewControllerDelegate
578
583
 
579
584
  - (void)viewControllerWillPresentAtIndex:(NSInteger)index position:(CGFloat)position detent:(CGFloat)detent {
@@ -743,10 +743,35 @@ using namespace facebook::react;
743
743
  [_grabberView applyConfiguration];
744
744
  _grabberView.hidden = !showGrabber;
745
745
 
746
+ __weak __typeof(self) weakSelf = self;
747
+ _grabberView.onTap = ^{
748
+ [weakSelf handleGrabberTap];
749
+ };
750
+
746
751
  [self.view bringSubviewToFront:_grabberView];
747
752
  } else {
748
753
  self.sheet.prefersGrabberVisible = showGrabber;
749
754
  _grabberView.hidden = YES;
755
+ _grabberView.onTap = nil;
756
+ }
757
+ }
758
+
759
+ - (void)handleGrabberTap {
760
+ NSInteger detentCount = _detents.count;
761
+ if (detentCount == 0)
762
+ return;
763
+
764
+ NSInteger currentIndex = self.currentDetentIndex;
765
+ if (currentIndex < 0)
766
+ return;
767
+
768
+ NSInteger nextIndex = (currentIndex + 1) % detentCount;
769
+ if (nextIndex == 0 && detentCount == 1 && self.dismissible) {
770
+ [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
771
+ } else {
772
+ [self.sheet animateChanges:^{
773
+ [self resizeToDetentIndex:nextIndex];
774
+ }];
750
775
  }
751
776
  }
752
777
 
@@ -34,6 +34,9 @@ NS_ASSUME_NONNULL_BEGIN
34
34
  /// Whether the grabber color adapts to the background (default: YES)
35
35
  @property (nonatomic, strong, nullable) NSNumber *adaptive;
36
36
 
37
+ /// Called when the grabber is tapped
38
+ @property (nonatomic, copy, nullable) void (^onTap)(void);
39
+
37
40
  /// Adds the grabber view to a parent view with proper constraints
38
41
  - (void)addToView:(UIView *)parentView;
39
42
 
@@ -51,9 +51,11 @@ static const CGFloat kDefaultGrabberTopMargin = 5.0;
51
51
  #pragma mark - Setup
52
52
 
53
53
  - (void)setupView {
54
- self.userInteractionEnabled = NO;
55
54
  self.clipsToBounds = YES;
56
55
 
56
+ UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
57
+ [self addGestureRecognizer:tap];
58
+
57
59
  _vibrancyView = [[UIVisualEffectView alloc] initWithEffect:nil];
58
60
  _vibrancyView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
59
61
  [self addSubview:_vibrancyView];
@@ -64,6 +66,14 @@ static const CGFloat kDefaultGrabberTopMargin = 5.0;
64
66
  [_vibrancyView.contentView addSubview:_fillView];
65
67
  }
66
68
 
69
+ #pragma mark - Actions
70
+
71
+ - (void)handleTap {
72
+ if (_onTap) {
73
+ _onTap();
74
+ }
75
+ }
76
+
67
77
  #pragma mark - Public
68
78
 
69
79
  - (void)addToView:(UIView *)parentView {
@@ -24,6 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
24
24
  @interface TrueSheetKeyboardObserver : NSObject
25
25
 
26
26
  @property (nonatomic, weak, nullable) TrueSheetViewController *viewController;
27
+ @property (nonatomic, readonly) CGFloat currentHeight;
27
28
 
28
29
  - (void)addDelegate:(id<TrueSheetKeyboardObserverDelegate>)delegate;
29
30
  - (void)removeDelegate:(id<TrueSheetKeyboardObserverDelegate>)delegate;
@@ -14,6 +14,11 @@
14
14
 
15
15
  @implementation TrueSheetKeyboardObserver {
16
16
  NSHashTable<id<TrueSheetKeyboardObserverDelegate>> *_delegates;
17
+ CGFloat _currentHeight;
18
+ }
19
+
20
+ - (CGFloat)currentHeight {
21
+ return _currentHeight;
17
22
  }
18
23
 
19
24
  - (instancetype)init {
@@ -76,6 +81,8 @@
76
81
  CGRect keyboardFrameInWindow = [window convertRect:keyboardFrame fromWindow:nil];
77
82
  CGFloat keyboardHeight = MAX(0, window.bounds.size.height - keyboardFrameInWindow.origin.y);
78
83
 
84
+ _currentHeight = keyboardHeight;
85
+
79
86
  for (id<TrueSheetKeyboardObserverDelegate> delegate in _delegates) {
80
87
  if (keyboardHeight > 0) {
81
88
  [delegate keyboardWillShow:keyboardHeight duration:duration curve:curve];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lodev09/react-native-true-sheet",
3
- "version": "3.9.6",
3
+ "version": "3.9.8",
4
4
  "description": "The true native bottom sheet experience for your React Native Apps.",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",
@@ -185,10 +185,8 @@
185
185
  "publish": false
186
186
  },
187
187
  "hooks": {
188
- "before:init": [
189
- "yarn tidy",
190
- "yarn test"
191
- ]
188
+ "before:init": "yarn test",
189
+ "after:bump": "yarn tidy && sed -i '' 's/## Unreleased/## Unreleased\\n\\n## ${version}/' CHANGELOG.md"
192
190
  },
193
191
  "github": {
194
192
  "release": true,