@lodev09/react-native-true-sheet 3.5.1-beta.3 → 3.5.1-beta.4
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/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +2 -2
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +31 -28
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +336 -272
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +0 -5
- package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +7 -8
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +150 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +55 -0
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +18 -12
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +91 -2
- package/android/src/main/java/com/lodev09/truesheet/core/{TrueSheetDialogObserver.kt → TrueSheetStackManager.kt} +7 -5
- package/ios/TrueSheetViewController.h +2 -3
- package/ios/TrueSheetViewController.mm +11 -4
- package/ios/core/TrueSheetDetentCalculator.h +2 -3
- package/ios/core/TrueSheetDetentCalculator.mm +7 -9
- package/lib/module/TrueSheet.js +0 -2
- package/lib/module/TrueSheet.js.map +1 -1
- package/lib/module/fabric/TrueSheetViewNativeComponent.ts +0 -1
- package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
- package/lib/typescript/src/TrueSheet.types.d.ts +0 -8
- package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +0 -1
- package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/navigation/types.d.ts +1 -1
- package/lib/typescript/src/navigation/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/TrueSheet.tsx +0 -2
- package/src/TrueSheet.types.ts +0 -9
- package/src/fabric/TrueSheetViewNativeComponent.ts +0 -1
- package/src/navigation/types.ts +0 -1
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetAnimator.kt +0 -144
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDialogFragment.kt +0 -317
- package/android/src/main/res/anim/fast_fade_out.xml +0 -6
- package/android/src/main/res/values/styles.xml +0 -21
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
package com.lodev09.truesheet.core
|
|
2
|
-
|
|
3
|
-
import android.app.Dialog
|
|
4
|
-
import android.graphics.Color
|
|
5
|
-
import android.graphics.drawable.ShapeDrawable
|
|
6
|
-
import android.graphics.drawable.shapes.RoundRectShape
|
|
7
|
-
import android.os.Bundle
|
|
8
|
-
import android.util.Log
|
|
9
|
-
import android.util.TypedValue
|
|
10
|
-
import android.view.LayoutInflater
|
|
11
|
-
import android.view.View
|
|
12
|
-
import android.view.ViewGroup
|
|
13
|
-
import android.view.WindowManager
|
|
14
|
-
import android.widget.FrameLayout
|
|
15
|
-
import androidx.activity.OnBackPressedCallback
|
|
16
|
-
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
17
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
18
|
-
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
19
|
-
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
20
|
-
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|
21
|
-
import com.lodev09.truesheet.BuildConfig
|
|
22
|
-
import com.lodev09.truesheet.R
|
|
23
|
-
import com.lodev09.truesheet.utils.ScreenUtils
|
|
24
|
-
|
|
25
|
-
// =============================================================================
|
|
26
|
-
// MARK: - Delegate Protocol
|
|
27
|
-
// =============================================================================
|
|
28
|
-
|
|
29
|
-
interface TrueSheetDialogFragmentDelegate {
|
|
30
|
-
fun onDialogCreated()
|
|
31
|
-
fun onDialogShow()
|
|
32
|
-
fun onDialogDismiss()
|
|
33
|
-
fun onDialogCancel()
|
|
34
|
-
fun onStateChanged(sheetView: View, newState: Int)
|
|
35
|
-
fun onSlide(sheetView: View, slideOffset: Float)
|
|
36
|
-
fun onBackPressed()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// =============================================================================
|
|
40
|
-
// MARK: - TrueSheetDialogFragment
|
|
41
|
-
// =============================================================================
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Custom BottomSheetDialogFragment for TrueSheet.
|
|
45
|
-
* Provides a Material Design bottom sheet with proper lifecycle management.
|
|
46
|
-
*
|
|
47
|
-
* This fragment handles:
|
|
48
|
-
* - Dialog creation with proper theming (edge-to-edge support)
|
|
49
|
-
* - BottomSheetBehavior configuration and callbacks
|
|
50
|
-
* - Background styling with corner radius
|
|
51
|
-
* - Grabber view management
|
|
52
|
-
* - Back press handling
|
|
53
|
-
*
|
|
54
|
-
* The parent TrueSheetViewController handles:
|
|
55
|
-
* - React Native touch dispatching
|
|
56
|
-
* - Detent calculations
|
|
57
|
-
* - Animations
|
|
58
|
-
* - Keyboard/modal observers
|
|
59
|
-
* - Stacking and dimming
|
|
60
|
-
*/
|
|
61
|
-
class TrueSheetDialogFragment : BottomSheetDialogFragment() {
|
|
62
|
-
|
|
63
|
-
companion object {
|
|
64
|
-
private const val GRABBER_TAG = "TrueSheetGrabber"
|
|
65
|
-
private const val DEFAULT_MAX_WIDTH = 640 // dp
|
|
66
|
-
private const val DEFAULT_CORNER_RADIUS = 16f // dp
|
|
67
|
-
|
|
68
|
-
fun newInstance(): TrueSheetDialogFragment = TrueSheetDialogFragment()
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// =============================================================================
|
|
72
|
-
// MARK: - Properties
|
|
73
|
-
// =============================================================================
|
|
74
|
-
|
|
75
|
-
var delegate: TrueSheetDialogFragmentDelegate? = null
|
|
76
|
-
|
|
77
|
-
// Content view provided by the controller
|
|
78
|
-
var contentView: View? = null
|
|
79
|
-
|
|
80
|
-
// React context for theme resolution and screen utils
|
|
81
|
-
var reactContext: ThemedReactContext? = null
|
|
82
|
-
|
|
83
|
-
// Configuration
|
|
84
|
-
var sheetCornerRadius: Float = DEFAULT_CORNER_RADIUS.dpToPx()
|
|
85
|
-
var sheetBackgroundColor: Int? = null
|
|
86
|
-
var edgeToEdgeFullScreen: Boolean = false
|
|
87
|
-
var grabberEnabled: Boolean = true
|
|
88
|
-
var grabberOptions: GrabberOptions? = null
|
|
89
|
-
var draggable: Boolean = true
|
|
90
|
-
|
|
91
|
-
var dismissible: Boolean = true
|
|
92
|
-
set(value) {
|
|
93
|
-
field = value
|
|
94
|
-
(dialog as? BottomSheetDialog)?.apply {
|
|
95
|
-
setCanceledOnTouchOutside(value)
|
|
96
|
-
setCancelable(value)
|
|
97
|
-
behavior.isHideable = value
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// =============================================================================
|
|
102
|
-
// MARK: - Computed Properties
|
|
103
|
-
// =============================================================================
|
|
104
|
-
|
|
105
|
-
val bottomSheetDialog: BottomSheetDialog?
|
|
106
|
-
get() = dialog as? BottomSheetDialog
|
|
107
|
-
|
|
108
|
-
val behavior: BottomSheetBehavior<FrameLayout>?
|
|
109
|
-
get() = bottomSheetDialog?.behavior
|
|
110
|
-
|
|
111
|
-
val bottomSheetView: FrameLayout?
|
|
112
|
-
get() = dialog?.findViewById(com.google.android.material.R.id.design_bottom_sheet)
|
|
113
|
-
|
|
114
|
-
private val edgeToEdgeEnabled: Boolean
|
|
115
|
-
get() {
|
|
116
|
-
val defaultEnabled = android.os.Build.VERSION.SDK_INT >= 36
|
|
117
|
-
return BuildConfig.EDGE_TO_EDGE_ENABLED || bottomSheetDialog?.edgeToEdgeEnabled == true || defaultEnabled
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
val topInset: Int
|
|
121
|
-
get() = reactContext?.let { if (edgeToEdgeEnabled) ScreenUtils.getInsets(it).top else 0 } ?: 0
|
|
122
|
-
|
|
123
|
-
// =============================================================================
|
|
124
|
-
// MARK: - Lifecycle
|
|
125
|
-
// =============================================================================
|
|
126
|
-
|
|
127
|
-
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
128
|
-
val ctx = reactContext ?: requireContext()
|
|
129
|
-
|
|
130
|
-
val style = if (edgeToEdgeEnabled) {
|
|
131
|
-
R.style.TrueSheetEdgeToEdgeEnabledDialog
|
|
132
|
-
} else {
|
|
133
|
-
R.style.TrueSheetDialog
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
val dialog = BottomSheetDialog(ctx, style)
|
|
137
|
-
|
|
138
|
-
dialog.window?.apply {
|
|
139
|
-
setWindowAnimations(0)
|
|
140
|
-
setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
|
|
141
|
-
// Clear default dim - TrueSheet uses custom TrueSheetDimView for dimming
|
|
142
|
-
clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
dialog.setOnShowListener {
|
|
146
|
-
setupBottomSheetBehavior()
|
|
147
|
-
setupBackground()
|
|
148
|
-
setupGrabber()
|
|
149
|
-
// Re-apply dismissible after show since behavior may reset it
|
|
150
|
-
dialog.behavior.isHideable = dismissible
|
|
151
|
-
|
|
152
|
-
delegate?.onDialogShow()
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
dialog.setCanceledOnTouchOutside(dismissible)
|
|
156
|
-
dialog.setCancelable(dismissible)
|
|
157
|
-
dialog.behavior.isHideable = dismissible
|
|
158
|
-
dialog.behavior.isDraggable = draggable
|
|
159
|
-
dialog.behavior.maxWidth = DEFAULT_MAX_WIDTH.dpToPx().toInt()
|
|
160
|
-
|
|
161
|
-
// Handle back press - delegate to controller for animated dismiss
|
|
162
|
-
dialog.onBackPressedDispatcher.addCallback(
|
|
163
|
-
this,
|
|
164
|
-
object : OnBackPressedCallback(true) {
|
|
165
|
-
override fun handleOnBackPressed() {
|
|
166
|
-
delegate?.onBackPressed()
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
return dialog
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = contentView
|
|
175
|
-
|
|
176
|
-
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
177
|
-
delegate?.onDialogCreated()
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
override fun onCancel(dialog: android.content.DialogInterface) {
|
|
181
|
-
super.onCancel(dialog)
|
|
182
|
-
delegate?.onDialogCancel()
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
override fun onDismiss(dialog: android.content.DialogInterface) {
|
|
186
|
-
super.onDismiss(dialog)
|
|
187
|
-
delegate?.onDialogDismiss()
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
override fun onDestroyView() {
|
|
191
|
-
// Detach content view to prevent it from being destroyed with the fragment
|
|
192
|
-
(contentView?.parent as? ViewGroup)?.removeView(contentView)
|
|
193
|
-
super.onDestroyView()
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// =============================================================================
|
|
197
|
-
// MARK: - Setup
|
|
198
|
-
// =============================================================================
|
|
199
|
-
|
|
200
|
-
private fun setupBottomSheetBehavior() {
|
|
201
|
-
val behavior = this.behavior ?: return
|
|
202
|
-
|
|
203
|
-
behavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
|
204
|
-
override fun onSlide(sheetView: View, slideOffset: Float) {
|
|
205
|
-
delegate?.onSlide(sheetView, slideOffset)
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
override fun onStateChanged(sheetView: View, newState: Int) {
|
|
209
|
-
delegate?.onStateChanged(sheetView, newState)
|
|
210
|
-
}
|
|
211
|
-
})
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
fun setupBackground() {
|
|
215
|
-
val bottomSheet = bottomSheetView ?: return
|
|
216
|
-
val ctx = reactContext ?: return
|
|
217
|
-
|
|
218
|
-
val radius = if (sheetCornerRadius < 0) DEFAULT_CORNER_RADIUS.dpToPx() else sheetCornerRadius
|
|
219
|
-
|
|
220
|
-
// Rounded corners only on top
|
|
221
|
-
val outerRadii = floatArrayOf(
|
|
222
|
-
radius,
|
|
223
|
-
radius,
|
|
224
|
-
radius,
|
|
225
|
-
radius,
|
|
226
|
-
0f,
|
|
227
|
-
0f,
|
|
228
|
-
0f,
|
|
229
|
-
0f
|
|
230
|
-
)
|
|
231
|
-
val backgroundColor = sheetBackgroundColor ?: getDefaultBackgroundColor(ctx)
|
|
232
|
-
|
|
233
|
-
bottomSheet.background = ShapeDrawable(RoundRectShape(outerRadii, null, null)).apply {
|
|
234
|
-
paint.color = backgroundColor
|
|
235
|
-
}
|
|
236
|
-
bottomSheet.clipToOutline = true
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
fun setupGrabber() {
|
|
240
|
-
val bottomSheet = bottomSheetView ?: return
|
|
241
|
-
val ctx = reactContext ?: return
|
|
242
|
-
|
|
243
|
-
// Remove existing grabber
|
|
244
|
-
bottomSheet.findViewWithTag<View>(GRABBER_TAG)?.let {
|
|
245
|
-
bottomSheet.removeView(it)
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (!grabberEnabled || !draggable) return
|
|
249
|
-
|
|
250
|
-
val grabberView = TrueSheetGrabberView(ctx, grabberOptions).apply {
|
|
251
|
-
tag = GRABBER_TAG
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
bottomSheet.addView(grabberView)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// =============================================================================
|
|
258
|
-
// MARK: - Configuration
|
|
259
|
-
// =============================================================================
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Configure detent-related behavior settings.
|
|
263
|
-
* Called by the controller when detents change.
|
|
264
|
-
*/
|
|
265
|
-
fun configureDetents(
|
|
266
|
-
peekHeight: Int,
|
|
267
|
-
halfExpandedRatio: Float,
|
|
268
|
-
expandedOffset: Int,
|
|
269
|
-
fitToContents: Boolean,
|
|
270
|
-
skipCollapsed: Boolean = false,
|
|
271
|
-
animate: Boolean = false
|
|
272
|
-
) {
|
|
273
|
-
val behavior = this.behavior ?: return
|
|
274
|
-
|
|
275
|
-
behavior.apply {
|
|
276
|
-
isFitToContents = fitToContents
|
|
277
|
-
this.skipCollapsed = skipCollapsed
|
|
278
|
-
setPeekHeight(peekHeight, animate)
|
|
279
|
-
this.halfExpandedRatio = halfExpandedRatio.coerceIn(0f, 0.999f)
|
|
280
|
-
this.expandedOffset = expandedOffset
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Set the behavior state.
|
|
286
|
-
*/
|
|
287
|
-
fun setState(state: Int) {
|
|
288
|
-
behavior?.state = state
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Update draggable state.
|
|
293
|
-
*/
|
|
294
|
-
fun updateDraggable(enabled: Boolean) {
|
|
295
|
-
draggable = enabled
|
|
296
|
-
behavior?.isDraggable = enabled
|
|
297
|
-
if (isAdded) setupGrabber()
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// =============================================================================
|
|
301
|
-
// MARK: - Helpers
|
|
302
|
-
// =============================================================================
|
|
303
|
-
|
|
304
|
-
private fun getDefaultBackgroundColor(context: ThemedReactContext): Int {
|
|
305
|
-
val typedValue = TypedValue()
|
|
306
|
-
return if (context.theme.resolveAttribute(
|
|
307
|
-
com.google.android.material.R.attr.colorSurfaceContainerLow,
|
|
308
|
-
typedValue,
|
|
309
|
-
true
|
|
310
|
-
)
|
|
311
|
-
) {
|
|
312
|
-
typedValue.data
|
|
313
|
-
} else {
|
|
314
|
-
Color.WHITE
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<resources>
|
|
3
|
-
<!-- Fast fade out animation for hiding sheet when rn-screen is presented -->
|
|
4
|
-
<style name="TrueSheetFastFadeOut" parent="Animation.AppCompat.Dialog">
|
|
5
|
-
<item name="android:windowEnterAnimation">@null</item>
|
|
6
|
-
<item name="android:windowExitAnimation">@anim/fast_fade_out</item>
|
|
7
|
-
</style>
|
|
8
|
-
|
|
9
|
-
<!-- Default BottomSheetDialog style with programmatic animations -->
|
|
10
|
-
<style name="TrueSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
|
|
11
|
-
<item name="android:windowAnimationStyle">@null</item>
|
|
12
|
-
</style>
|
|
13
|
-
|
|
14
|
-
<!-- BottomSheetDialog style with edge-to-edge and programmatic animations -->
|
|
15
|
-
<style name="TrueSheetEdgeToEdgeEnabledDialog" parent="Theme.Design.Light.BottomSheetDialog">
|
|
16
|
-
<item name="android:windowIsFloating">false</item>
|
|
17
|
-
<item name="enableEdgeToEdge">true</item>
|
|
18
|
-
<item name="android:navigationBarColor">@android:color/transparent</item>
|
|
19
|
-
<item name="android:windowAnimationStyle">@null</item>
|
|
20
|
-
</style>
|
|
21
|
-
</resources>
|