@sbaiahmed1/react-native-blur 0.2.0 → 0.3.0-beta.0

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 (38) hide show
  1. package/README.md +271 -16
  2. package/ReactNativeBlur.podspec +2 -1
  3. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeBlurViewManagerDelegate.java +38 -0
  4. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeBlurViewManagerInterface.java +20 -0
  5. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeGlassViewManagerDelegate.java +38 -0
  6. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeGlassViewManagerInterface.java +20 -0
  7. package/android/app/build/generated/source/codegen/jni/CMakeLists.txt +36 -0
  8. package/android/app/build/generated/source/codegen/jni/ReactNativeBlurViewSpec-generated.cpp +22 -0
  9. package/android/app/build/generated/source/codegen/jni/ReactNativeBlurViewSpec.h +24 -0
  10. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ComponentDescriptors.cpp +23 -0
  11. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ComponentDescriptors.h +25 -0
  12. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/EventEmitters.cpp +17 -0
  13. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/EventEmitters.h +30 -0
  14. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/Props.cpp +36 -0
  15. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/Props.h +91 -0
  16. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ReactNativeBlurViewSpecJSI-generated.cpp +17 -0
  17. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ReactNativeBlurViewSpecJSI.h +19 -0
  18. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ShadowNodes.cpp +18 -0
  19. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ShadowNodes.h +43 -0
  20. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/States.cpp +16 -0
  21. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/States.h +41 -0
  22. package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt +164 -39
  23. package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurViewManager.kt +20 -0
  24. package/ios/ReactNativeBlurView.mm +190 -238
  25. package/ios/ReactNativeBlurView.swift +309 -0
  26. package/ios/ReactNativeBlurViewManager.h +5 -0
  27. package/ios/ReactNativeBlurViewManager.m +165 -0
  28. package/lib/module/BlurView.js +14 -2
  29. package/lib/module/BlurView.js.map +1 -1
  30. package/lib/module/ReactNativeBlurViewNativeComponent.ts +9 -3
  31. package/lib/typescript/src/BlurView.d.ts +30 -1
  32. package/lib/typescript/src/BlurView.d.ts.map +1 -1
  33. package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts +8 -3
  34. package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts.map +1 -1
  35. package/package.json +2 -2
  36. package/src/BlurView.tsx +48 -3
  37. package/src/ReactNativeBlurViewNativeComponent.ts +9 -3
  38. package/ios/ReactNativeBlurViewManager.mm +0 -23
@@ -3,11 +3,13 @@ package com.sbaiahmed1.reactnativeblur
3
3
  import android.content.Context
4
4
  import android.graphics.Color
5
5
  import android.graphics.drawable.ColorDrawable
6
+ import android.os.Build
6
7
  import android.util.AttributeSet
7
8
  import android.util.Log
8
9
  import android.view.ViewGroup
9
10
  import eightbitlab.com.blurview.BlurView
10
11
  import eightbitlab.com.blurview.RenderEffectBlur
12
+ import eightbitlab.com.blurview.RenderScriptBlur
11
13
 
12
14
  /**
13
15
  * Android implementation of React Native BlurView component.
@@ -20,6 +22,10 @@ class ReactNativeBlurView : BlurView {
20
22
  private var pendingStyleUpdate: Boolean = false
21
23
  private var originalBackgroundColor: Int? = null
22
24
  private var hasExplicitBackground: Boolean = false
25
+ private var glassTintColor: Int = Color.TRANSPARENT
26
+ private var glassOpacity: Float = 1.0f
27
+ private var viewType: String = "blur"
28
+ private var glassType: String = "clear"
23
29
 
24
30
  companion object {
25
31
  private const val TAG = "ReactNativeBlurView"
@@ -27,26 +33,26 @@ class ReactNativeBlurView : BlurView {
27
33
  private const val MAX_BLUR_RADIUS = 25f
28
34
  private const val DEFAULT_BLUR_RADIUS = 10f
29
35
  private const val DEBUG = false // Set to true for debug builds
30
-
36
+
31
37
  // Cross-platform blur amount constants
32
38
  private const val MIN_BLUR_AMOUNT = 0f
33
39
  private const val MAX_BLUR_AMOUNT = 100f
34
40
  private const val DEFAULT_BLUR_AMOUNT = 10f
35
-
41
+
36
42
  private fun logDebug(message: String) {
37
43
  if (DEBUG) {
38
44
  Log.d(TAG, message)
39
45
  }
40
46
  }
41
-
47
+
42
48
  private fun logWarning(message: String) {
43
49
  Log.w(TAG, message)
44
50
  }
45
-
51
+
46
52
  private fun logError(message: String, throwable: Throwable? = null) {
47
53
  Log.e(TAG, message, throwable)
48
54
  }
49
-
55
+
50
56
  /**
51
57
  * Maps blur amount (0-100) to Android blur radius (0-25).
52
58
  * This ensures cross-platform consistency while respecting Android's limitations.
@@ -62,11 +68,11 @@ class ReactNativeBlurView : BlurView {
62
68
  constructor(context: Context?) : super(context) {
63
69
  initializeBlur()
64
70
  }
65
-
71
+
66
72
  constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
67
73
  initializeBlur()
68
74
  }
69
-
75
+
70
76
  constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
71
77
  context,
72
78
  attrs,
@@ -84,21 +90,21 @@ class ReactNativeBlurView : BlurView {
84
90
  super.setBackgroundColor(Color.TRANSPARENT)
85
91
  logDebug("ReactNativeBlurView initialized")
86
92
  }
87
-
93
+
88
94
  /**
89
95
  * Override setBackgroundColor to handle blur setup timing and background preservation.
90
96
  * @param color The background color to apply
91
97
  */
92
98
  override fun setBackgroundColor(color: Int) {
93
99
  logDebug("setBackgroundColor called: $color (isSetup: $isSetup)")
94
-
100
+
95
101
  // Store the original background color if it's not transparent
96
102
  if (color != Color.TRANSPARENT) {
97
103
  originalBackgroundColor = color
98
104
  hasExplicitBackground = true
99
105
  logDebug("Stored explicit background color: $color")
100
106
  }
101
-
107
+
102
108
  // If blur is not setup yet, defer setting the background
103
109
  if (!isSetup) {
104
110
  logDebug("Blur not setup, deferring background color")
@@ -112,7 +118,7 @@ class ReactNativeBlurView : BlurView {
112
118
  }
113
119
  return
114
120
  }
115
-
121
+
116
122
  // If blur is setup and we have an explicit background, apply it carefully
117
123
  if (hasExplicitBackground && color != Color.TRANSPARENT) {
118
124
  logDebug("Applying background color over blur: $color")
@@ -122,17 +128,17 @@ class ReactNativeBlurView : BlurView {
122
128
  super.setBackgroundColor(Color.TRANSPARENT)
123
129
  }
124
130
  }
125
-
131
+
126
132
  /**
127
133
  * Override setAlpha to handle blur setup timing.
128
134
  * @param alpha The alpha value to apply
129
135
  */
130
136
  override fun setAlpha(alpha: Float) {
131
137
  logDebug("setAlpha called: $alpha (isSetup: $isSetup)")
132
-
138
+
133
139
  // Always apply alpha changes immediately as they don't interfere with blur setup
134
140
  super.setAlpha(alpha)
135
-
141
+
136
142
  // If blur is not setup yet, trigger setup attempt
137
143
  if (!isSetup && isAttachedToWindow) {
138
144
  pendingStyleUpdate = true
@@ -144,17 +150,17 @@ class ReactNativeBlurView : BlurView {
144
150
  }
145
151
  }
146
152
  }
147
-
153
+
148
154
  /**
149
155
  * Override setElevation to handle blur setup timing.
150
156
  * @param elevation The elevation value to apply
151
157
  */
152
158
  override fun setElevation(elevation: Float) {
153
159
  logDebug("setElevation called: $elevation (isSetup: $isSetup)")
154
-
160
+
155
161
  // Always apply elevation changes immediately
156
162
  super.setElevation(elevation)
157
-
163
+
158
164
  // If blur is not setup yet, trigger setup attempt
159
165
  if (!isSetup && isAttachedToWindow) {
160
166
  pendingStyleUpdate = true
@@ -175,7 +181,7 @@ class ReactNativeBlurView : BlurView {
175
181
  super.onAttachedToWindow()
176
182
  setupBlurView()
177
183
  }
178
-
184
+
179
185
  /**
180
186
  * Called when the view is detached from a window.
181
187
  * Performs cleanup to prevent memory leaks.
@@ -184,7 +190,7 @@ class ReactNativeBlurView : BlurView {
184
190
  super.onDetachedFromWindow()
185
191
  cleanup()
186
192
  }
187
-
193
+
188
194
  /**
189
195
  * Cleanup method to reset state and remove pending callbacks.
190
196
  * Helps prevent memory leaks and ensures clean state.
@@ -205,36 +211,62 @@ class ReactNativeBlurView : BlurView {
205
211
  */
206
212
  private fun setupBlurView() {
207
213
  if (isSetup) return
208
-
214
+
209
215
  try {
210
216
  val rootView = findRootView()
211
-
217
+
212
218
  rootView?.let { root ->
213
- // Setup the blur view with RenderEffect for better performance and modern API
214
- this.setupWith(root, RenderEffectBlur())
219
+ try {
220
+ // Choose blur algorithm based on Android API level
221
+ val blurAlgorithm = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
222
+ // Android 12+ (API 31+): Use RenderEffectBlur for better performance
223
+ logDebug("Using RenderEffectBlur for API ${Build.VERSION.SDK_INT}")
224
+ RenderEffectBlur()
225
+ } else {
226
+ // Android 10-11 (API < 31): Use RenderScriptBlur for compatibility
227
+ logDebug("Using RenderScriptBlur for API ${Build.VERSION.SDK_INT}")
228
+ try {
229
+ RenderScriptBlur(context)
230
+ } catch (e: Exception) {
231
+ logWarning("RenderScriptBlur not supported on this device: ${e.message}")
232
+ // Fallback: return null to trigger transparent background fallback
233
+ throw UnsupportedOperationException("Blur not supported on this device", e)
234
+ }
235
+ }
236
+
237
+ // Setup the blur view with the appropriate algorithm
238
+ this.setupWith(root, blurAlgorithm)
215
239
  .setBlurRadius(blurRadius)
216
240
  .setOverlayColor(overlayColor)
217
-
241
+
218
242
  isSetup = true
219
243
  pendingStyleUpdate = false
220
-
244
+
221
245
  // Apply any pending background color after blur setup
222
246
  if (hasExplicitBackground && originalBackgroundColor != null) {
223
247
  logDebug("Applying pending background color: $originalBackgroundColor")
224
248
  super.setBackgroundColor(originalBackgroundColor!!)
225
249
  }
226
-
227
- logDebug("Blur setup successful with root: ${root.javaClass.simpleName}")
250
+
251
+ logDebug("Blur setup successful with root: ${root.javaClass.simpleName}")} catch (e: Exception) {
252
+ logWarning("Failed to setup blur algorithm: ${e.message}")
253
+ // Fallback: use semi-transparent overlay when blur is unsupported
254
+ super.setBackgroundColor(overlayColor)
255
+ isSetup = true // Mark as setup to prevent retry loops
256
+ }
228
257
  } ?: run {
229
258
  logWarning("No suitable root view found for blur setup")
259
+ // Use semi-transparent overlay when no root view is available
260
+ super.setBackgroundColor(overlayColor)
261
+ isSetup = true
230
262
  }
231
263
  } catch (e: Exception) {
232
- // Fallback: set transparent background to avoid yellow tint
233
- super.setBackgroundColor(Color.TRANSPARENT)
264
+ // Fallback: use semi-transparent overlay to avoid visual issues
265
+ super.setBackgroundColor(overlayColor)
234
266
  logError("Failed to setup blur: ${e.message}", e)
235
267
  }
236
268
  }
237
-
269
+
238
270
  /**
239
271
  * Find the root view using multiple strategies.
240
272
  * @return The root ViewGroup or null if not found
@@ -248,7 +280,7 @@ class ReactNativeBlurView : BlurView {
248
280
  }
249
281
  parent = parent.parent
250
282
  }
251
-
283
+
252
284
  // Strategy 2: If content view not found, use the activity's root view
253
285
  try {
254
286
  val activity = context as? android.app.Activity
@@ -258,7 +290,7 @@ class ReactNativeBlurView : BlurView {
258
290
  } catch (e: Exception) {
259
291
  logDebug("Could not access activity root view: ${e.message}")
260
292
  }
261
-
293
+
262
294
  // Strategy 3: Fallback to immediate parent
263
295
  return this.parent as? ViewGroup
264
296
  }
@@ -270,7 +302,7 @@ class ReactNativeBlurView : BlurView {
270
302
  fun setBlurAmount(amount: Float) {
271
303
  blurRadius = mapBlurAmountToRadius(amount)
272
304
  logDebug("setBlurAmount: $amount -> $blurRadius (mapped from 0-100 to 0-25 range, isSetup: $isSetup)")
273
-
305
+
274
306
  if (isSetup) {
275
307
  try {
276
308
  setBlurRadius(blurRadius)
@@ -296,7 +328,7 @@ class ReactNativeBlurView : BlurView {
296
328
  SYSTEM_MATERIAL(Color.argb(50, 255, 255, 255)),
297
329
  SYSTEM_THICK_MATERIAL(Color.argb(65, 255, 255, 255)),
298
330
  SYSTEM_CHROME_MATERIAL(Color.argb(45, 240, 240, 240));
299
-
331
+
300
332
  companion object {
301
333
  /**
302
334
  * Get BlurType from string, with fallback to LIGHT for unknown types.
@@ -319,7 +351,7 @@ class ReactNativeBlurView : BlurView {
319
351
  }
320
352
  }
321
353
  }
322
-
354
+
323
355
  /**
324
356
  * Set the blur type which determines the overlay color.
325
357
  * @param type The blur type string (case-insensitive)
@@ -328,7 +360,7 @@ class ReactNativeBlurView : BlurView {
328
360
  val blurType = BlurType.fromString(type)
329
361
  overlayColor = blurType.overlayColor
330
362
  logDebug("setBlurType: $type -> ${blurType.name} (isSetup: $isSetup)")
331
-
363
+
332
364
  if (isSetup) {
333
365
  try {
334
366
  setOverlayColor(overlayColor)
@@ -347,12 +379,12 @@ class ReactNativeBlurView : BlurView {
347
379
  try {
348
380
  val fallbackColor = Color.parseColor(it)
349
381
  logDebug("setReducedTransparencyFallbackColor: $color -> $fallbackColor (stored but not applied unless accessibility requires it)")
350
-
382
+
351
383
  // Store the fallback color but don't apply it unless accessibility settings require it
352
- // For now, we'll just log it since Android doesn't have a direct equivalent to iOS's
384
+ // For now, we'll just log it since Android doesn't have a direct equivalent to iOS's
353
385
  // "Reduce Transparency" setting that we can easily check
354
386
  // The blur effect should remain the primary visual
355
-
387
+
356
388
  } catch (e: Exception) {
357
389
  logWarning("Invalid color format for reduced transparency fallback: $color")
358
390
  }
@@ -360,4 +392,97 @@ class ReactNativeBlurView : BlurView {
360
392
  logDebug("Cleared reduced transparency fallback color")
361
393
  }
362
394
  }
395
+
396
+ /**
397
+ * Set the glass tint color for liquid glass effect.
398
+ * @param color The color string in hex format (e.g., "#FF0000") or null to clear
399
+ */
400
+ fun setGlassTintColor(color: String?) {
401
+ color?.let {
402
+ try {
403
+ glassTintColor = Color.parseColor(it)
404
+ logDebug("setGlassTintColor: $color -> $glassTintColor")
405
+ updateGlassEffect()
406
+ } catch (e: Exception) {
407
+ logWarning("Invalid color format for glass tint: $color")
408
+ glassTintColor = Color.TRANSPARENT
409
+ }
410
+ } ?: run {
411
+ glassTintColor = Color.TRANSPARENT
412
+ logDebug("Cleared glass tint color")
413
+ updateGlassEffect()
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Set the glass opacity for liquid glass effect.
419
+ * @param opacity The opacity value (0.0 to 1.0)
420
+ */
421
+ fun setGlassOpacity(opacity: Float) {
422
+ glassOpacity = opacity.coerceIn(0.0f, 1.0f)
423
+ logDebug("setGlassOpacity: $opacity")
424
+ updateGlassEffect()
425
+ }
426
+
427
+ /**
428
+ * Set the view type (blur or liquidGlass).
429
+ * @param type The view type string
430
+ */
431
+ fun setType(type: String) {
432
+ viewType = type
433
+ logDebug("setType: $type")
434
+ updateViewType()
435
+ }
436
+
437
+ /**
438
+ * Set the glass type for liquid glass effect.
439
+ * @param type The glass type string
440
+ */
441
+ fun setGlassType(type: String) {
442
+ glassType = type
443
+ logDebug("setGlassType: $type")
444
+ updateGlassEffect()
445
+ }
446
+
447
+ /**
448
+ * Update the glass effect based on current glass properties.
449
+ */
450
+ private fun updateGlassEffect() {
451
+ if (viewType == "liquidGlass" && isSetup) {
452
+ try {
453
+ // Apply glass tint with opacity
454
+ val glassColor = Color.argb(
455
+ (glassOpacity * 255).toInt(),
456
+ Color.red(glassTintColor),
457
+ Color.green(glassTintColor),
458
+ Color.blue(glassTintColor)
459
+ )
460
+ setOverlayColor(glassColor)
461
+ logDebug("Applied glass effect: color=$glassColor, opacity=$glassOpacity")
462
+ } catch (e: Exception) {
463
+ logError("Failed to update glass effect: ${e.message}", e)
464
+ }
465
+ }
466
+ }
467
+
468
+ /**
469
+ * Update the view type and apply appropriate effects.
470
+ */
471
+ private fun updateViewType() {
472
+ when (viewType) {
473
+ "liquidGlass" -> {
474
+ updateGlassEffect()
475
+ }
476
+ "blur" -> {
477
+ // Restore original blur overlay color
478
+ if (isSetup) {
479
+ try {
480
+ setOverlayColor(overlayColor)
481
+ } catch (e: Exception) {
482
+ logError("Failed to restore blur overlay: ${e.message}", e)
483
+ }
484
+ }
485
+ }
486
+ }
487
+ }
363
488
  }
@@ -44,6 +44,26 @@ class ReactNativeBlurViewManager : ViewGroupManager<ReactNativeBlurView>(),
44
44
  view?.setReducedTransparencyFallbackColor(reducedTransparencyFallbackColor)
45
45
  }
46
46
 
47
+ @ReactProp(name = "glassTintColor")
48
+ override fun setGlassTintColor(view: ReactNativeBlurView?, glassTintColor: String?) {
49
+ view?.setGlassTintColor(glassTintColor)
50
+ }
51
+
52
+ @ReactProp(name = "glassOpacity")
53
+ override fun setGlassOpacity(view: ReactNativeBlurView?, glassOpacity: Double) {
54
+ view?.setGlassOpacity(glassOpacity.toFloat())
55
+ }
56
+
57
+ @ReactProp(name = "type")
58
+ override fun setType(view: ReactNativeBlurView?, type: String?) {
59
+ view?.setType(type ?: "blur")
60
+ }
61
+
62
+ @ReactProp(name = "glassType")
63
+ override fun setGlassType(view: ReactNativeBlurView?, glassType: String?) {
64
+ view?.setGlassType(glassType ?: "clear")
65
+ }
66
+
47
67
  companion object {
48
68
  const val NAME = "ReactNativeBlurView"
49
69
  }