@lodev09/react-native-true-sheet 3.0.0-beta.0 → 3.0.0-beta.10
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.
- package/README.md +7 -21
- package/RNTrueSheet.podspec +5 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +58 -60
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContentView.kt +10 -18
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetFooterView.kt +76 -20
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderView.kt +38 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetHeaderViewManager.kt +21 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetPackage.kt +1 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +104 -146
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +315 -403
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +24 -11
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +116 -0
- package/android/src/main/java/com/lodev09/truesheet/utils/ScreenUtils.kt +33 -5
- package/android/src/main/jni/CMakeLists.txt +87 -0
- package/android/src/main/jni/TrueSheetSpec.h +17 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.cpp +46 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetViewState.h +42 -0
- package/ios/TrueSheetContainerView.h +23 -0
- package/ios/TrueSheetContainerView.mm +80 -13
- package/ios/TrueSheetContentView.h +9 -1
- package/ios/TrueSheetContentView.mm +102 -24
- package/ios/TrueSheetFooterView.mm +2 -2
- package/ios/TrueSheetHeaderView.h +29 -0
- package/ios/TrueSheetHeaderView.mm +60 -0
- package/ios/TrueSheetView.h +0 -16
- package/ios/TrueSheetView.mm +208 -190
- package/ios/TrueSheetViewController.h +17 -4
- package/ios/TrueSheetViewController.mm +197 -266
- package/ios/utils/ConversionUtil.h +24 -0
- package/ios/utils/ConversionUtil.mm +50 -0
- package/ios/utils/LayoutUtil.h +11 -1
- package/ios/utils/LayoutUtil.mm +32 -1
- package/lib/module/TrueSheet.js +30 -33
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
- package/lib/module/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +6 -8
- package/lib/typescript/src/TrueSheet.d.ts +0 -3
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +30 -43
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetContainerViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts +6 -0
- package/lib/typescript/src/fabric/TrueSheetHeaderViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +3 -6
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/package.json +9 -5
- package/react-native.config.js +5 -2
- package/src/TrueSheet.tsx +34 -31
- package/src/TrueSheet.types.ts +47 -61
- package/src/fabric/TrueSheetContainerViewNativeComponent.ts +1 -1
- package/src/fabric/TrueSheetHeaderViewNativeComponent.ts +8 -0
- package/src/fabric/TrueSheetViewNativeComponent.ts +6 -8
- package/android/src/main/java/com/lodev09/truesheet/events/SizeChangeEvent.kt +0 -27
- package/ios/events/OnSizeChangeEvent.h +0 -28
- package/ios/events/OnSizeChangeEvent.mm +0 -30
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
|
-
import android.graphics.Color
|
|
4
3
|
import android.view.WindowManager
|
|
5
4
|
import com.facebook.react.bridge.ReadableArray
|
|
6
5
|
import com.facebook.react.module.annotations.ReactModule
|
|
7
6
|
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
7
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
8
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
8
9
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
9
10
|
import com.facebook.react.uimanager.UIManagerHelper
|
|
10
11
|
import com.facebook.react.uimanager.ViewGroupManager
|
|
@@ -36,7 +37,7 @@ class TrueSheetViewManager :
|
|
|
36
37
|
|
|
37
38
|
override fun onAfterUpdateTransaction(view: TrueSheetView) {
|
|
38
39
|
super.onAfterUpdateTransaction(view)
|
|
39
|
-
view.
|
|
40
|
+
view.finalizeUpdates()
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
override fun addEventEmitters(reactContext: ThemedReactContext, view: TrueSheetView) {
|
|
@@ -44,6 +45,11 @@ class TrueSheetViewManager :
|
|
|
44
45
|
view.eventDispatcher = dispatcher
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
override fun updateState(view: TrueSheetView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
|
|
49
|
+
view.stateWrapper = stateWrapper
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
override fun getDelegate(): ViewManagerDelegate<TrueSheetView> = delegate
|
|
48
54
|
|
|
49
55
|
/**
|
|
@@ -61,8 +67,7 @@ class TrueSheetViewManager :
|
|
|
61
67
|
DragBeginEvent.EVENT_NAME to hashMapOf("registrationName" to DragBeginEvent.REGISTRATION_NAME),
|
|
62
68
|
DragChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DragChangeEvent.REGISTRATION_NAME),
|
|
63
69
|
DragEndEvent.EVENT_NAME to hashMapOf("registrationName" to DragEndEvent.REGISTRATION_NAME),
|
|
64
|
-
PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME)
|
|
65
|
-
SizeChangeEvent.EVENT_NAME to hashMapOf("registrationName" to SizeChangeEvent.REGISTRATION_NAME)
|
|
70
|
+
PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME)
|
|
66
71
|
)
|
|
67
72
|
|
|
68
73
|
// ==================== Props ====================
|
|
@@ -85,16 +90,14 @@ class TrueSheetViewManager :
|
|
|
85
90
|
view.setDetents(detents)
|
|
86
91
|
}
|
|
87
92
|
|
|
88
|
-
@ReactProp(name = "background", defaultInt =
|
|
93
|
+
@ReactProp(name = "background", defaultInt = 0)
|
|
89
94
|
override fun setBackground(view: TrueSheetView, color: Int) {
|
|
90
95
|
view.setSheetBackgroundColor(color)
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
@ReactProp(name = "cornerRadius", defaultDouble = -1.0)
|
|
94
99
|
override fun setCornerRadius(view: TrueSheetView, radius: Double) {
|
|
95
|
-
|
|
96
|
-
view.setCornerRadius(radius.dpToPx())
|
|
97
|
-
}
|
|
100
|
+
view.setCornerRadius(radius.dpToPx())
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
@ReactProp(name = "grabber", defaultBoolean = true)
|
|
@@ -112,9 +115,9 @@ class TrueSheetViewManager :
|
|
|
112
115
|
view.setDimmed(dimmed)
|
|
113
116
|
}
|
|
114
117
|
|
|
115
|
-
@ReactProp(name = "
|
|
116
|
-
override fun
|
|
117
|
-
view.
|
|
118
|
+
@ReactProp(name = "dimmedDetentIndex", defaultInt = 0)
|
|
119
|
+
override fun setDimmedDetentIndex(view: TrueSheetView, index: Int) {
|
|
120
|
+
view.setDimmedDetentIndex(index)
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
@ReactProp(name = "initialDetentIndex", defaultInt = -1)
|
|
@@ -154,6 +157,16 @@ class TrueSheetViewManager :
|
|
|
154
157
|
view.setEdgeToEdgeFullScreen(edgeToEdgeFullScreen)
|
|
155
158
|
}
|
|
156
159
|
|
|
160
|
+
@ReactProp(name = "scrollable", defaultBoolean = false)
|
|
161
|
+
override fun setScrollable(view: TrueSheetView, value: Boolean) {
|
|
162
|
+
// iOS-specific prop - no-op on Android
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@ReactProp(name = "pageSizing", defaultBoolean = true)
|
|
166
|
+
override fun setPageSizing(view: TrueSheetView, value: Boolean) {
|
|
167
|
+
// iOS-specific prop - no-op on Android
|
|
168
|
+
}
|
|
169
|
+
|
|
157
170
|
companion object {
|
|
158
171
|
const val REACT_CLASS = "TrueSheetView"
|
|
159
172
|
const val TAG_NAME = "TrueSheet"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
package com.lodev09.truesheet.core
|
|
2
|
+
|
|
3
|
+
import androidx.appcompat.app.AppCompatActivity
|
|
4
|
+
import androidx.fragment.app.Fragment
|
|
5
|
+
import androidx.fragment.app.FragmentManager
|
|
6
|
+
import com.facebook.react.bridge.ReactContext
|
|
7
|
+
|
|
8
|
+
private const val RN_SCREENS_PACKAGE = "com.swmansion.rnscreens"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Observes fragment lifecycle to detect react-native-screens modal presentation.
|
|
12
|
+
* Automatically notifies when modals are presented/dismissed.
|
|
13
|
+
*/
|
|
14
|
+
class RNScreensFragmentObserver(
|
|
15
|
+
private val reactContext: ReactContext,
|
|
16
|
+
private val onModalPresented: () -> Unit,
|
|
17
|
+
private val onModalDismissed: () -> Unit
|
|
18
|
+
) {
|
|
19
|
+
private var fragmentLifecycleCallback: FragmentManager.FragmentLifecycleCallbacks? = null
|
|
20
|
+
private val activeModalFragments: MutableSet<Fragment> = mutableSetOf()
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if there are active modal fragments being tracked.
|
|
24
|
+
*/
|
|
25
|
+
fun hasActiveModals(): Boolean = activeModalFragments.isNotEmpty()
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Start observing fragment lifecycle events.
|
|
29
|
+
*/
|
|
30
|
+
fun start() {
|
|
31
|
+
val activity = reactContext.currentActivity as? AppCompatActivity ?: return
|
|
32
|
+
val fragmentManager = activity.supportFragmentManager
|
|
33
|
+
|
|
34
|
+
fragmentLifecycleCallback = object : FragmentManager.FragmentLifecycleCallbacks() {
|
|
35
|
+
override fun onFragmentAttached(fm: FragmentManager, fragment: Fragment, context: android.content.Context) {
|
|
36
|
+
super.onFragmentAttached(fm, fragment, context)
|
|
37
|
+
|
|
38
|
+
if (isModalFragment(fragment)) {
|
|
39
|
+
activeModalFragments.add(fragment)
|
|
40
|
+
|
|
41
|
+
// Notify when the first modal is attached
|
|
42
|
+
if (activeModalFragments.size == 1) {
|
|
43
|
+
onModalPresented()
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override fun onFragmentStopped(fm: FragmentManager, fragment: Fragment) {
|
|
49
|
+
super.onFragmentStopped(fm, fragment)
|
|
50
|
+
|
|
51
|
+
if (activeModalFragments.contains(fragment)) {
|
|
52
|
+
activeModalFragments.remove(fragment)
|
|
53
|
+
|
|
54
|
+
// Notify when all modals are dismissed
|
|
55
|
+
if (activeModalFragments.isEmpty()) {
|
|
56
|
+
onModalDismissed()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallback!!, true)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Stop observing and cleanup.
|
|
67
|
+
*/
|
|
68
|
+
fun stop() {
|
|
69
|
+
fragmentLifecycleCallback?.let { callback ->
|
|
70
|
+
val activity = reactContext.currentActivity as? AppCompatActivity
|
|
71
|
+
activity?.supportFragmentManager?.unregisterFragmentLifecycleCallbacks(callback)
|
|
72
|
+
}
|
|
73
|
+
fragmentLifecycleCallback = null
|
|
74
|
+
activeModalFragments.clear()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
companion object {
|
|
78
|
+
/**
|
|
79
|
+
* Check if fragment is from react-native-screens.
|
|
80
|
+
*/
|
|
81
|
+
private fun isScreensFragment(fragment: Fragment): Boolean = fragment.javaClass.name.startsWith(RN_SCREENS_PACKAGE)
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if fragment is a react-native-screens modal (fullScreenModal, transparentModal, or formSheet).
|
|
85
|
+
* Uses reflection to check the fragment's screen.stackPresentation property.
|
|
86
|
+
*/
|
|
87
|
+
private fun isModalFragment(fragment: Fragment): Boolean {
|
|
88
|
+
val className = fragment.javaClass.name
|
|
89
|
+
|
|
90
|
+
if (!isScreensFragment(fragment)) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ScreenModalFragment is always a modal (used for formSheet with BottomSheetDialog)
|
|
95
|
+
if (className.contains("ScreenModalFragment")) {
|
|
96
|
+
return true
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// For ScreenStackFragment, check the screen's stackPresentation via reflection
|
|
100
|
+
try {
|
|
101
|
+
val getScreenMethod = fragment.javaClass.getMethod("getScreen")
|
|
102
|
+
val screen = getScreenMethod.invoke(fragment) ?: return false
|
|
103
|
+
|
|
104
|
+
val getStackPresentationMethod = screen.javaClass.getMethod("getStackPresentation")
|
|
105
|
+
val stackPresentation = getStackPresentationMethod.invoke(screen) ?: return false
|
|
106
|
+
|
|
107
|
+
val presentationName = stackPresentation.toString()
|
|
108
|
+
return presentationName == "MODAL" ||
|
|
109
|
+
presentationName == "TRANSPARENT_MODAL" ||
|
|
110
|
+
presentationName == "FORM_SHEET"
|
|
111
|
+
} catch (e: Exception) {
|
|
112
|
+
return false
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -89,14 +89,42 @@ object ScreenUtils {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* Get the
|
|
92
|
+
* Get the screen width
|
|
93
93
|
*
|
|
94
|
-
* @param
|
|
95
|
-
* @return
|
|
94
|
+
* @param context React context
|
|
95
|
+
* @return Screen width in pixels
|
|
96
96
|
*/
|
|
97
|
-
fun
|
|
97
|
+
fun getScreenWidth(context: ReactContext): Int {
|
|
98
|
+
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
|
99
|
+
|
|
100
|
+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
101
|
+
val windowMetrics = windowManager.currentWindowMetrics
|
|
102
|
+
windowMetrics.bounds.width()
|
|
103
|
+
} else {
|
|
104
|
+
val displayMetrics = DisplayMetrics()
|
|
105
|
+
@Suppress("DEPRECATION")
|
|
106
|
+
windowManager.defaultDisplay.getMetrics(displayMetrics)
|
|
107
|
+
displayMetrics.widthPixels
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Get the location of a view in screen coordinates
|
|
113
|
+
*
|
|
114
|
+
* @param view The view to get screen location for
|
|
115
|
+
* @return IntArray with [x, y] coordinates in screen space
|
|
116
|
+
*/
|
|
117
|
+
fun getScreenLocation(view: View): IntArray {
|
|
98
118
|
val location = IntArray(2)
|
|
99
119
|
view.getLocationOnScreen(location)
|
|
100
|
-
return location
|
|
120
|
+
return location
|
|
101
121
|
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Get the Y coordinate of a view in screen coordinates
|
|
125
|
+
*
|
|
126
|
+
* @param view The view to get screen Y coordinate for
|
|
127
|
+
* @return Y coordinate in screen space
|
|
128
|
+
*/
|
|
129
|
+
fun getScreenY(view: View): Int = getScreenLocation(view)[1]
|
|
102
130
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.13)
|
|
2
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
3
|
+
|
|
4
|
+
set(LIB_LITERAL TrueSheetSpec)
|
|
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 *.cpp ${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
|
+
target_include_directories(
|
|
23
|
+
${LIB_TARGET_NAME}
|
|
24
|
+
PUBLIC
|
|
25
|
+
.
|
|
26
|
+
${LIB_COMMON_DIR}
|
|
27
|
+
${LIB_ANDROID_GENERATED_JNI_DIR}
|
|
28
|
+
${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if (REACTNATIVE_MERGED_SO)
|
|
32
|
+
target_link_libraries(
|
|
33
|
+
${LIB_TARGET_NAME}
|
|
34
|
+
fbjni
|
|
35
|
+
jsi
|
|
36
|
+
reactnative
|
|
37
|
+
log
|
|
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
|
+
log
|
|
59
|
+
)
|
|
60
|
+
endif()
|
|
61
|
+
|
|
62
|
+
target_include_directories(
|
|
63
|
+
${CMAKE_PROJECT_NAME}
|
|
64
|
+
PUBLIC
|
|
65
|
+
${CMAKE_CURRENT_SOURCE_DIR}
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
|
|
69
|
+
target_compile_reactnative_options(${LIB_TARGET_NAME} PUBLIC)
|
|
70
|
+
else()
|
|
71
|
+
target_compile_options(
|
|
72
|
+
${LIB_TARGET_NAME}
|
|
73
|
+
PRIVATE
|
|
74
|
+
-fexceptions
|
|
75
|
+
-frtti
|
|
76
|
+
-std=c++20
|
|
77
|
+
-Wall
|
|
78
|
+
)
|
|
79
|
+
endif()
|
|
80
|
+
|
|
81
|
+
target_compile_options(
|
|
82
|
+
${LIB_TARGET_NAME}
|
|
83
|
+
PRIVATE
|
|
84
|
+
-Wpedantic
|
|
85
|
+
-Wno-gnu-zero-variadic-macro-arguments
|
|
86
|
+
-Wno-dollar-in-identifier-extension
|
|
87
|
+
)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <ReactCommon/JavaTurboModule.h>
|
|
4
|
+
#include <ReactCommon/TurboModule.h>
|
|
5
|
+
#include <jsi/jsi.h>
|
|
6
|
+
#include <react/renderer/components/TrueSheetSpec/TrueSheetViewComponentDescriptor.h>
|
|
7
|
+
|
|
8
|
+
namespace facebook {
|
|
9
|
+
namespace react {
|
|
10
|
+
|
|
11
|
+
JSI_EXPORT
|
|
12
|
+
std::shared_ptr<TurboModule> TrueSheetSpec_ModuleProvider(
|
|
13
|
+
const std::string &moduleName,
|
|
14
|
+
const JavaTurboModule::InitParams ¶ms);
|
|
15
|
+
|
|
16
|
+
} // namespace react
|
|
17
|
+
} // namespace facebook
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <react/renderer/components/TrueSheetSpec/TrueSheetViewShadowNode.h>
|
|
4
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
5
|
+
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Descriptor for <TrueSheetView> component.
|
|
10
|
+
*/
|
|
11
|
+
class TrueSheetViewComponentDescriptor final
|
|
12
|
+
: public ConcreteComponentDescriptor<TrueSheetViewShadowNode> {
|
|
13
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
14
|
+
|
|
15
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
16
|
+
auto &concreteShadowNode =
|
|
17
|
+
static_cast<TrueSheetViewShadowNode &>(shadowNode);
|
|
18
|
+
concreteShadowNode.adjustLayoutWithState();
|
|
19
|
+
|
|
20
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#include "TrueSheetViewShadowNode.h"
|
|
2
|
+
|
|
3
|
+
#include <yoga/style/StyleSizeLength.h>
|
|
4
|
+
|
|
5
|
+
namespace facebook::react {
|
|
6
|
+
|
|
7
|
+
extern const char TrueSheetViewComponentName[] = "TrueSheetView";
|
|
8
|
+
|
|
9
|
+
void TrueSheetViewShadowNode::adjustLayoutWithState() {
|
|
10
|
+
ensureUnsealed();
|
|
11
|
+
|
|
12
|
+
auto state = std::static_pointer_cast<
|
|
13
|
+
const TrueSheetViewShadowNode::ConcreteState>(getState());
|
|
14
|
+
auto stateData = state->getData();
|
|
15
|
+
|
|
16
|
+
// If container dimensions are set from native, override Yoga's dimensions
|
|
17
|
+
if (stateData.containerWidth > 0 || stateData.containerHeight > 0) {
|
|
18
|
+
auto &props = getConcreteProps();
|
|
19
|
+
yoga::Style adjustedStyle = props.yogaStyle;
|
|
20
|
+
auto currentStyle = yogaNode_.style();
|
|
21
|
+
bool needsUpdate = false;
|
|
22
|
+
|
|
23
|
+
// Set width if provided
|
|
24
|
+
if (stateData.containerWidth > 0) {
|
|
25
|
+
adjustedStyle.setDimension(yoga::Dimension::Width, yoga::StyleSizeLength::points(stateData.containerWidth));
|
|
26
|
+
if (adjustedStyle.dimension(yoga::Dimension::Width) != currentStyle.dimension(yoga::Dimension::Width)) {
|
|
27
|
+
needsUpdate = true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Set height if provided
|
|
32
|
+
if (stateData.containerHeight > 0) {
|
|
33
|
+
adjustedStyle.setDimension(yoga::Dimension::Height, yoga::StyleSizeLength::points(stateData.containerHeight));
|
|
34
|
+
if (adjustedStyle.dimension(yoga::Dimension::Height) != currentStyle.dimension(yoga::Dimension::Height)) {
|
|
35
|
+
needsUpdate = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (needsUpdate) {
|
|
40
|
+
yogaNode_.setStyle(adjustedStyle);
|
|
41
|
+
yogaNode_.setDirty(true);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/renderer/components/TrueSheetSpec/EventEmitters.h>
|
|
5
|
+
#include <react/renderer/components/TrueSheetSpec/Props.h>
|
|
6
|
+
#include <react/renderer/components/TrueSheetSpec/TrueSheetViewState.h>
|
|
7
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
+
|
|
9
|
+
namespace facebook::react {
|
|
10
|
+
|
|
11
|
+
JSI_EXPORT extern const char TrueSheetViewComponentName[];
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* `ShadowNode` for <TrueSheetView> component.
|
|
15
|
+
*/
|
|
16
|
+
class JSI_EXPORT TrueSheetViewShadowNode final
|
|
17
|
+
: public ConcreteViewShadowNode<
|
|
18
|
+
TrueSheetViewComponentName,
|
|
19
|
+
TrueSheetViewProps,
|
|
20
|
+
TrueSheetViewEventEmitter,
|
|
21
|
+
TrueSheetViewState> {
|
|
22
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
23
|
+
|
|
24
|
+
public:
|
|
25
|
+
void adjustLayoutWithState();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#include "TrueSheetViewState.h"
|
|
2
|
+
|
|
3
|
+
namespace facebook::react {
|
|
4
|
+
|
|
5
|
+
#ifdef ANDROID
|
|
6
|
+
folly::dynamic TrueSheetViewState::getDynamic() const {
|
|
7
|
+
return folly::dynamic::object("containerWidth", containerWidth)("containerHeight", containerHeight);
|
|
8
|
+
}
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#ifdef ANDROID
|
|
6
|
+
#include <folly/dynamic.h>
|
|
7
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
8
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
namespace facebook::react {
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* State for <TrueSheetView> component.
|
|
15
|
+
* Contains the container dimensions from native.
|
|
16
|
+
*/
|
|
17
|
+
class TrueSheetViewState final {
|
|
18
|
+
public:
|
|
19
|
+
using Shared = std::shared_ptr<const TrueSheetViewState>;
|
|
20
|
+
|
|
21
|
+
TrueSheetViewState() = default;
|
|
22
|
+
|
|
23
|
+
#ifdef ANDROID
|
|
24
|
+
TrueSheetViewState(
|
|
25
|
+
TrueSheetViewState const &previousState,
|
|
26
|
+
folly::dynamic data)
|
|
27
|
+
: containerWidth(static_cast<float>(data["containerWidth"].getDouble())),
|
|
28
|
+
containerHeight(static_cast<float>(data["containerHeight"].getDouble())) {}
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
float containerWidth{0};
|
|
32
|
+
float containerHeight{0};
|
|
33
|
+
|
|
34
|
+
#ifdef ANDROID
|
|
35
|
+
folly::dynamic getDynamic() const;
|
|
36
|
+
MapBuffer getMapBuffer() const {
|
|
37
|
+
return MapBufferBuilder::EMPTY();
|
|
38
|
+
}
|
|
39
|
+
#endif
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
} // namespace facebook::react
|
|
@@ -21,6 +21,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
21
21
|
*/
|
|
22
22
|
- (void)containerViewContentDidChangeSize:(CGSize)newSize;
|
|
23
23
|
|
|
24
|
+
@optional
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Called when the header size changes
|
|
28
|
+
* @param newSize The new size of the header
|
|
29
|
+
*/
|
|
30
|
+
- (void)containerViewHeaderDidChangeSize:(CGSize)newSize;
|
|
31
|
+
|
|
24
32
|
@end
|
|
25
33
|
|
|
26
34
|
@interface TrueSheetContainerView : RCTViewComponentView
|
|
@@ -30,16 +38,31 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
30
38
|
*/
|
|
31
39
|
@property (nonatomic, weak, nullable) id<TrueSheetContainerViewDelegate> delegate;
|
|
32
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Enable ScrollView pinning
|
|
43
|
+
*/
|
|
44
|
+
@property (nonatomic, assign) BOOL scrollViewPinningEnabled;
|
|
45
|
+
|
|
33
46
|
/**
|
|
34
47
|
* Returns the current content height
|
|
35
48
|
*/
|
|
36
49
|
- (CGFloat)contentHeight;
|
|
37
50
|
|
|
51
|
+
/**
|
|
52
|
+
* Returns the current header height
|
|
53
|
+
*/
|
|
54
|
+
- (CGFloat)headerHeight;
|
|
55
|
+
|
|
38
56
|
/**
|
|
39
57
|
* Updates footer layout constraints if needed
|
|
40
58
|
*/
|
|
41
59
|
- (void)layoutFooter;
|
|
42
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Setup ScrollView pinning
|
|
63
|
+
*/
|
|
64
|
+
- (void)setupContentScrollViewPinning;
|
|
65
|
+
|
|
43
66
|
@end
|
|
44
67
|
|
|
45
68
|
NS_ASSUME_NONNULL_END
|