react-native-blur-vibe 0.1.0 → 0.1.1
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
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# React Native Blur-Vibe
|
|
2
|
+
|
|
3
|
+
<img width="1500" height="500" alt="github-banner" src="https://github.com/user-attachments/assets/78b2e5ec-5b57-48c0-b984-69cb57cbcf26" />
|
|
4
|
+
<br></br>
|
|
5
|
+
A modern, actively maintained blur view for React Native. Works on <b>iOS</b> and <b>Android</b> with full New Architecture (Fabric) support.
|
|
4
6
|
|
|
5
7
|
> The key difference from other blur libraries: `overlayColor` works on **both iOS and Android** — letting you control blur visibility the same way CSS `backdrop-filter` + `background-color` works on the web.
|
|
6
|
-
|
|
8
|
+
<br></br>
|
|
7
9
|
[](https://www.npmjs.com/package/react-native-blur-vibe)
|
|
8
10
|
[](https://github.com/I-am-Pritam-20/react-native-blur-vibe/actions/workflows/build-ios.yml)
|
|
9
11
|
[](https://github.com/I-am-Pritam-20/react-native-blur-vibe/actions/workflows/build-android.yml)
|
|
@@ -46,6 +48,20 @@ The `overlayColor` alpha channel is what controls blur visibility:
|
|
|
46
48
|
**This works on both iOS and Android.** Not just Android like other libraries.
|
|
47
49
|
|
|
48
50
|
---
|
|
51
|
+
|
|
52
|
+
<details>
|
|
53
|
+
<summary><h3>Screenshots (Expand to see)</h3></summary>
|
|
54
|
+
<table>
|
|
55
|
+
<tr>
|
|
56
|
+
<td align="center"> <h3>Android</h3>
|
|
57
|
+
<img width="244" height="462" alt="Android-Demo" src="https://github.com/user-attachments/assets/e1cd120e-1ce1-4bba-aef1-4182aa023fbb" />
|
|
58
|
+
</td>
|
|
59
|
+
<td align="center"> <h3>iOS</h3>
|
|
60
|
+
<img width="244" height="462" alt="iPhone-Demo" src="https://github.com/user-attachments/assets/4b8ad035-d2ff-471e-b3e6-a645c87ea066" />
|
|
61
|
+
</td>
|
|
62
|
+
</tr>
|
|
63
|
+
</table>
|
|
64
|
+
</details>
|
|
49
65
|
|
|
50
66
|
## Installation
|
|
51
67
|
|
|
@@ -19,11 +19,14 @@ import android.widget.FrameLayout
|
|
|
19
19
|
/**
|
|
20
20
|
* BlurVibeView — Android implementation
|
|
21
21
|
*
|
|
22
|
-
* API 31+
|
|
23
|
-
* API 24-30: RenderScript (built
|
|
22
|
+
* API 31+ : RenderEffect (hardware accelerated)
|
|
23
|
+
* API 24-30: RenderScript (built-in SDK, no extra dep)
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* Color props (overlayColor, reducedTransparencyFallbackColor) are
|
|
26
|
+
* received as hex strings from JS and parsed manually here.
|
|
27
|
+
* This gives full control over alpha channel handling.
|
|
28
|
+
*
|
|
29
|
+
* Supports: "#RGB" "#RRGGBB" "#RRGGBBAA" "transparent"
|
|
27
30
|
*/
|
|
28
31
|
@SuppressLint("NewApi")
|
|
29
32
|
class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
@@ -31,7 +34,7 @@ class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
|
31
34
|
private val overlayView = View(context)
|
|
32
35
|
private var blurAmountValue: Float = 10f
|
|
33
36
|
private var overlayColorValue: Int = Color.TRANSPARENT
|
|
34
|
-
private var
|
|
37
|
+
private var fallbackColorValue: Int = Color.parseColor("#F2F2F2")
|
|
35
38
|
private var blurRadiusDownscale: Int = 4
|
|
36
39
|
|
|
37
40
|
init {
|
|
@@ -43,18 +46,20 @@ class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
|
43
46
|
applyBlur()
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
// MARK: - Public setters (called by ViewManager)
|
|
50
|
+
|
|
46
51
|
fun setBlurAmount(amount: Float) {
|
|
47
52
|
blurAmountValue = amount.coerceIn(0f, 100f)
|
|
48
53
|
applyBlur()
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
fun setOverlayColor(
|
|
52
|
-
overlayColorValue =
|
|
56
|
+
fun setOverlayColor(colorString: String) {
|
|
57
|
+
overlayColorValue = parseHexColor(colorString) ?: Color.TRANSPARENT
|
|
53
58
|
updateOverlay()
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
fun setReducedTransparencyFallbackColor(
|
|
57
|
-
|
|
61
|
+
fun setReducedTransparencyFallbackColor(colorString: String) {
|
|
62
|
+
fallbackColorValue = parseHexColor(colorString) ?: Color.parseColor("#F2F2F2")
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
fun setBlurRadius(radius: Int) {
|
|
@@ -62,6 +67,8 @@ class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
|
62
67
|
applyBlur()
|
|
63
68
|
}
|
|
64
69
|
|
|
70
|
+
// MARK: - Blur
|
|
71
|
+
|
|
65
72
|
private fun applyBlur() {
|
|
66
73
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
67
74
|
applyRenderEffect()
|
|
@@ -106,10 +113,12 @@ class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
|
106
113
|
|
|
107
114
|
background = android.graphics.drawable.BitmapDrawable(resources, bitmap)
|
|
108
115
|
} catch (e: Exception) {
|
|
109
|
-
setBackgroundColor(
|
|
116
|
+
setBackgroundColor(fallbackColorValue)
|
|
110
117
|
}
|
|
111
118
|
}
|
|
112
119
|
|
|
120
|
+
// MARK: - Overlay
|
|
121
|
+
|
|
113
122
|
private fun updateOverlay() {
|
|
114
123
|
overlayView.setBackgroundColor(overlayColorValue)
|
|
115
124
|
bringChildToFront(overlayView)
|
|
@@ -125,4 +134,41 @@ class BlurVibeView(context: Context) : FrameLayout(context) {
|
|
|
125
134
|
post { renderScriptBlur() }
|
|
126
135
|
}
|
|
127
136
|
}
|
|
137
|
+
|
|
138
|
+
// MARK: - Color parser
|
|
139
|
+
// Supports: "transparent", "#RGB", "#RRGGBB", "#RRGGBBAA"
|
|
140
|
+
// Returns null if unparseable (caller uses fallback)
|
|
141
|
+
private fun parseHexColor(colorString: String): Int? {
|
|
142
|
+
val s = colorString.trim()
|
|
143
|
+
if (s.equals("transparent", ignoreCase = true)) return Color.TRANSPARENT
|
|
144
|
+
if (!s.startsWith("#")) return null
|
|
145
|
+
|
|
146
|
+
val hex = s.removePrefix("#")
|
|
147
|
+
return try {
|
|
148
|
+
when (hex.length) {
|
|
149
|
+
3 -> { // #RGB → #RRGGBB
|
|
150
|
+
val r = hex[0].toString().repeat(2).toInt(16)
|
|
151
|
+
val g = hex[1].toString().repeat(2).toInt(16)
|
|
152
|
+
val b = hex[2].toString().repeat(2).toInt(16)
|
|
153
|
+
Color.argb(255, r, g, b)
|
|
154
|
+
}
|
|
155
|
+
6 -> { // #RRGGBB
|
|
156
|
+
val r = hex.substring(0, 2).toInt(16)
|
|
157
|
+
val g = hex.substring(2, 4).toInt(16)
|
|
158
|
+
val b = hex.substring(4, 6).toInt(16)
|
|
159
|
+
Color.argb(255, r, g, b)
|
|
160
|
+
}
|
|
161
|
+
8 -> { // #RRGGBBAA — note: AA is alpha, last two digits
|
|
162
|
+
val r = hex.substring(0, 2).toInt(16)
|
|
163
|
+
val g = hex.substring(2, 4).toInt(16)
|
|
164
|
+
val b = hex.substring(4, 6).toInt(16)
|
|
165
|
+
val a = hex.substring(6, 8).toInt(16)
|
|
166
|
+
Color.argb(a, r, g, b)
|
|
167
|
+
}
|
|
168
|
+
else -> null
|
|
169
|
+
}
|
|
170
|
+
} catch (e: NumberFormatException) {
|
|
171
|
+
null
|
|
172
|
+
}
|
|
173
|
+
}
|
|
128
174
|
}
|
|
@@ -10,26 +10,33 @@ class BlurVibeViewManager : SimpleViewManager<BlurVibeView>() {
|
|
|
10
10
|
|
|
11
11
|
override fun createViewInstance(context: ThemedReactContext) = BlurVibeView(context)
|
|
12
12
|
|
|
13
|
+
// Float — matches TS codegen Float type ✅
|
|
13
14
|
@ReactProp(name = "blurAmount", defaultFloat = 10f)
|
|
14
15
|
fun setBlurAmount(view: BlurVibeView, amount: Float) {
|
|
15
16
|
view.setBlurAmount(amount)
|
|
16
17
|
}
|
|
17
18
|
|
|
19
|
+
// String — matches TS codegen string type ✅ (no-op on Android)
|
|
18
20
|
@ReactProp(name = "blurType")
|
|
19
21
|
fun setBlurType(view: BlurVibeView, type: String?) {
|
|
20
22
|
// No-op on Android — blurType is iOS UIBlurEffectStyle only
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
// String — matches TS codegen string type ✅
|
|
26
|
+
// We parse hex manually in BlurVibeView for full alpha control
|
|
27
|
+
// Do NOT use Int with customType="Color" — RN reorders alpha bytes unexpectedly
|
|
23
28
|
@ReactProp(name = "overlayColor")
|
|
24
|
-
fun setOverlayColor(view: BlurVibeView, color:
|
|
25
|
-
view.setOverlayColor(color)
|
|
29
|
+
fun setOverlayColor(view: BlurVibeView, color: String?) {
|
|
30
|
+
view.setOverlayColor(color ?: "transparent")
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
// String — matches TS codegen string type ✅
|
|
28
34
|
@ReactProp(name = "reducedTransparencyFallbackColor")
|
|
29
|
-
fun setReducedTransparencyFallbackColor(view: BlurVibeView, color:
|
|
30
|
-
view.setReducedTransparencyFallbackColor(color)
|
|
35
|
+
fun setReducedTransparencyFallbackColor(view: BlurVibeView, color: String?) {
|
|
36
|
+
view.setReducedTransparencyFallbackColor(color ?: "#F2F2F2")
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
// Int32 — matches TS codegen Int32 type ✅
|
|
33
40
|
@ReactProp(name = "blurRadius", defaultInt = 4)
|
|
34
41
|
fun setBlurRadius(view: BlurVibeView, radius: Int) {
|
|
35
42
|
view.setBlurRadius(radius)
|
package/ios/BlurVibeView.swift
CHANGED
|
@@ -7,18 +7,25 @@ class BlurVibeView: UIView {
|
|
|
7
7
|
private var blurEffectView: UIVisualEffectView?
|
|
8
8
|
private let overlayView = UIView()
|
|
9
9
|
|
|
10
|
-
// MARK: -
|
|
10
|
+
// MARK: - Props
|
|
11
11
|
|
|
12
|
+
/// Blur intensity 0–100. Maps to UIBlurEffect intensity via animator.
|
|
12
13
|
@objc var blurAmount: NSNumber = 10 { didSet { updateBlur() } }
|
|
14
|
+
|
|
15
|
+
/// iOS blur style — maps to UIBlurEffectStyle
|
|
13
16
|
@objc var blurType: NSString = "light" { didSet { updateBlur() } }
|
|
14
17
|
|
|
15
|
-
/// Overlay color
|
|
16
|
-
/// Alpha
|
|
17
|
-
///
|
|
18
|
-
/// "#00000000" = pure blur, "#00000080" = tinted blur, "#000000FF" = hidden blur
|
|
18
|
+
/// Overlay color on top of blur. Works on iOS AND Android.
|
|
19
|
+
/// Alpha controls blur visibility — like CSS backdrop-filter + background-color.
|
|
20
|
+
/// Supports: "transparent", "#RGB", "#RRGGBB", "#RRGGBBAA"
|
|
19
21
|
@objc var overlayColor: NSString = "transparent" { didSet { updateOverlay() } }
|
|
22
|
+
|
|
23
|
+
/// Fallback color when Reduce Transparency is enabled.
|
|
20
24
|
@objc var reducedTransparencyFallbackColor: NSString = "#F2F2F2" { didSet { updateBlur() } }
|
|
21
25
|
|
|
26
|
+
/// Android-only downscale factor. Accepted on iOS to avoid prop warning — no-op.
|
|
27
|
+
@objc var blurRadius: NSNumber = 4
|
|
28
|
+
|
|
22
29
|
// MARK: - Init
|
|
23
30
|
override init(frame: CGRect) { super.init(frame: frame); commonInit() }
|
|
24
31
|
required init?(coder: NSCoder) { super.init(coder: coder); commonInit() }
|
|
@@ -47,7 +54,8 @@ class BlurVibeView: UIView {
|
|
|
47
54
|
if UIAccessibility.isReduceTransparencyEnabled {
|
|
48
55
|
blurEffectView?.removeFromSuperview()
|
|
49
56
|
blurEffectView = nil
|
|
50
|
-
backgroundColor = parseColor(reducedTransparencyFallbackColor as String)
|
|
57
|
+
backgroundColor = parseColor(reducedTransparencyFallbackColor as String)
|
|
58
|
+
?? UIColor(white: 0.95, alpha: 1)
|
|
51
59
|
return
|
|
52
60
|
}
|
|
53
61
|
backgroundColor = .clear
|
|
@@ -102,7 +110,8 @@ class BlurVibeView: UIView {
|
|
|
102
110
|
}
|
|
103
111
|
}
|
|
104
112
|
|
|
105
|
-
// MARK: - Color Parser
|
|
113
|
+
// MARK: - Color Parser
|
|
114
|
+
// Supports: "transparent", "#RGB", "#RRGGBB", "#RRGGBBAA"
|
|
106
115
|
private func parseColor(_ colorString: String) -> UIColor? {
|
|
107
116
|
var hex = colorString.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
108
117
|
guard hex.hasPrefix("#") else { return nil }
|
|
@@ -110,23 +119,26 @@ class BlurVibeView: UIView {
|
|
|
110
119
|
var rgbValue: UInt64 = 0
|
|
111
120
|
Scanner(string: hex).scanHexInt64(&rgbValue)
|
|
112
121
|
switch hex.count {
|
|
113
|
-
case 3:
|
|
122
|
+
case 3: // #RGB
|
|
114
123
|
return UIColor(
|
|
115
|
-
red:
|
|
124
|
+
red: CGFloat((rgbValue & 0xF00) >> 8) / 15,
|
|
116
125
|
green: CGFloat((rgbValue & 0x0F0) >> 4) / 15,
|
|
117
|
-
blue:
|
|
118
|
-
|
|
126
|
+
blue: CGFloat( rgbValue & 0x00F ) / 15,
|
|
127
|
+
alpha: 1)
|
|
128
|
+
case 6: // #RRGGBB
|
|
119
129
|
return UIColor(
|
|
120
|
-
red:
|
|
121
|
-
green: CGFloat((rgbValue & 0x00FF00) >>
|
|
122
|
-
blue:
|
|
130
|
+
red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255,
|
|
131
|
+
green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255,
|
|
132
|
+
blue: CGFloat( rgbValue & 0x0000FF ) / 255,
|
|
133
|
+
alpha: 1)
|
|
123
134
|
case 8: // #RRGGBBAA
|
|
124
135
|
return UIColor(
|
|
125
|
-
red:
|
|
136
|
+
red: CGFloat((rgbValue & 0xFF000000) >> 24) / 255,
|
|
126
137
|
green: CGFloat((rgbValue & 0x00FF0000) >> 16) / 255,
|
|
127
|
-
blue:
|
|
128
|
-
alpha: CGFloat(rgbValue & 0x000000FF) / 255)
|
|
129
|
-
default:
|
|
138
|
+
blue: CGFloat((rgbValue & 0x0000FF00) >> 8) / 255,
|
|
139
|
+
alpha: CGFloat( rgbValue & 0x000000FF ) / 255)
|
|
140
|
+
default:
|
|
141
|
+
return nil
|
|
130
142
|
}
|
|
131
143
|
}
|
|
132
144
|
}
|
|
@@ -6,4 +6,5 @@ RCT_EXTERN_MODULE(BlurVibeViewManager, RCTViewManager)
|
|
|
6
6
|
RCT_EXPORT_VIEW_PROPERTY(blurAmount, NSNumber)
|
|
7
7
|
RCT_EXPORT_VIEW_PROPERTY(blurType, NSString)
|
|
8
8
|
RCT_EXPORT_VIEW_PROPERTY(overlayColor, NSString)
|
|
9
|
-
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, NSString)
|
|
9
|
+
RCT_EXPORT_VIEW_PROPERTY(reducedTransparencyFallbackColor, NSString)
|
|
10
|
+
RCT_EXPORT_VIEW_PROPERTY(blurRadius, NSNumber)
|