@sbaiahmed1/react-native-blur 0.2.1 → 0.3.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 (31) hide show
  1. package/README.md +345 -106
  2. package/ReactNativeBlur.podspec +2 -1
  3. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeBlurViewManagerDelegate.java +18 -3
  4. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeBlurViewManagerInterface.java +6 -1
  5. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeGlassEffectContainerManagerDelegate.java +53 -0
  6. package/android/app/build/generated/source/codegen/java/com/facebook/react/viewmanagers/ReactNativeGlassEffectContainerManagerInterface.java +25 -0
  7. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ComponentDescriptors.cpp +1 -1
  8. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ComponentDescriptors.h +1 -1
  9. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/EventEmitters.h +1 -1
  10. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/Props.cpp +17 -7
  11. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/Props.h +55 -15
  12. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ShadowNodes.cpp +1 -1
  13. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/ShadowNodes.h +7 -7
  14. package/android/app/build/generated/source/codegen/jni/react/renderer/components/ReactNativeBlurViewSpec/States.h +3 -3
  15. package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurView.kt +150 -46
  16. package/android/src/main/java/com/sbaiahmed1/reactnativeblur/ReactNativeBlurViewManager.kt +25 -0
  17. package/ios/ReactNativeBlurView.mm +197 -237
  18. package/ios/ReactNativeBlurView.swift +321 -0
  19. package/ios/ReactNativeBlurViewManager.h +5 -0
  20. package/ios/ReactNativeBlurViewManager.m +171 -0
  21. package/lib/module/BlurView.js +17 -2
  22. package/lib/module/BlurView.js.map +1 -1
  23. package/lib/module/ReactNativeBlurViewNativeComponent.ts +10 -3
  24. package/lib/typescript/src/BlurView.d.ts +36 -1
  25. package/lib/typescript/src/BlurView.d.ts.map +1 -1
  26. package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts +9 -3
  27. package/lib/typescript/src/ReactNativeBlurViewNativeComponent.d.ts.map +1 -1
  28. package/package.json +1 -1
  29. package/src/BlurView.tsx +58 -3
  30. package/src/ReactNativeBlurViewNativeComponent.ts +10 -3
  31. package/ios/ReactNativeBlurViewManager.mm +0 -23
@@ -22,6 +22,10 @@ class ReactNativeBlurView : BlurView {
22
22
  private var pendingStyleUpdate: Boolean = false
23
23
  private var originalBackgroundColor: Int? = null
24
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"
25
29
 
26
30
  companion object {
27
31
  private const val TAG = "ReactNativeBlurView"
@@ -29,26 +33,26 @@ class ReactNativeBlurView : BlurView {
29
33
  private const val MAX_BLUR_RADIUS = 25f
30
34
  private const val DEFAULT_BLUR_RADIUS = 10f
31
35
  private const val DEBUG = false // Set to true for debug builds
32
-
36
+
33
37
  // Cross-platform blur amount constants
34
38
  private const val MIN_BLUR_AMOUNT = 0f
35
39
  private const val MAX_BLUR_AMOUNT = 100f
36
40
  private const val DEFAULT_BLUR_AMOUNT = 10f
37
-
41
+
38
42
  private fun logDebug(message: String) {
39
43
  if (DEBUG) {
40
44
  Log.d(TAG, message)
41
45
  }
42
46
  }
43
-
47
+
44
48
  private fun logWarning(message: String) {
45
49
  Log.w(TAG, message)
46
50
  }
47
-
51
+
48
52
  private fun logError(message: String, throwable: Throwable? = null) {
49
53
  Log.e(TAG, message, throwable)
50
54
  }
51
-
55
+
52
56
  /**
53
57
  * Maps blur amount (0-100) to Android blur radius (0-25).
54
58
  * This ensures cross-platform consistency while respecting Android's limitations.
@@ -64,11 +68,11 @@ class ReactNativeBlurView : BlurView {
64
68
  constructor(context: Context?) : super(context) {
65
69
  initializeBlur()
66
70
  }
67
-
71
+
68
72
  constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
69
73
  initializeBlur()
70
74
  }
71
-
75
+
72
76
  constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
73
77
  context,
74
78
  attrs,
@@ -86,21 +90,21 @@ class ReactNativeBlurView : BlurView {
86
90
  super.setBackgroundColor(Color.TRANSPARENT)
87
91
  logDebug("ReactNativeBlurView initialized")
88
92
  }
89
-
93
+
90
94
  /**
91
95
  * Override setBackgroundColor to handle blur setup timing and background preservation.
92
96
  * @param color The background color to apply
93
97
  */
94
98
  override fun setBackgroundColor(color: Int) {
95
99
  logDebug("setBackgroundColor called: $color (isSetup: $isSetup)")
96
-
100
+
97
101
  // Store the original background color if it's not transparent
98
102
  if (color != Color.TRANSPARENT) {
99
103
  originalBackgroundColor = color
100
104
  hasExplicitBackground = true
101
105
  logDebug("Stored explicit background color: $color")
102
106
  }
103
-
107
+
104
108
  // If blur is not setup yet, defer setting the background
105
109
  if (!isSetup) {
106
110
  logDebug("Blur not setup, deferring background color")
@@ -114,7 +118,7 @@ class ReactNativeBlurView : BlurView {
114
118
  }
115
119
  return
116
120
  }
117
-
121
+
118
122
  // If blur is setup and we have an explicit background, apply it carefully
119
123
  if (hasExplicitBackground && color != Color.TRANSPARENT) {
120
124
  logDebug("Applying background color over blur: $color")
@@ -124,17 +128,17 @@ class ReactNativeBlurView : BlurView {
124
128
  super.setBackgroundColor(Color.TRANSPARENT)
125
129
  }
126
130
  }
127
-
131
+
128
132
  /**
129
133
  * Override setAlpha to handle blur setup timing.
130
134
  * @param alpha The alpha value to apply
131
135
  */
132
136
  override fun setAlpha(alpha: Float) {
133
137
  logDebug("setAlpha called: $alpha (isSetup: $isSetup)")
134
-
138
+
135
139
  // Always apply alpha changes immediately as they don't interfere with blur setup
136
140
  super.setAlpha(alpha)
137
-
141
+
138
142
  // If blur is not setup yet, trigger setup attempt
139
143
  if (!isSetup && isAttachedToWindow) {
140
144
  pendingStyleUpdate = true
@@ -146,17 +150,17 @@ class ReactNativeBlurView : BlurView {
146
150
  }
147
151
  }
148
152
  }
149
-
153
+
150
154
  /**
151
155
  * Override setElevation to handle blur setup timing.
152
156
  * @param elevation The elevation value to apply
153
157
  */
154
158
  override fun setElevation(elevation: Float) {
155
159
  logDebug("setElevation called: $elevation (isSetup: $isSetup)")
156
-
160
+
157
161
  // Always apply elevation changes immediately
158
162
  super.setElevation(elevation)
159
-
163
+
160
164
  // If blur is not setup yet, trigger setup attempt
161
165
  if (!isSetup && isAttachedToWindow) {
162
166
  pendingStyleUpdate = true
@@ -177,7 +181,7 @@ class ReactNativeBlurView : BlurView {
177
181
  super.onAttachedToWindow()
178
182
  setupBlurView()
179
183
  }
180
-
184
+
181
185
  /**
182
186
  * Called when the view is detached from a window.
183
187
  * Performs cleanup to prevent memory leaks.
@@ -186,7 +190,7 @@ class ReactNativeBlurView : BlurView {
186
190
  super.onDetachedFromWindow()
187
191
  cleanup()
188
192
  }
189
-
193
+
190
194
  /**
191
195
  * Cleanup method to reset state and remove pending callbacks.
192
196
  * Helps prevent memory leaks and ensures clean state.
@@ -207,10 +211,10 @@ class ReactNativeBlurView : BlurView {
207
211
  */
208
212
  private fun setupBlurView() {
209
213
  if (isSetup) return
210
-
214
+
211
215
  try {
212
216
  val rootView = findRootView()
213
-
217
+
214
218
  rootView?.let { root ->
215
219
  try {
216
220
  // Choose blur algorithm based on Android API level
@@ -229,23 +233,22 @@ class ReactNativeBlurView : BlurView {
229
233
  throw UnsupportedOperationException("Blur not supported on this device", e)
230
234
  }
231
235
  }
232
-
236
+
233
237
  // Setup the blur view with the appropriate algorithm
234
238
  this.setupWith(root, blurAlgorithm)
235
- .setBlurRadius(blurRadius)
236
- .setOverlayColor(overlayColor)
237
-
238
- isSetup = true
239
- pendingStyleUpdate = false
240
-
241
- // Apply any pending background color after blur setup
242
- if (hasExplicitBackground && originalBackgroundColor != null) {
243
- logDebug("Applying pending background color: $originalBackgroundColor")
244
- super.setBackgroundColor(originalBackgroundColor!!)
245
- }
246
-
247
- logDebug("Blur setup successful with root: ${root.javaClass.simpleName}")
248
- } catch (e: Exception) {
239
+ .setBlurRadius(blurRadius)
240
+ .setOverlayColor(overlayColor)
241
+
242
+ isSetup = true
243
+ pendingStyleUpdate = false
244
+
245
+ // Apply any pending background color after blur setup
246
+ if (hasExplicitBackground && originalBackgroundColor != null) {
247
+ logDebug("Applying pending background color: $originalBackgroundColor")
248
+ super.setBackgroundColor(originalBackgroundColor!!)
249
+ }
250
+
251
+ logDebug("Blur setup successful with root: ${root.javaClass.simpleName}")} catch (e: Exception) {
249
252
  logWarning("Failed to setup blur algorithm: ${e.message}")
250
253
  // Fallback: use semi-transparent overlay when blur is unsupported
251
254
  super.setBackgroundColor(overlayColor)
@@ -263,7 +266,7 @@ class ReactNativeBlurView : BlurView {
263
266
  logError("Failed to setup blur: ${e.message}", e)
264
267
  }
265
268
  }
266
-
269
+
267
270
  /**
268
271
  * Find the root view using multiple strategies.
269
272
  * @return The root ViewGroup or null if not found
@@ -277,7 +280,7 @@ class ReactNativeBlurView : BlurView {
277
280
  }
278
281
  parent = parent.parent
279
282
  }
280
-
283
+
281
284
  // Strategy 2: If content view not found, use the activity's root view
282
285
  try {
283
286
  val activity = context as? android.app.Activity
@@ -287,7 +290,7 @@ class ReactNativeBlurView : BlurView {
287
290
  } catch (e: Exception) {
288
291
  logDebug("Could not access activity root view: ${e.message}")
289
292
  }
290
-
293
+
291
294
  // Strategy 3: Fallback to immediate parent
292
295
  return this.parent as? ViewGroup
293
296
  }
@@ -299,7 +302,7 @@ class ReactNativeBlurView : BlurView {
299
302
  fun setBlurAmount(amount: Float) {
300
303
  blurRadius = mapBlurAmountToRadius(amount)
301
304
  logDebug("setBlurAmount: $amount -> $blurRadius (mapped from 0-100 to 0-25 range, isSetup: $isSetup)")
302
-
305
+
303
306
  if (isSetup) {
304
307
  try {
305
308
  setBlurRadius(blurRadius)
@@ -325,7 +328,7 @@ class ReactNativeBlurView : BlurView {
325
328
  SYSTEM_MATERIAL(Color.argb(50, 255, 255, 255)),
326
329
  SYSTEM_THICK_MATERIAL(Color.argb(65, 255, 255, 255)),
327
330
  SYSTEM_CHROME_MATERIAL(Color.argb(45, 240, 240, 240));
328
-
331
+
329
332
  companion object {
330
333
  /**
331
334
  * Get BlurType from string, with fallback to LIGHT for unknown types.
@@ -348,7 +351,7 @@ class ReactNativeBlurView : BlurView {
348
351
  }
349
352
  }
350
353
  }
351
-
354
+
352
355
  /**
353
356
  * Set the blur type which determines the overlay color.
354
357
  * @param type The blur type string (case-insensitive)
@@ -357,7 +360,7 @@ class ReactNativeBlurView : BlurView {
357
360
  val blurType = BlurType.fromString(type)
358
361
  overlayColor = blurType.overlayColor
359
362
  logDebug("setBlurType: $type -> ${blurType.name} (isSetup: $isSetup)")
360
-
363
+
361
364
  if (isSetup) {
362
365
  try {
363
366
  setOverlayColor(overlayColor)
@@ -376,12 +379,12 @@ class ReactNativeBlurView : BlurView {
376
379
  try {
377
380
  val fallbackColor = Color.parseColor(it)
378
381
  logDebug("setReducedTransparencyFallbackColor: $color -> $fallbackColor (stored but not applied unless accessibility requires it)")
379
-
382
+
380
383
  // Store the fallback color but don't apply it unless accessibility settings require it
381
- // 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
382
385
  // "Reduce Transparency" setting that we can easily check
383
386
  // The blur effect should remain the primary visual
384
-
387
+
385
388
  } catch (e: Exception) {
386
389
  logWarning("Invalid color format for reduced transparency fallback: $color")
387
390
  }
@@ -389,4 +392,105 @@ class ReactNativeBlurView : BlurView {
389
392
  logDebug("Cleared reduced transparency fallback color")
390
393
  }
391
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 view type (blur or liquidGlass).
439
+ * @param type The view type string
440
+ */
441
+ fun setIsInteractive(isInteractive: Boolean) {
442
+ logDebug("setType: $isInteractive")
443
+ }
444
+
445
+ /**
446
+ * Set the glass type for liquid glass effect.
447
+ * @param type The glass type string
448
+ */
449
+ fun setGlassType(type: String) {
450
+ glassType = type
451
+ logDebug("setGlassType: $type")
452
+ updateGlassEffect()
453
+ }
454
+
455
+ /**
456
+ * Update the glass effect based on current glass properties.
457
+ */
458
+ private fun updateGlassEffect() {
459
+ if (viewType == "liquidGlass" && isSetup) {
460
+ try {
461
+ // Apply glass tint with opacity
462
+ val glassColor = Color.argb(
463
+ (glassOpacity * 255).toInt(),
464
+ Color.red(glassTintColor),
465
+ Color.green(glassTintColor),
466
+ Color.blue(glassTintColor)
467
+ )
468
+ setOverlayColor(glassColor)
469
+ logDebug("Applied glass effect: color=$glassColor, opacity=$glassOpacity")
470
+ } catch (e: Exception) {
471
+ logError("Failed to update glass effect: ${e.message}", e)
472
+ }
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Update the view type and apply appropriate effects.
478
+ */
479
+ private fun updateViewType() {
480
+ when (viewType) {
481
+ "liquidGlass" -> {
482
+ updateGlassEffect()
483
+ }
484
+ "blur" -> {
485
+ // Restore original blur overlay color
486
+ if (isSetup) {
487
+ try {
488
+ setOverlayColor(overlayColor)
489
+ } catch (e: Exception) {
490
+ logError("Failed to restore blur overlay: ${e.message}", e)
491
+ }
492
+ }
493
+ }
494
+ }
495
+ }
392
496
  }
@@ -44,6 +44,31 @@ 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
+
67
+ @ReactProp(name = "isInteractive")
68
+ override fun setIsInteractive(view: ReactNativeBlurView?, isInteractive: Boolean) {
69
+ view?.setIsInteractive(isInteractive)
70
+ }
71
+
47
72
  companion object {
48
73
  const val NAME = "ReactNativeBlurView"
49
74
  }