@lodev09/react-native-true-sheet 3.0.0-beta.4 → 3.0.0-beta.6
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 +0 -1
- package/RNTrueSheet.podspec +5 -1
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerView.kt +50 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetContainerViewManager.kt +7 -0
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +0 -9
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +33 -7
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +12 -4
- 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/TrueSheetContainerViewComponentDescriptor.h +24 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContainerViewShadowNode.cpp +46 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContainerViewShadowNode.h +28 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContainerViewState.cpp +11 -0
- package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContainerViewState.h +42 -0
- package/ios/TrueSheetContainerView.mm +61 -5
- package/ios/TrueSheetContentView.mm +0 -11
- package/ios/TrueSheetView.h +0 -16
- package/ios/TrueSheetView.mm +10 -8
- package/ios/TrueSheetViewController.h +0 -1
- package/ios/TrueSheetViewController.mm +9 -26
- package/ios/utils/ConversionUtil.mm +30 -40
- package/lib/module/TrueSheet.js +1 -23
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/fabric/TrueSheetContainerViewNativeComponent.ts +3 -1
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +0 -6
- 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 +0 -13
- 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/TrueSheetViewNativeComponent.d.ts +0 -5
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/package.json +2 -2
- package/react-native.config.js +5 -2
- package/src/TrueSheet.tsx +1 -27
- package/src/TrueSheet.types.ts +0 -15
- package/src/fabric/TrueSheetContainerViewNativeComponent.ts +3 -1
- package/src/fabric/TrueSheetViewNativeComponent.ts +0 -6
- 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
package/README.md
CHANGED
package/RNTrueSheet.podspec
CHANGED
|
@@ -13,8 +13,12 @@ Pod::Spec.new do |s|
|
|
|
13
13
|
s.platforms = { :ios => min_ios_version_supported }
|
|
14
14
|
s.source = { :git => "https://github.com/lodev09/react-native-true-sheet.git", :tag => "#{s.version}" }
|
|
15
15
|
|
|
16
|
-
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}", "common/cpp/**/*.{cpp,h}"
|
|
17
17
|
s.private_header_files = "ios/**/*.h"
|
|
18
18
|
|
|
19
|
+
s.pod_target_xcconfig = {
|
|
20
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/common/cpp\""
|
|
21
|
+
}
|
|
22
|
+
|
|
19
23
|
install_modules_dependencies(s)
|
|
20
24
|
end
|
|
@@ -3,6 +3,9 @@ package com.lodev09.truesheet
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
4
|
import android.view.View
|
|
5
5
|
import androidx.core.view.isNotEmpty
|
|
6
|
+
import com.facebook.react.bridge.WritableNativeMap
|
|
7
|
+
import com.facebook.react.uimanager.PixelUtil.pxToDp
|
|
8
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
6
9
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
10
|
import com.facebook.react.views.view.ReactViewGroup
|
|
8
11
|
|
|
@@ -26,6 +29,53 @@ class TrueSheetContainerView(private val reactContext: ThemedReactContext) :
|
|
|
26
29
|
|
|
27
30
|
var delegate: TrueSheetContainerViewDelegate? = null
|
|
28
31
|
|
|
32
|
+
private var stateWrapper: StateWrapper? = null
|
|
33
|
+
|
|
34
|
+
// Pending dimensions to update when stateWrapper becomes available
|
|
35
|
+
private var pendingWidth: Int = 0
|
|
36
|
+
private var pendingHeight: Int = 0
|
|
37
|
+
|
|
38
|
+
fun setStateWrapper(wrapper: StateWrapper?) {
|
|
39
|
+
stateWrapper = wrapper
|
|
40
|
+
|
|
41
|
+
if (wrapper == null) return
|
|
42
|
+
|
|
43
|
+
// Get dimensions from parent controller and update state if we haven't yet
|
|
44
|
+
val controller = parent as? TrueSheetViewController
|
|
45
|
+
if (controller != null && pendingWidth == 0) {
|
|
46
|
+
val w = controller.width
|
|
47
|
+
val h = controller.height
|
|
48
|
+
if (w > 0 && h > 0) {
|
|
49
|
+
updateState(w, h)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Update state with container dimensions.
|
|
56
|
+
* Called by the controller when the dialog size changes.
|
|
57
|
+
*/
|
|
58
|
+
fun updateState(width: Int, height: Int) {
|
|
59
|
+
// Skip if dimensions haven't changed
|
|
60
|
+
if (width == pendingWidth && height == pendingHeight && stateWrapper != null) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Store dimensions
|
|
65
|
+
pendingWidth = width
|
|
66
|
+
pendingHeight = height
|
|
67
|
+
|
|
68
|
+
val sw = stateWrapper ?: return
|
|
69
|
+
|
|
70
|
+
val realWidth = width.toFloat().pxToDp()
|
|
71
|
+
val realHeight = height.toFloat().pxToDp()
|
|
72
|
+
|
|
73
|
+
val newStateData = WritableNativeMap()
|
|
74
|
+
newStateData.putDouble("containerWidth", realWidth.toDouble())
|
|
75
|
+
newStateData.putDouble("containerHeight", realHeight.toDouble())
|
|
76
|
+
sw.updateState(newStateData)
|
|
77
|
+
}
|
|
78
|
+
|
|
29
79
|
/**
|
|
30
80
|
* Reference to content view (first child)
|
|
31
81
|
*/
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.lodev09.truesheet
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.module.annotations.ReactModule
|
|
4
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
5
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
4
6
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
5
7
|
import com.facebook.react.uimanager.ViewGroupManager
|
|
6
8
|
|
|
@@ -15,6 +17,11 @@ class TrueSheetContainerViewManager : ViewGroupManager<TrueSheetContainerView>()
|
|
|
15
17
|
|
|
16
18
|
override fun createViewInstance(reactContext: ThemedReactContext): TrueSheetContainerView = TrueSheetContainerView(reactContext)
|
|
17
19
|
|
|
20
|
+
override fun updateState(view: TrueSheetContainerView, props: ReactStylesDiffMap?, stateWrapper: StateWrapper?): Any? {
|
|
21
|
+
view.setStateWrapper(stateWrapper)
|
|
22
|
+
return null
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
companion object {
|
|
19
26
|
const val REACT_CLASS = "TrueSheetContainerView"
|
|
20
27
|
}
|
|
@@ -18,7 +18,6 @@ import com.lodev09.truesheet.events.DragChangeEvent
|
|
|
18
18
|
import com.lodev09.truesheet.events.DragEndEvent
|
|
19
19
|
import com.lodev09.truesheet.events.MountEvent
|
|
20
20
|
import com.lodev09.truesheet.events.PositionChangeEvent
|
|
21
|
-
import com.lodev09.truesheet.events.SizeChangeEvent
|
|
22
21
|
import com.lodev09.truesheet.events.WillDismissEvent
|
|
23
22
|
import com.lodev09.truesheet.events.WillPresentEvent
|
|
24
23
|
|
|
@@ -350,14 +349,6 @@ class TrueSheetView(private val reactContext: ThemedReactContext) :
|
|
|
350
349
|
viewController.dismiss()
|
|
351
350
|
}
|
|
352
351
|
|
|
353
|
-
override fun viewControllerDidChangeSize(width: Int, height: Int) {
|
|
354
|
-
// Dispatch size change event to JS
|
|
355
|
-
val surfaceId = UIManagerHelper.getSurfaceId(this)
|
|
356
|
-
eventDispatcher?.dispatchEvent(
|
|
357
|
-
SizeChangeEvent(surfaceId, id, width, height)
|
|
358
|
-
)
|
|
359
|
-
}
|
|
360
|
-
|
|
361
352
|
// ==================== TrueSheetContainerViewDelegate Implementation ====================
|
|
362
353
|
|
|
363
354
|
override fun containerViewContentDidChangeSize(width: Int, height: Int) {
|
|
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
|
|
|
4
4
|
import android.graphics.Color
|
|
5
5
|
import android.graphics.drawable.ShapeDrawable
|
|
6
6
|
import android.graphics.drawable.shapes.RoundRectShape
|
|
7
|
+
import android.util.TypedValue
|
|
7
8
|
import android.view.MotionEvent
|
|
8
9
|
import android.view.View
|
|
9
10
|
import android.view.WindowManager
|
|
@@ -40,7 +41,6 @@ interface TrueSheetViewControllerDelegate {
|
|
|
40
41
|
fun viewControllerDidDragChange(index: Int, position: Float)
|
|
41
42
|
fun viewControllerDidDragEnd(index: Int, position: Float)
|
|
42
43
|
fun viewControllerDidChangePosition(index: Int, position: Float, transitioning: Boolean)
|
|
43
|
-
fun viewControllerDidChangeSize(width: Int, height: Int)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -65,6 +65,9 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
65
65
|
private val jSTouchDispatcher = JSTouchDispatcher(this)
|
|
66
66
|
private var jSPointerDispatcher: JSPointerDispatcher? = null
|
|
67
67
|
|
|
68
|
+
private var viewWidth = 0
|
|
69
|
+
private var viewHeight = 0
|
|
70
|
+
|
|
68
71
|
/**
|
|
69
72
|
* Delegate for handling view controller events
|
|
70
73
|
*/
|
|
@@ -192,8 +195,8 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
192
195
|
}
|
|
193
196
|
}
|
|
194
197
|
|
|
195
|
-
var cornerRadius: Float =
|
|
196
|
-
var sheetBackgroundColor: Int =
|
|
198
|
+
var cornerRadius: Float = 28f.dpToPx()
|
|
199
|
+
var sheetBackgroundColor: Int = 0
|
|
197
200
|
var detents = mutableListOf(0.5, 1.0)
|
|
198
201
|
|
|
199
202
|
private var windowAnimation: Int = 0
|
|
@@ -203,6 +206,24 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
203
206
|
jSPointerDispatcher = JSPointerDispatcher(this)
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Get the default background color from Material Design 3 theme.
|
|
211
|
+
* Uses colorSurfaceContainerLow which adapts to light/dark mode.
|
|
212
|
+
*/
|
|
213
|
+
fun getDefaultBackgroundColor(): Int {
|
|
214
|
+
val typedValue = TypedValue()
|
|
215
|
+
return if (reactContext.theme.resolveAttribute(
|
|
216
|
+
com.google.android.material.R.attr.colorSurfaceContainerLow,
|
|
217
|
+
typedValue,
|
|
218
|
+
true
|
|
219
|
+
)
|
|
220
|
+
) {
|
|
221
|
+
typedValue.data
|
|
222
|
+
} else {
|
|
223
|
+
Color.WHITE
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
206
227
|
// ==================== Lifecycle ====================
|
|
207
228
|
|
|
208
229
|
/**
|
|
@@ -495,8 +516,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
495
516
|
0f
|
|
496
517
|
)
|
|
497
518
|
|
|
519
|
+
// 0 (transparent) is used as sentinel for "use system default"
|
|
520
|
+
val backgroundColor = if (sheetBackgroundColor != 0) sheetBackgroundColor else getDefaultBackgroundColor()
|
|
521
|
+
|
|
498
522
|
val background = ShapeDrawable(RoundRectShape(outerRadii, null, null))
|
|
499
|
-
background.paint.color =
|
|
523
|
+
background.paint.color = backgroundColor
|
|
500
524
|
|
|
501
525
|
this.background = background
|
|
502
526
|
this.clipToOutline = true
|
|
@@ -774,6 +798,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
774
798
|
|
|
775
799
|
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
776
800
|
super.onSizeChanged(w, h, oldw, oldh)
|
|
801
|
+
viewWidth = w
|
|
802
|
+
viewHeight = h
|
|
803
|
+
|
|
804
|
+
// Update container state with new dimensions
|
|
805
|
+
containerView?.updateState(viewWidth, viewHeight)
|
|
777
806
|
|
|
778
807
|
// Only proceed if size actually changed
|
|
779
808
|
if (w == oldw && h == oldh) return
|
|
@@ -796,9 +825,6 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
796
825
|
delegate?.viewControllerDidChangePosition(detentInfo.index, detentInfo.position, transitioning = true)
|
|
797
826
|
}
|
|
798
827
|
}
|
|
799
|
-
|
|
800
|
-
// Notify delegate about size change
|
|
801
|
-
delegate?.viewControllerDidChangeSize(w, h)
|
|
802
828
|
}
|
|
803
829
|
|
|
804
830
|
override fun handleException(t: Throwable) {
|
|
@@ -1,6 +1,5 @@
|
|
|
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
|
|
@@ -61,8 +60,7 @@ class TrueSheetViewManager :
|
|
|
61
60
|
DragBeginEvent.EVENT_NAME to hashMapOf("registrationName" to DragBeginEvent.REGISTRATION_NAME),
|
|
62
61
|
DragChangeEvent.EVENT_NAME to hashMapOf("registrationName" to DragChangeEvent.REGISTRATION_NAME),
|
|
63
62
|
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)
|
|
63
|
+
PositionChangeEvent.EVENT_NAME to hashMapOf("registrationName" to PositionChangeEvent.REGISTRATION_NAME)
|
|
66
64
|
)
|
|
67
65
|
|
|
68
66
|
// ==================== Props ====================
|
|
@@ -85,7 +83,7 @@ class TrueSheetViewManager :
|
|
|
85
83
|
view.setDetents(detents)
|
|
86
84
|
}
|
|
87
85
|
|
|
88
|
-
@ReactProp(name = "background", defaultInt =
|
|
86
|
+
@ReactProp(name = "background", defaultInt = 0)
|
|
89
87
|
override fun setBackground(view: TrueSheetView, color: Int) {
|
|
90
88
|
view.setSheetBackgroundColor(color)
|
|
91
89
|
}
|
|
@@ -154,6 +152,16 @@ class TrueSheetViewManager :
|
|
|
154
152
|
view.setEdgeToEdgeFullScreen(edgeToEdgeFullScreen)
|
|
155
153
|
}
|
|
156
154
|
|
|
155
|
+
@ReactProp(name = "fitScrollView", defaultBoolean = false)
|
|
156
|
+
override fun setFitScrollView(view: TrueSheetView, value: Boolean) {
|
|
157
|
+
// iOS-specific prop - no-op on Android
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@ReactProp(name = "pageSizing", defaultBoolean = true)
|
|
161
|
+
override fun setPageSizing(view: TrueSheetView, value: Boolean) {
|
|
162
|
+
// iOS-specific prop - no-op on Android
|
|
163
|
+
}
|
|
164
|
+
|
|
157
165
|
companion object {
|
|
158
166
|
const val REACT_CLASS = "TrueSheetView"
|
|
159
167
|
const val TAG_NAME = "TrueSheet"
|
|
@@ -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/TrueSheetContainerViewComponentDescriptor.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/TrueSheetContainerViewShadowNode.h>
|
|
4
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
5
|
+
|
|
6
|
+
namespace facebook::react {
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* Descriptor for <TrueSheetContainerView> component.
|
|
10
|
+
*/
|
|
11
|
+
class TrueSheetContainerViewComponentDescriptor final
|
|
12
|
+
: public ConcreteComponentDescriptor<TrueSheetContainerViewShadowNode> {
|
|
13
|
+
using ConcreteComponentDescriptor::ConcreteComponentDescriptor;
|
|
14
|
+
|
|
15
|
+
void adopt(ShadowNode &shadowNode) const override {
|
|
16
|
+
auto &concreteShadowNode =
|
|
17
|
+
static_cast<TrueSheetContainerViewShadowNode &>(shadowNode);
|
|
18
|
+
concreteShadowNode.adjustLayoutWithState();
|
|
19
|
+
|
|
20
|
+
ConcreteComponentDescriptor::adopt(shadowNode);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
} // namespace facebook::react
|
package/common/cpp/react/renderer/components/TrueSheetSpec/TrueSheetContainerViewShadowNode.cpp
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#include "TrueSheetContainerViewShadowNode.h"
|
|
2
|
+
|
|
3
|
+
#include <yoga/style/StyleSizeLength.h>
|
|
4
|
+
|
|
5
|
+
namespace facebook::react {
|
|
6
|
+
|
|
7
|
+
extern const char TrueSheetContainerViewComponentName[] = "TrueSheetContainerView";
|
|
8
|
+
|
|
9
|
+
void TrueSheetContainerViewShadowNode::adjustLayoutWithState() {
|
|
10
|
+
ensureUnsealed();
|
|
11
|
+
|
|
12
|
+
auto state = std::static_pointer_cast<
|
|
13
|
+
const TrueSheetContainerViewShadowNode::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/TrueSheetContainerViewState.h>
|
|
7
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
8
|
+
|
|
9
|
+
namespace facebook::react {
|
|
10
|
+
|
|
11
|
+
JSI_EXPORT extern const char TrueSheetContainerViewComponentName[];
|
|
12
|
+
|
|
13
|
+
/*
|
|
14
|
+
* `ShadowNode` for <TrueSheetContainerView> component.
|
|
15
|
+
*/
|
|
16
|
+
class JSI_EXPORT TrueSheetContainerViewShadowNode final
|
|
17
|
+
: public ConcreteViewShadowNode<
|
|
18
|
+
TrueSheetContainerViewComponentName,
|
|
19
|
+
TrueSheetContainerViewProps,
|
|
20
|
+
TrueSheetContainerViewEventEmitter,
|
|
21
|
+
TrueSheetContainerViewState> {
|
|
22
|
+
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
|
23
|
+
|
|
24
|
+
public:
|
|
25
|
+
void adjustLayoutWithState();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#include "TrueSheetContainerViewState.h"
|
|
2
|
+
|
|
3
|
+
namespace facebook::react {
|
|
4
|
+
|
|
5
|
+
#ifdef ANDROID
|
|
6
|
+
folly::dynamic TrueSheetContainerViewState::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 <TrueSheetContainerView> component.
|
|
15
|
+
* Contains the container dimensions from native.
|
|
16
|
+
*/
|
|
17
|
+
class TrueSheetContainerViewState final {
|
|
18
|
+
public:
|
|
19
|
+
using Shared = std::shared_ptr<const TrueSheetContainerViewState>;
|
|
20
|
+
|
|
21
|
+
TrueSheetContainerViewState() = default;
|
|
22
|
+
|
|
23
|
+
#ifdef ANDROID
|
|
24
|
+
TrueSheetContainerViewState(
|
|
25
|
+
TrueSheetContainerViewState 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
|
|
@@ -9,14 +9,18 @@
|
|
|
9
9
|
#ifdef RCT_NEW_ARCH_ENABLED
|
|
10
10
|
|
|
11
11
|
#import "TrueSheetContainerView.h"
|
|
12
|
-
#import <react/renderer/components/TrueSheetSpec/ComponentDescriptors.h>
|
|
13
12
|
#import <react/renderer/components/TrueSheetSpec/EventEmitters.h>
|
|
14
13
|
#import <react/renderer/components/TrueSheetSpec/Props.h>
|
|
15
14
|
#import <react/renderer/components/TrueSheetSpec/RCTComponentViewHelpers.h>
|
|
15
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetContainerViewComponentDescriptor.h>
|
|
16
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetContainerViewShadowNode.h>
|
|
17
|
+
#import <react/renderer/components/TrueSheetSpec/TrueSheetContainerViewState.h>
|
|
16
18
|
#import "TrueSheetContentView.h"
|
|
17
19
|
#import "TrueSheetFooterView.h"
|
|
18
20
|
|
|
19
21
|
#import <React/RCTConversions.h>
|
|
22
|
+
#import <React/RCTLog.h>
|
|
23
|
+
#import <react/renderer/core/State.h>
|
|
20
24
|
|
|
21
25
|
using namespace facebook::react;
|
|
22
26
|
|
|
@@ -26,6 +30,8 @@ using namespace facebook::react;
|
|
|
26
30
|
@implementation TrueSheetContainerView {
|
|
27
31
|
TrueSheetContentView *_contentView;
|
|
28
32
|
TrueSheetFooterView *_footerView;
|
|
33
|
+
TrueSheetContainerViewShadowNode::ConcreteState::Shared _state;
|
|
34
|
+
CGFloat _lastContainerWidth;
|
|
29
35
|
}
|
|
30
36
|
|
|
31
37
|
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
@@ -41,11 +47,49 @@ using namespace facebook::react;
|
|
|
41
47
|
|
|
42
48
|
_contentView = nil;
|
|
43
49
|
_footerView = nil;
|
|
50
|
+
_lastContainerWidth = 0;
|
|
44
51
|
}
|
|
45
52
|
return self;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
- (void)
|
|
55
|
+
- (void)layoutSubviews {
|
|
56
|
+
[super layoutSubviews];
|
|
57
|
+
|
|
58
|
+
// Override Yoga layout - fill the entire parent (controller's view)
|
|
59
|
+
if (self.superview) {
|
|
60
|
+
CGRect parentBounds = self.superview.bounds;
|
|
61
|
+
if (!CGRectEqualToRect(self.frame, parentBounds)) {
|
|
62
|
+
self.frame = parentBounds;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Update state with container width so Yoga can use it for children layout
|
|
66
|
+
[self updateStateIfNeeded];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
- (void)updateStateIfNeeded {
|
|
71
|
+
if (!self.superview) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
CGFloat containerWidth = self.superview.bounds.size.width;
|
|
76
|
+
if (containerWidth > 0 && fabs(containerWidth - _lastContainerWidth) > 0.5) {
|
|
77
|
+
_lastContainerWidth = containerWidth;
|
|
78
|
+
[self updateState];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
- (void)updateState {
|
|
83
|
+
if (!_state) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_state->updateState([=](TrueSheetContainerViewShadowNode::ConcreteState::Data const &oldData)
|
|
88
|
+
-> TrueSheetContainerViewShadowNode::ConcreteState::SharedData {
|
|
89
|
+
auto newData = oldData;
|
|
90
|
+
newData.containerWidth = static_cast<float>(_lastContainerWidth);
|
|
91
|
+
return std::make_shared<TrueSheetContainerViewShadowNode::ConcreteState::Data const>(newData);
|
|
92
|
+
});
|
|
49
93
|
}
|
|
50
94
|
|
|
51
95
|
- (CGFloat)contentHeight {
|
|
@@ -64,7 +108,6 @@ using namespace facebook::react;
|
|
|
64
108
|
|
|
65
109
|
- (void)setupContentScrollViewPinning:(BOOL)pinned {
|
|
66
110
|
if (_contentView) {
|
|
67
|
-
NSLog(@"setting up scrollview pinning: %i", pinned);
|
|
68
111
|
[_contentView setupScrollViewPinning:pinned];
|
|
69
112
|
}
|
|
70
113
|
}
|
|
@@ -75,7 +118,7 @@ using namespace facebook::react;
|
|
|
75
118
|
// Handle content view mounting
|
|
76
119
|
if ([childComponentView isKindOfClass:[TrueSheetContentView class]]) {
|
|
77
120
|
if (_contentView != nil) {
|
|
78
|
-
|
|
121
|
+
RCTLogWarn(@"TrueSheet: Container can only have one content component.");
|
|
79
122
|
return;
|
|
80
123
|
}
|
|
81
124
|
|
|
@@ -86,7 +129,7 @@ using namespace facebook::react;
|
|
|
86
129
|
// Handle footer view mounting
|
|
87
130
|
if ([childComponentView isKindOfClass:[TrueSheetFooterView class]]) {
|
|
88
131
|
if (_footerView != nil) {
|
|
89
|
-
|
|
132
|
+
RCTLogWarn(@"TrueSheet: Container can only have one footer component.");
|
|
90
133
|
return;
|
|
91
134
|
}
|
|
92
135
|
|
|
@@ -110,6 +153,19 @@ using namespace facebook::react;
|
|
|
110
153
|
[super updateProps:props oldProps:oldProps];
|
|
111
154
|
}
|
|
112
155
|
|
|
156
|
+
- (void)updateState:(const State::Shared &)state oldState:(const State::Shared &)oldState {
|
|
157
|
+
_state = std::static_pointer_cast<TrueSheetContainerViewShadowNode::ConcreteState const>(state);
|
|
158
|
+
|
|
159
|
+
// Reset last width when state is updated to ensure we push the correct width
|
|
160
|
+
// This handles re-presentation of the sheet where state is recreated
|
|
161
|
+
_lastContainerWidth = 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
165
|
+
[super finalizeUpdates:updateMask];
|
|
166
|
+
[self updateStateIfNeeded];
|
|
167
|
+
}
|
|
168
|
+
|
|
113
169
|
#pragma mark - TrueSheetContentViewDelegate
|
|
114
170
|
|
|
115
171
|
- (void)contentViewDidChangeSize:(CGSize)newSize {
|
|
@@ -53,17 +53,6 @@ using namespace facebook::react;
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
//- (void)didMoveToSuperview {
|
|
57
|
-
// [super didMoveToSuperview];
|
|
58
|
-
//
|
|
59
|
-
// // Setup scroll view pinning after Fabric mounts the view in container
|
|
60
|
-
// // Ensures proper view hierarchy for scroll detection and pinning
|
|
61
|
-
// if (self.superview) {
|
|
62
|
-
// NSLog(@"content has attached");
|
|
63
|
-
//// [self setupScrollViewPinning];
|
|
64
|
-
// }
|
|
65
|
-
//}
|
|
66
|
-
|
|
67
56
|
- (void)unpinScrollView {
|
|
68
57
|
// Unpin previous scroll view if exists
|
|
69
58
|
if (_pinnedScrollView) {
|