@swmansion/react-native-bottom-sheet 0.7.0-next.5 → 0.7.0-next.7

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.
@@ -13,11 +13,12 @@ Pod::Spec.new do |s|
13
13
  s.platforms = { :ios => min_ios_version_supported }
14
14
  s.source = { :git => "https://github.com/software-mansion-labs/react-native-bottom-sheet.git", :tag => "#{s.version}" }
15
15
 
16
- s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
16
+ s.source_files = ["ios/**/*.{h,m,mm,cpp,swift}", "common/**/*.{h,cpp}"]
17
17
  s.private_header_files = "ios/**/*.h"
18
18
  s.swift_version = "5.0"
19
19
  s.pod_target_xcconfig = {
20
- "DEFINES_MODULE" => "YES"
20
+ "DEFINES_MODULE" => "YES",
21
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/common/cpp\""
21
22
  }
22
23
 
23
24
  install_modules_dependencies(s)
@@ -11,7 +11,9 @@ import android.widget.FrameLayout
11
11
  import androidx.dynamicanimation.animation.DynamicAnimation
12
12
  import androidx.dynamicanimation.animation.SpringAnimation
13
13
  import androidx.dynamicanimation.animation.SpringForce
14
+ import com.facebook.react.bridge.Arguments
14
15
  import com.facebook.react.uimanager.PointerEvents
16
+ import com.facebook.react.uimanager.StateWrapper
15
17
  import com.facebook.react.views.view.ReactViewGroup
16
18
  import kotlin.math.abs
17
19
 
@@ -27,6 +29,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
27
29
  // MARK: - Listener
28
30
 
29
31
  var listener: BottomSheetViewListener? = null
32
+ var stateWrapper: StateWrapper? = null
30
33
 
31
34
  // MARK: - State
32
35
 
@@ -48,6 +51,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
48
51
 
49
52
  // Touch tracking
50
53
  private var initialTouchY = 0f
54
+ private var initialTouchX = 0f
51
55
  private var lastTouchY = 0f
52
56
  private var activePointerId = MotionEvent.INVALID_POINTER_ID
53
57
 
@@ -129,6 +133,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
129
133
 
130
134
  if (activeAnimation != null || isPanning) return
131
135
  sheetContainer.translationY = translationY(targetIndex)
136
+ updateShadowState(sheetContainer.translationY)
132
137
  }
133
138
 
134
139
  private fun layoutSheetChildren() {
@@ -207,6 +212,19 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
207
212
  val maxHeight = detentSpecs.lastOrNull()?.height ?: height.toFloat()
208
213
  val ty = sheetContainer.translationY
209
214
  listener?.onPositionChange(((maxHeight - ty) / density).toDouble())
215
+ updateShadowState(ty)
216
+ }
217
+
218
+ private var lastShadowOffsetY = Float.NaN
219
+
220
+ private fun updateShadowState(translationY: Float) {
221
+ val offsetY = (translationY / density).toDouble()
222
+ if (offsetY.toFloat() == lastShadowOffsetY) return
223
+ lastShadowOffsetY = offsetY.toFloat()
224
+ val sw = stateWrapper ?: return
225
+ val map = Arguments.createMap()
226
+ map.putDouble("contentOffsetY", offsetY)
227
+ sw.updateState(map)
210
228
  }
211
229
 
212
230
  // MARK: - Choreographer (position tracking during animation)
@@ -282,12 +300,13 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
282
300
 
283
301
  override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
284
302
  val sheetTop = sheetContainer.top + sheetContainer.translationY
285
- if (ev.y < sheetTop) {
303
+ if (ev.actionMasked == MotionEvent.ACTION_DOWN && ev.y < sheetTop) {
286
304
  return false
287
305
  }
288
306
 
289
307
  when (ev.actionMasked) {
290
308
  MotionEvent.ACTION_DOWN -> {
309
+ initialTouchX = ev.x
291
310
  initialTouchY = ev.y
292
311
  lastTouchY = ev.y
293
312
  activePointerId = ev.getPointerId(0)
@@ -296,10 +315,12 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
296
315
  if (activePointerId == MotionEvent.INVALID_POINTER_ID) return false
297
316
  val pointerIndex = ev.findPointerIndex(activePointerId)
298
317
  if (pointerIndex < 0) return false
318
+ val x = ev.getX(pointerIndex)
299
319
  val y = ev.getY(pointerIndex)
320
+ val dx = x - initialTouchX
300
321
  val dy = y - initialTouchY
301
322
 
302
- if (abs(dy) > touchSlop) {
323
+ if (abs(dy) > touchSlop && abs(dy) > abs(dx)) {
303
324
  if (!isAtMaxDraggable) {
304
325
  lastTouchY = y
305
326
  requestDisallowInterceptTouchEvent(false)
@@ -313,6 +334,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
313
334
  }
314
335
  }
315
336
  MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
337
+ initialTouchX = 0f
316
338
  activePointerId = MotionEvent.INVALID_POINTER_ID
317
339
  }
318
340
  }
@@ -321,7 +343,7 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
321
343
 
322
344
  override fun onTouchEvent(event: MotionEvent): Boolean {
323
345
  val sheetTop = sheetContainer.top + sheetContainer.translationY
324
- if (event.y < sheetTop) {
346
+ if (event.actionMasked == MotionEvent.ACTION_DOWN && event.y < sheetTop) {
325
347
  return false
326
348
  }
327
349
 
@@ -418,9 +440,12 @@ class BottomSheetView(context: Context) : ReactViewGroup(context) {
418
440
  hasLaidOut = false
419
441
  isPanning = false
420
442
  initialTouchY = 0f
443
+ initialTouchX = 0f
421
444
  lastTouchY = 0f
422
445
  activePointerId = MotionEvent.INVALID_POINTER_ID
423
446
  sheetContainer.translationY = 0f
424
447
  sheetContainer.removeAllViews()
448
+ stateWrapper = null
449
+ lastShadowOffsetY = Float.NaN
425
450
  }
426
451
  }
@@ -3,6 +3,8 @@ package com.swmansion.reactnativebottomsheet
3
3
  import android.view.View
4
4
  import com.facebook.react.bridge.ReadableArray
5
5
  import com.facebook.react.module.annotations.ReactModule
6
+ import com.facebook.react.uimanager.ReactStylesDiffMap
7
+ import com.facebook.react.uimanager.StateWrapper
6
8
  import com.facebook.react.uimanager.ThemedReactContext
7
9
  import com.facebook.react.uimanager.ViewGroupManager
8
10
  import com.facebook.react.uimanager.ViewManagerDelegate
@@ -63,6 +65,15 @@ class BottomSheetViewManager :
63
65
  parent.removeSheetChildAt(index)
64
66
  }
65
67
 
68
+ override fun updateState(
69
+ view: BottomSheetView,
70
+ props: ReactStylesDiffMap,
71
+ stateWrapper: StateWrapper?,
72
+ ): Any? {
73
+ view.stateWrapper = stateWrapper
74
+ return null
75
+ }
76
+
66
77
  override fun needsCustomLayoutForChildren(): Boolean = true
67
78
 
68
79
  override fun getExportedCustomDirectEventTypeConstants(): Map<String, Any> {
@@ -0,0 +1,78 @@
1
+ cmake_minimum_required(VERSION 3.13)
2
+ set(CMAKE_VERBOSE_MAKEFILE ON)
3
+
4
+ set(LIB_LITERAL ReactNativeBottomSheetSpec)
5
+ set(LIB_TARGET_NAME react_codegen_${LIB_LITERAL})
6
+
7
+ set(LIB_ANDROID_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
8
+ set(LIB_COMMON_DIR ${LIB_ANDROID_DIR}/../common/cpp)
9
+ set(LIB_ANDROID_GENERATED_JNI_DIR ${LIB_ANDROID_DIR}/build/generated/source/codegen/jni)
10
+ set(LIB_ANDROID_GENERATED_COMPONENTS_DIR ${LIB_ANDROID_GENERATED_JNI_DIR}/react/renderer/components/${LIB_LITERAL})
11
+
12
+ file(GLOB LIB_CUSTOM_SRCS CONFIGURE_DEPENDS ${LIB_COMMON_DIR}/react/renderer/components/${LIB_LITERAL}/*.cpp)
13
+ file(GLOB LIB_CODEGEN_SRCS CONFIGURE_DEPENDS ${LIB_ANDROID_GENERATED_JNI_DIR}/*.cpp ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}/*.cpp)
14
+
15
+ add_library(
16
+ ${LIB_TARGET_NAME}
17
+ SHARED
18
+ ${LIB_CUSTOM_SRCS}
19
+ ${LIB_CODEGEN_SRCS}
20
+ )
21
+
22
+ # Custom headers must come before generated headers so that our ShadowNodes.h
23
+ # and ComponentDescriptors.h take precedence over the codegen type aliases.
24
+ target_include_directories(
25
+ ${LIB_TARGET_NAME}
26
+ PUBLIC
27
+ ${LIB_COMMON_DIR}
28
+ ${LIB_ANDROID_GENERATED_JNI_DIR}
29
+ ${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
30
+ )
31
+
32
+ if (REACTNATIVE_MERGED_SO)
33
+ target_link_libraries(
34
+ ${LIB_TARGET_NAME}
35
+ fbjni
36
+ jsi
37
+ reactnative
38
+ )
39
+ else()
40
+ target_link_libraries(
41
+ ${LIB_TARGET_NAME}
42
+ fbjni
43
+ folly_runtime
44
+ glog
45
+ jsi
46
+ react_codegen_rncore
47
+ react_debug
48
+ react_nativemodule_core
49
+ react_render_core
50
+ react_render_debug
51
+ react_render_graphics
52
+ react_render_mapbuffer
53
+ react_render_componentregistry
54
+ react_utils
55
+ rrc_view
56
+ turbomodulejsijni
57
+ yoga
58
+ )
59
+ endif()
60
+
61
+ target_include_directories(
62
+ ${CMAKE_PROJECT_NAME}
63
+ PUBLIC
64
+ ${CMAKE_CURRENT_SOURCE_DIR}
65
+ )
66
+
67
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
68
+ target_compile_reactnative_options(${LIB_TARGET_NAME} PUBLIC)
69
+ else()
70
+ target_compile_options(
71
+ ${LIB_TARGET_NAME}
72
+ PRIVATE
73
+ -fexceptions
74
+ -frtti
75
+ -std=c++20
76
+ -Wall
77
+ )
78
+ endif()
@@ -0,0 +1,28 @@
1
+ #include "ShadowNodes.h"
2
+
3
+ #include <yoga/Yoga.h>
4
+
5
+ namespace facebook::react {
6
+
7
+ void BottomSheetViewShadowNode::adjustLayoutWithState() {
8
+ #ifdef ANDROID
9
+ ensureUnsealed();
10
+
11
+ auto state =
12
+ std::static_pointer_cast<const BottomSheetViewShadowNode::ConcreteState>(
13
+ getState());
14
+ auto stateData = state->getData();
15
+
16
+ auto adjustedStyle = getConcreteProps().yogaStyle;
17
+ auto newPaddingTop =
18
+ yoga::Style::Length::points(stateData.contentOffsetY);
19
+
20
+ if (adjustedStyle.padding(yoga::Edge::Top) != newPaddingTop) {
21
+ adjustedStyle.setPadding(yoga::Edge::Top, newPaddingTop);
22
+ yogaNode_.setStyle(adjustedStyle);
23
+ yogaNode_.setDirty(true);
24
+ }
25
+ #endif
26
+ }
27
+
28
+ } // namespace facebook::react
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+
3
+ #ifdef ANDROID
4
+ #include <folly/dynamic.h>
5
+ #include <react/renderer/mapbuffer/MapBuffer.h>
6
+ #include <react/renderer/mapbuffer/MapBufferBuilder.h>
7
+ #endif
8
+
9
+ namespace facebook::react {
10
+
11
+ class BottomSheetViewState final {
12
+ public:
13
+ BottomSheetViewState() = default;
14
+
15
+ #ifdef ANDROID
16
+ BottomSheetViewState(
17
+ const BottomSheetViewState& previousState,
18
+ folly::dynamic data)
19
+ : contentOffsetY(
20
+ static_cast<float>(data["contentOffsetY"].getDouble())) {}
21
+ #endif
22
+
23
+ float contentOffsetY{0};
24
+
25
+ #ifdef ANDROID
26
+ folly::dynamic getDynamic() const {
27
+ return folly::dynamic::object("contentOffsetY", contentOffsetY);
28
+ }
29
+
30
+ MapBuffer getMapBuffer() const {
31
+ return MapBufferBuilder::EMPTY();
32
+ }
33
+ #endif
34
+ };
35
+
36
+ } // namespace facebook::react
@@ -0,0 +1,19 @@
1
+ #pragma once
2
+
3
+ #include <react/renderer/components/ReactNativeBottomSheetSpec/ShadowNodes.h>
4
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
5
+
6
+ namespace facebook::react {
7
+
8
+ class BottomSheetViewComponentDescriptor final
9
+ : public ConcreteComponentDescriptor<BottomSheetViewShadowNode> {
10
+ using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
11
+
12
+ void adopt(ShadowNode& shadowNode) const override {
13
+ auto& node = static_cast<BottomSheetViewShadowNode&>(shadowNode);
14
+ node.adjustLayoutWithState();
15
+ ConcreteComponentDescriptor::adopt(shadowNode);
16
+ }
17
+ };
18
+
19
+ } // namespace facebook::react
@@ -0,0 +1,25 @@
1
+ #pragma once
2
+
3
+ #include <jsi/jsi.h>
4
+ #include <react/renderer/components/ReactNativeBottomSheetSpec/BottomSheetViewState.h>
5
+ #include <react/renderer/components/ReactNativeBottomSheetSpec/EventEmitters.h>
6
+ #include <react/renderer/components/ReactNativeBottomSheetSpec/Props.h>
7
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
8
+
9
+ namespace facebook::react {
10
+
11
+ JSI_EXPORT extern const char BottomSheetViewComponentName[];
12
+
13
+ class JSI_EXPORT BottomSheetViewShadowNode final
14
+ : public ConcreteViewShadowNode<
15
+ BottomSheetViewComponentName,
16
+ BottomSheetViewProps,
17
+ BottomSheetViewEventEmitter,
18
+ BottomSheetViewState> {
19
+ using ConcreteViewShadowNode::ConcreteViewShadowNode;
20
+
21
+ public:
22
+ void adjustLayoutWithState();
23
+ };
24
+
25
+ } // namespace facebook::react
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swmansion/react-native-bottom-sheet",
3
- "version": "0.7.0-next.5",
3
+ "version": "0.7.0-next.7",
4
4
  "description": "Provides bottom-sheet components for React Native.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -17,6 +17,7 @@
17
17
  "lib",
18
18
  "android",
19
19
  "ios",
20
+ "common",
20
21
  "cpp",
21
22
  "*.podspec",
22
23
  "react-native.config.js",
@@ -1 +1,11 @@
1
- module.exports = {};
1
+ module.exports = {
2
+ dependency: {
3
+ platforms: {
4
+ android: {
5
+ libraryName: 'ReactNativeBottomSheetSpec',
6
+ componentDescriptors: ['BottomSheetViewComponentDescriptor'],
7
+ cmakeListsPath: 'src/main/jni/CMakeLists.txt',
8
+ },
9
+ },
10
+ },
11
+ };