@lodev09/react-native-true-sheet 3.5.1-beta.3 → 3.5.1-beta.5

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.
Files changed (33) hide show
  1. package/android/src/main/java/com/lodev09/truesheet/TrueSheetModule.kt +2 -2
  2. package/android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt +31 -28
  3. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +358 -271
  4. package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewManager.kt +0 -5
  5. package/android/src/main/java/com/lodev09/truesheet/core/RNScreensFragmentObserver.kt +7 -8
  6. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetBottomSheetView.kt +158 -0
  7. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +55 -0
  8. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDetentCalculator.kt +18 -12
  9. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDimView.kt +91 -2
  10. package/android/src/main/java/com/lodev09/truesheet/core/{TrueSheetDialogObserver.kt → TrueSheetStackManager.kt} +7 -5
  11. package/ios/TrueSheetViewController.h +2 -3
  12. package/ios/TrueSheetViewController.mm +11 -4
  13. package/ios/core/TrueSheetDetentCalculator.h +2 -3
  14. package/ios/core/TrueSheetDetentCalculator.mm +7 -9
  15. package/lib/module/TrueSheet.js +0 -2
  16. package/lib/module/TrueSheet.js.map +1 -1
  17. package/lib/module/fabric/TrueSheetViewNativeComponent.ts +0 -1
  18. package/lib/typescript/src/TrueSheet.d.ts.map +1 -1
  19. package/lib/typescript/src/TrueSheet.types.d.ts +0 -8
  20. package/lib/typescript/src/TrueSheet.types.d.ts.map +1 -1
  21. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts +0 -1
  22. package/lib/typescript/src/fabric/TrueSheetViewNativeComponent.d.ts.map +1 -1
  23. package/lib/typescript/src/navigation/types.d.ts +1 -1
  24. package/lib/typescript/src/navigation/types.d.ts.map +1 -1
  25. package/package.json +1 -1
  26. package/src/TrueSheet.tsx +0 -2
  27. package/src/TrueSheet.types.ts +0 -9
  28. package/src/fabric/TrueSheetViewNativeComponent.ts +0 -1
  29. package/src/navigation/types.ts +0 -1
  30. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetAnimator.kt +0 -144
  31. package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetDialogFragment.kt +0 -317
  32. package/android/src/main/res/anim/fast_fade_out.xml +0 -6
  33. 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,6 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <alpha xmlns:android="http://schemas.android.com/apk/res/android"
3
- android:fromAlpha="1.0"
4
- android:toAlpha="0.0"
5
- android:duration="100"
6
- android:interpolator="@android:interpolator/accelerate_quad" />
@@ -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>