@sbaiahmed1/react-native-blur 0.3.0 → 3.1.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.
- package/README.md +8 -40
- package/ReactNativeBlur.podspec +1 -0
- package/ios/Helpers/BlurStyleHelpers.swift +59 -0
- package/ios/Helpers/ReactNativeBlurViewHelper.swift +59 -0
- package/ios/ReactNativeBlurView.mm +6 -1
- package/ios/ReactNativeBlurViewManager.m +6 -0
- package/ios/Views/AdvancedBlurView.swift +94 -0
- package/ios/Views/BasicColoredView.swift +58 -0
- package/ios/Views/BlurEffectView.swift +70 -0
- package/package.json +1 -1
- package/ios/ReactNativeBlurView.swift +0 -321
package/README.md
CHANGED
|
@@ -16,17 +16,7 @@ A modern React Native blur view component that provides native blur effects and
|
|
|
16
16
|
</p>
|
|
17
17
|
</div>
|
|
18
18
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
<div align="center">
|
|
22
|
-
<br>
|
|
23
|
-
<em>Liquid Glass effect in action (iOS 26+ only)</em>
|
|
24
|
-
<br>
|
|
25
|
-
<strong>⚠️ Android automatically falls back to enhanced blur with tint overlay</strong>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
## Blur Demo
|
|
29
|
-
## Liquid Glass Demo
|
|
19
|
+
## Demo
|
|
30
20
|
|
|
31
21
|
<div align="center">
|
|
32
22
|
<img src="ios-blur-glass-demo.gif" alt="iOS Demo" width="300" />
|
|
@@ -34,7 +24,7 @@ A modern React Native blur view component that provides native blur effects and
|
|
|
34
24
|
|
|
35
25
|
<br>
|
|
36
26
|
<em>iOS (left) and Android (right) blur effects in action</em>
|
|
37
|
-
|
|
27
|
+
<br>
|
|
38
28
|
<em>Liquid Glass effect in action (iOS 26+ only)</em>
|
|
39
29
|
<br>
|
|
40
30
|
<strong>⚠️ Android automatically falls back to enhanced blur with tint overlay</strong>
|
|
@@ -46,17 +36,19 @@ A modern React Native blur view component that provides native blur effects and
|
|
|
46
36
|
|
|
47
37
|
| Library Version | Minimum Xcode Version | iOS Features Available |
|
|
48
38
|
|-----------------|----------------------|----------------------|
|
|
49
|
-
| **3.0
|
|
50
|
-
| **2.1
|
|
39
|
+
| **0.3.0+** (Current) | **Xcode 26.0** | ✅ Full liquid glass effects with UIGlassEffect API<br/>✅ Enhanced SwiftUI implementation<br/>✅ All blur types and system materials |
|
|
40
|
+
| **0.2.1** | Xcode 16.0+ | ✅ Standard blur effects<br/>✅ System materials (iOS 13+)<br/>❌ No liquid glass effects |
|
|
51
41
|
|
|
52
42
|
### Xcode 26.0+ Compatibility Table
|
|
53
43
|
|
|
54
44
|
| Xcode Version | Library Compatibility | Features Available | Notes |
|
|
55
45
|
|---------------|----------------------|-------------------|-------|
|
|
56
46
|
| **Xcode 26.0+** | ✅ **Fully Supported** | ✅ All features including liquid glass effects<br/>✅ UIGlassEffect API<br/>✅ SwiftUI implementation<br/>✅ All blur types and system materials | **Recommended for current version** |
|
|
57
|
-
| **Xcode 16.x and below** | ❌ **Not Supported** | ❌ Liquid glass effects<br/>❌ UIGlassEffect API<br/>⚠️ Basic blur effects may work with limitations | Use library version 2.1
|
|
47
|
+
| **Xcode 16.x and below** | ❌ **Not Supported** | ❌ Liquid glass effects<br/>❌ UIGlassEffect API<br/>⚠️ Basic blur effects may work with limitations | Use library version 0.2.1 instead |
|
|
58
48
|
|
|
59
|
-
>
|
|
49
|
+
> ⚠️ **Critical Requirement**: The current version (0.3.0+) requires **Xcode 26.0 or higher** and will not work with older Xcode versions. This is a hard requirement due to the UIGlassEffect API and SwiftUI enhancements introduced in Xcode 26.0.
|
|
50
|
+
|
|
51
|
+
> 💡 **Migration Tip**: If you're unable to upgrade to Xcode 26.0, please use version **0.2.1** of this library which supports Xcode 16.0 and provides standard blur effects without liquid glass capabilities.
|
|
60
52
|
|
|
61
53
|
## Features
|
|
62
54
|
|
|
@@ -300,30 +292,6 @@ import { BlurView } from '@sbaiahmed1/react-native-blur';
|
|
|
300
292
|
- **Bundle size** is your primary concern
|
|
301
293
|
- You can accept **experimental Android blur** with potential fallbacks
|
|
302
294
|
|
|
303
|
-
## Version Compatibility
|
|
304
|
-
|
|
305
|
-
### Xcode Requirements
|
|
306
|
-
|
|
307
|
-
| Library Version | Minimum Xcode Version | iOS Features Available |
|
|
308
|
-
|-----------------|----------------------|----------------------|
|
|
309
|
-
| **3.0.0+** (Current) | **Xcode 26.0** | ✅ Full liquid glass effects with UIGlassEffect API<br/>✅ Enhanced SwiftUI implementation<br/>✅ All blur types and system materials |
|
|
310
|
-
| **2.1.0** | Xcode 16.0+ | ✅ Standard blur effects<br/>✅ System materials (iOS 13+)<br/>❌ No liquid glass effects |
|
|
311
|
-
|
|
312
|
-
### Xcode 26.0+ Compatibility Table
|
|
313
|
-
|
|
314
|
-
| Xcode Version | Library Compatibility | Features Available | Notes |
|
|
315
|
-
|---------------|----------------------|-------------------|-------|
|
|
316
|
-
| **Xcode 26.0+** | ✅ **Fully Supported** | ✅ All features including liquid glass effects<br/>✅ UIGlassEffect API<br/>✅ SwiftUI implementation<br/>✅ All blur types and system materials | **Recommended for current version** |
|
|
317
|
-
| **Xcode 16.x and below** | ❌ **Not Supported** | ❌ Liquid glass effects<br/>❌ UIGlassEffect API<br/>⚠️ Basic blur effects may work with limitations | Use library version 2.1.0 instead |
|
|
318
|
-
|
|
319
|
-
> ⚠️ **Critical Requirement**: The current version (3.0.0+) requires **Xcode 26.0 or higher** and will not work with older Xcode versions. This is a hard requirement due to the UIGlassEffect API and SwiftUI enhancements introduced in Xcode 26.0.
|
|
320
|
-
|
|
321
|
-
> 💡 **Migration Tip**: If you're unable to upgrade to Xcode 26.0, please use version **2.1.0** of this library which supports Xcode 16.0 and provides standard blur effects without liquid glass capabilities.
|
|
322
|
-
|
|
323
|
-
### Installation by Xcode Version
|
|
324
|
-
|
|
325
|
-
**For Xcode 26.0+:**
|
|
326
|
-
|
|
327
295
|
## Installation
|
|
328
296
|
|
|
329
297
|
```bash
|
package/ReactNativeBlur.podspec
CHANGED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// BlurStyleHelpers.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - Style Mapping Helper Functions
|
|
7
|
+
|
|
8
|
+
/// Maps string blur style names to UIBlurEffect.Style values
|
|
9
|
+
func blurStyleFromString(_ styleString: String) -> UIBlurEffect.Style {
|
|
10
|
+
switch styleString {
|
|
11
|
+
case "xlight":
|
|
12
|
+
return .extraLight
|
|
13
|
+
case "light":
|
|
14
|
+
return .light
|
|
15
|
+
case "dark":
|
|
16
|
+
return .dark
|
|
17
|
+
case "extraDark":
|
|
18
|
+
return .systemThickMaterialDark
|
|
19
|
+
case "regular":
|
|
20
|
+
return .regular
|
|
21
|
+
case "prominent":
|
|
22
|
+
return .prominent
|
|
23
|
+
case "systemUltraThinMaterial":
|
|
24
|
+
return .systemUltraThinMaterial
|
|
25
|
+
case "systemThinMaterial":
|
|
26
|
+
return .systemThinMaterial
|
|
27
|
+
case "systemMaterial":
|
|
28
|
+
return .systemMaterial
|
|
29
|
+
case "systemThickMaterial":
|
|
30
|
+
return .systemThickMaterial
|
|
31
|
+
case "systemChromeMaterial":
|
|
32
|
+
return .systemChromeMaterial
|
|
33
|
+
default:
|
|
34
|
+
return .extraLight
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// Maps string glass type names to Glass effect values (iOS 26.0+)
|
|
39
|
+
@available(iOS 26.0, *)
|
|
40
|
+
func glassEffectFromString(_ glassTypeString: String) -> Glass {
|
|
41
|
+
switch glassTypeString {
|
|
42
|
+
case "regular":
|
|
43
|
+
return .regular
|
|
44
|
+
case "clear":
|
|
45
|
+
return .clear
|
|
46
|
+
default:
|
|
47
|
+
return .clear
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// MARK: - Blur Amount Mapping
|
|
52
|
+
|
|
53
|
+
/// Maps blur amount (0-100) to proper blur intensity using UIViewPropertyAnimator approach
|
|
54
|
+
func mapBlurAmountToIntensity(_ amount: Double) -> Double {
|
|
55
|
+
let clampedAmount = max(0.0, min(100.0, amount))
|
|
56
|
+
|
|
57
|
+
// Map 0-100 to 0-1.0 intensity for smooth progression
|
|
58
|
+
return clampedAmount / 100.0
|
|
59
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// ReactNativeBlurViewHelper.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - Objective-C Bridging Helpers
|
|
7
|
+
|
|
8
|
+
@objc public class ReactNativeBlurViewHelper: NSObject {
|
|
9
|
+
|
|
10
|
+
/// Creates and returns a view containing a colored rectangle.
|
|
11
|
+
@objc public static func createBlurViewWithFrame(_ frame: CGRect) -> AdvancedBlurView {
|
|
12
|
+
return AdvancedBlurView(frame: frame)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/// Updates the blur view with a new glass tint color.
|
|
16
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassTintColor glassTintColor: UIColor) {
|
|
17
|
+
blurView.glassTintColor = glassTintColor
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Updates the blur view with a new glass opacity.
|
|
21
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassOpacity glassOpacity: Double) {
|
|
22
|
+
blurView.glassOpacity = glassOpacity
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/// Updates the blur view with a new blur amount.
|
|
26
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurAmount blurAmount: Double) {
|
|
27
|
+
blurView.blurAmount = blurAmount
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Updates the blur view with a new blur type.
|
|
31
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurType blurType: String) {
|
|
32
|
+
blurView.blurTypeString = blurType
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Updates the blur view with a new glass type.
|
|
36
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassType glassType: String) {
|
|
37
|
+
blurView.glassType = glassType
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// Updates the blur view with a new blur style.
|
|
41
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withType type: String) {
|
|
42
|
+
blurView.type = type
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Updates the blur view with a new blur style.
|
|
46
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withIsInteractive isInteractive: Bool) {
|
|
47
|
+
blurView.isInteractive = isInteractive
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Updates the blur view with a new reduced transparency fallback color.
|
|
51
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withReducedTransparencyFallbackColor fallbackColor: UIColor) {
|
|
52
|
+
blurView.reducedTransparencyFallbackColor = fallbackColor
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// No-op updater kept for API compatibility.
|
|
56
|
+
@objc public static func updateBlurView(_ blurView: AdvancedBlurView) {
|
|
57
|
+
// Nothing to update in the minimal implementation
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
#import <react/renderer/components/ReactNativeBlurViewSpec/RCTComponentViewHelpers.h>
|
|
7
7
|
|
|
8
8
|
#import "RCTFabricComponentsPlugins.h"
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
#if __has_include("ReactNativeBlur-Swift.h")
|
|
11
|
+
#import "ReactNativeBlur-Swift.h"
|
|
12
|
+
#else
|
|
13
|
+
#import <ReactNativeBlur/ReactNativeBlur-Swift.h>
|
|
14
|
+
#endif
|
|
10
15
|
|
|
11
16
|
using namespace facebook::react;
|
|
12
17
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#import "ReactNativeBlurViewManager.h"
|
|
2
|
+
|
|
3
|
+
#if __has_include("ReactNativeBlur-Swift.h")
|
|
2
4
|
#import "ReactNativeBlur-Swift.h"
|
|
5
|
+
#else
|
|
6
|
+
#import <ReactNativeBlur/ReactNativeBlur-Swift.h>
|
|
7
|
+
#endif
|
|
8
|
+
|
|
3
9
|
#import <React/RCTUIManager.h>
|
|
4
10
|
#import <React/RCTBridge.h>
|
|
5
11
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// AdvancedBlurView.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - UIKit Wrapper
|
|
7
|
+
|
|
8
|
+
@objc public class AdvancedBlurView: UIView {
|
|
9
|
+
|
|
10
|
+
private var hostingController: UIHostingController<BasicColoredView>?
|
|
11
|
+
|
|
12
|
+
@objc public var glassTintColor: UIColor = .clear {
|
|
13
|
+
didSet {
|
|
14
|
+
updateView()
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@objc public var glassOpacity: Double = 1.0 {
|
|
19
|
+
didSet {
|
|
20
|
+
updateView()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@objc public var blurAmount: Double = 10.0 {
|
|
25
|
+
didSet {
|
|
26
|
+
updateView()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@objc public var type: String = "blur" {
|
|
31
|
+
didSet {
|
|
32
|
+
updateView()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@objc public var blurTypeString: String = "xlight" {
|
|
37
|
+
didSet {
|
|
38
|
+
updateView()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc public var glassType: String = "clear" {
|
|
43
|
+
didSet {
|
|
44
|
+
updateView()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@objc public var reducedTransparencyFallbackColor: UIColor = .white {
|
|
49
|
+
didSet {
|
|
50
|
+
updateView()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@objc public var isInteractive: Bool = true {
|
|
55
|
+
didSet {
|
|
56
|
+
updateView()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public override init(frame: CGRect) {
|
|
61
|
+
super.init(frame: frame)
|
|
62
|
+
setupHostingController()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
required init?(coder: NSCoder) {
|
|
66
|
+
super.init(coder: coder)
|
|
67
|
+
setupHostingController()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private func setupHostingController() {
|
|
71
|
+
let blurStyle = blurStyleFromString(blurTypeString)
|
|
72
|
+
let swiftUIView = BasicColoredView(glassTintColor: glassTintColor, glassOpacity: glassOpacity, blurAmount: blurAmount, blurStyle: blurStyle, type: type, glassType: glassType, reducedTransparencyFallbackColor: reducedTransparencyFallbackColor, isInteractive: isInteractive)
|
|
73
|
+
let hosting = UIHostingController(rootView: swiftUIView)
|
|
74
|
+
|
|
75
|
+
hosting.view.backgroundColor = .clear
|
|
76
|
+
hosting.view.translatesAutoresizingMaskIntoConstraints = false
|
|
77
|
+
|
|
78
|
+
addSubview(hosting.view)
|
|
79
|
+
NSLayoutConstraint.activate([
|
|
80
|
+
hosting.view.topAnchor.constraint(equalTo: topAnchor),
|
|
81
|
+
hosting.view.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
82
|
+
hosting.view.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
83
|
+
hosting.view.bottomAnchor.constraint(equalTo: bottomAnchor)
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
self.hostingController = hosting
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private func updateView() {
|
|
90
|
+
let blurStyle = blurStyleFromString(blurTypeString)
|
|
91
|
+
let newSwiftUIView = BasicColoredView(glassTintColor: glassTintColor, glassOpacity: glassOpacity, blurAmount: blurAmount, blurStyle: blurStyle, type:type, glassType: glassType, reducedTransparencyFallbackColor: reducedTransparencyFallbackColor, isInteractive: isInteractive)
|
|
92
|
+
hostingController?.rootView = newSwiftUIView
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// BasicColoredView.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - SwiftUI View Component
|
|
7
|
+
|
|
8
|
+
struct BasicColoredView: View {
|
|
9
|
+
var glassTintColor: UIColor
|
|
10
|
+
var glassOpacity: Double
|
|
11
|
+
var blurAmount: Double
|
|
12
|
+
var blurStyle: UIBlurEffect.Style
|
|
13
|
+
var type: String
|
|
14
|
+
var glassType: String
|
|
15
|
+
var reducedTransparencyFallbackColor: UIColor
|
|
16
|
+
var isInteractive: Bool
|
|
17
|
+
|
|
18
|
+
var body: some View {
|
|
19
|
+
let blurIntensity = mapBlurAmountToIntensity(blurAmount)
|
|
20
|
+
|
|
21
|
+
// Check if reduced transparency is enabled
|
|
22
|
+
let isReducedTransparencyEnabled = UIAccessibility.isReduceTransparencyEnabled
|
|
23
|
+
|
|
24
|
+
if isReducedTransparencyEnabled {
|
|
25
|
+
// Use fallback color when reduced transparency is enabled
|
|
26
|
+
Rectangle()
|
|
27
|
+
.fill(Color(reducedTransparencyFallbackColor))
|
|
28
|
+
} else {
|
|
29
|
+
if (type == "liquidGlass"){
|
|
30
|
+
if #available(iOS 26.0, *) {
|
|
31
|
+
let baseGlassEffect = glassEffectFromString(glassType)
|
|
32
|
+
Rectangle()
|
|
33
|
+
.glassEffect(
|
|
34
|
+
baseGlassEffect
|
|
35
|
+
.tint(Color(glassTintColor)
|
|
36
|
+
.opacity(glassOpacity))
|
|
37
|
+
.interactive(isInteractive)
|
|
38
|
+
, in: .rect)
|
|
39
|
+
|
|
40
|
+
} else {
|
|
41
|
+
// Use proper blur intensity control for liquid glass fallback
|
|
42
|
+
Rectangle()
|
|
43
|
+
.fill(Color(.clear))
|
|
44
|
+
.background(Blur(style: blurStyle, intensity: blurIntensity))
|
|
45
|
+
.overlay(
|
|
46
|
+
Color(glassTintColor)
|
|
47
|
+
.opacity(glassOpacity)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
}else {
|
|
51
|
+
// Use proper blur intensity control for regular blur
|
|
52
|
+
Rectangle()
|
|
53
|
+
.fill(Color(.clear))
|
|
54
|
+
.background(Blur(style: blurStyle, intensity: blurIntensity))
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// BlurEffectView.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
4
|
+
import UIKit
|
|
5
|
+
|
|
6
|
+
// MARK: - Blur View with proper intensity control
|
|
7
|
+
|
|
8
|
+
class BlurEffectView: UIVisualEffectView {
|
|
9
|
+
private var animator: UIViewPropertyAnimator?
|
|
10
|
+
private var blurStyle: UIBlurEffect.Style = .systemMaterial
|
|
11
|
+
private var intensity: Double = 1.0
|
|
12
|
+
|
|
13
|
+
override init(effect: UIVisualEffect?) {
|
|
14
|
+
super.init(effect: effect)
|
|
15
|
+
setupBlur()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
required init?(coder: NSCoder) {
|
|
19
|
+
super.init(coder: coder)
|
|
20
|
+
setupBlur()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
func updateBlur(style: UIBlurEffect.Style, intensity: Double) {
|
|
24
|
+
self.blurStyle = style
|
|
25
|
+
self.intensity = intensity
|
|
26
|
+
setupBlur()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
private func setupBlur() {
|
|
30
|
+
// Clean up existing animator
|
|
31
|
+
animator?.stopAnimation(true)
|
|
32
|
+
animator?.finishAnimation(at: .current)
|
|
33
|
+
animator = nil
|
|
34
|
+
|
|
35
|
+
// Reset effect
|
|
36
|
+
effect = nil
|
|
37
|
+
|
|
38
|
+
// Create new animator
|
|
39
|
+
animator = UIViewPropertyAnimator(duration: 1, curve: .linear)
|
|
40
|
+
animator?.addAnimations { [weak self] in
|
|
41
|
+
self?.effect = UIBlurEffect(style: self?.blurStyle ?? .systemMaterial)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Set intensity and pause
|
|
45
|
+
animator?.fractionComplete = intensity
|
|
46
|
+
animator?.pauseAnimation()
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
deinit {
|
|
50
|
+
animator?.stopAnimation(true)
|
|
51
|
+
animator?.finishAnimation(at: .current)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MARK: - SwiftUI Blur Wrapper
|
|
56
|
+
|
|
57
|
+
struct Blur: UIViewRepresentable {
|
|
58
|
+
var style: UIBlurEffect.Style = .systemMaterial
|
|
59
|
+
var intensity: Double = 1.0
|
|
60
|
+
|
|
61
|
+
func makeUIView(context: Context) -> BlurEffectView {
|
|
62
|
+
let effectView = BlurEffectView(effect: nil)
|
|
63
|
+
effectView.updateBlur(style: style, intensity: intensity)
|
|
64
|
+
return effectView
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func updateUIView(_ uiView: BlurEffectView, context: Context) {
|
|
68
|
+
uiView.updateBlur(style: style, intensity: intensity)
|
|
69
|
+
}
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,321 +0,0 @@
|
|
|
1
|
-
// ReactNativeBlurView.swift
|
|
2
|
-
|
|
3
|
-
import SwiftUI
|
|
4
|
-
import UIKit
|
|
5
|
-
|
|
6
|
-
// MARK: Blur View with proper intensity control
|
|
7
|
-
|
|
8
|
-
class BlurEffectView: UIVisualEffectView {
|
|
9
|
-
private var animator: UIViewPropertyAnimator?
|
|
10
|
-
private var blurStyle: UIBlurEffect.Style = .systemMaterial
|
|
11
|
-
private var intensity: Double = 1.0
|
|
12
|
-
|
|
13
|
-
override init(effect: UIVisualEffect?) {
|
|
14
|
-
super.init(effect: effect)
|
|
15
|
-
setupBlur()
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
required init?(coder: NSCoder) {
|
|
19
|
-
super.init(coder: coder)
|
|
20
|
-
setupBlur()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
func updateBlur(style: UIBlurEffect.Style, intensity: Double) {
|
|
24
|
-
self.blurStyle = style
|
|
25
|
-
self.intensity = intensity
|
|
26
|
-
setupBlur()
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private func setupBlur() {
|
|
30
|
-
// Clean up existing animator
|
|
31
|
-
animator?.stopAnimation(true)
|
|
32
|
-
animator?.finishAnimation(at: .current)
|
|
33
|
-
animator = nil
|
|
34
|
-
|
|
35
|
-
// Reset effect
|
|
36
|
-
effect = nil
|
|
37
|
-
|
|
38
|
-
// Create new animator
|
|
39
|
-
animator = UIViewPropertyAnimator(duration: 1, curve: .linear)
|
|
40
|
-
animator?.addAnimations { [weak self] in
|
|
41
|
-
self?.effect = UIBlurEffect(style: self?.blurStyle ?? .systemMaterial)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Set intensity and pause
|
|
45
|
-
animator?.fractionComplete = intensity
|
|
46
|
-
animator?.pauseAnimation()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
deinit {
|
|
50
|
-
animator?.stopAnimation(true)
|
|
51
|
-
animator?.finishAnimation(at: .current)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
struct Blur: UIViewRepresentable {
|
|
56
|
-
var style: UIBlurEffect.Style = .systemMaterial
|
|
57
|
-
var intensity: Double = 1.0
|
|
58
|
-
|
|
59
|
-
func makeUIView(context: Context) -> BlurEffectView {
|
|
60
|
-
let effectView = BlurEffectView(effect: nil)
|
|
61
|
-
effectView.updateBlur(style: style, intensity: intensity)
|
|
62
|
-
return effectView
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
func updateUIView(_ uiView: BlurEffectView, context: Context) {
|
|
66
|
-
uiView.updateBlur(style: style, intensity: intensity)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// MARK: - Helper Functions
|
|
71
|
-
|
|
72
|
-
private func blurStyleFromString(_ styleString: String) -> UIBlurEffect.Style {
|
|
73
|
-
switch styleString {
|
|
74
|
-
case "xlight":
|
|
75
|
-
return .extraLight
|
|
76
|
-
case "light":
|
|
77
|
-
return .light
|
|
78
|
-
case "dark":
|
|
79
|
-
return .dark
|
|
80
|
-
case "extraDark":
|
|
81
|
-
return .systemThickMaterialDark
|
|
82
|
-
case "regular":
|
|
83
|
-
return .regular
|
|
84
|
-
case "prominent":
|
|
85
|
-
return .prominent
|
|
86
|
-
case "systemUltraThinMaterial":
|
|
87
|
-
return .systemUltraThinMaterial
|
|
88
|
-
case "systemThinMaterial":
|
|
89
|
-
return .systemThinMaterial
|
|
90
|
-
case "systemMaterial":
|
|
91
|
-
return .systemMaterial
|
|
92
|
-
case "systemThickMaterial":
|
|
93
|
-
return .systemThickMaterial
|
|
94
|
-
case "systemChromeMaterial":
|
|
95
|
-
return .systemChromeMaterial
|
|
96
|
-
default:
|
|
97
|
-
return .extraLight
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
@available(iOS 26.0, *)
|
|
102
|
-
private func glassEffectFromString(_ glassTypeString: String) -> Glass {
|
|
103
|
-
switch glassTypeString {
|
|
104
|
-
case "regular":
|
|
105
|
-
return .regular
|
|
106
|
-
case "clear":
|
|
107
|
-
return .clear
|
|
108
|
-
default:
|
|
109
|
-
return .clear
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// MARK: - Helper Functions for Blur Amount Mapping
|
|
114
|
-
|
|
115
|
-
/// Maps blur amount (0-100) to proper blur intensity using UIViewPropertyAnimator approach
|
|
116
|
-
private func mapBlurAmountToIntensity(_ amount: Double) -> Double {
|
|
117
|
-
let clampedAmount = max(0.0, min(100.0, amount))
|
|
118
|
-
|
|
119
|
-
// Map 0-100 to 0-1.0 intensity for smooth progression
|
|
120
|
-
return clampedAmount / 100.0
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// MARK: - Simple SwiftUI View
|
|
124
|
-
|
|
125
|
-
private struct BasicColoredView: View {
|
|
126
|
-
var glassTintColor: UIColor
|
|
127
|
-
var glassOpacity: Double
|
|
128
|
-
var blurAmount: Double
|
|
129
|
-
var blurStyle: UIBlurEffect.Style
|
|
130
|
-
var type: String
|
|
131
|
-
var glassType: String
|
|
132
|
-
var reducedTransparencyFallbackColor: UIColor
|
|
133
|
-
var isInteractive: Bool
|
|
134
|
-
|
|
135
|
-
var body: some View {
|
|
136
|
-
let blurIntensity = mapBlurAmountToIntensity(blurAmount)
|
|
137
|
-
|
|
138
|
-
// Check if reduced transparency is enabled
|
|
139
|
-
let isReducedTransparencyEnabled = UIAccessibility.isReduceTransparencyEnabled
|
|
140
|
-
|
|
141
|
-
if isReducedTransparencyEnabled {
|
|
142
|
-
// Use fallback color when reduced transparency is enabled
|
|
143
|
-
Rectangle()
|
|
144
|
-
.fill(Color(reducedTransparencyFallbackColor))
|
|
145
|
-
} else {
|
|
146
|
-
if (type == "liquidGlass"){
|
|
147
|
-
if #available(iOS 26.0, *) {
|
|
148
|
-
let baseGlassEffect = glassEffectFromString(glassType)
|
|
149
|
-
Rectangle()
|
|
150
|
-
.glassEffect(
|
|
151
|
-
baseGlassEffect
|
|
152
|
-
.tint(Color(glassTintColor)
|
|
153
|
-
.opacity(glassOpacity))
|
|
154
|
-
.interactive(isInteractive)
|
|
155
|
-
, in: .rect)
|
|
156
|
-
|
|
157
|
-
} else {
|
|
158
|
-
// Use proper blur intensity control for liquid glass fallback
|
|
159
|
-
Rectangle()
|
|
160
|
-
.fill(Color(.clear))
|
|
161
|
-
.background(Blur(style: blurStyle, intensity: blurIntensity))
|
|
162
|
-
.overlay(
|
|
163
|
-
Color(glassTintColor)
|
|
164
|
-
.opacity(glassOpacity)
|
|
165
|
-
)
|
|
166
|
-
}
|
|
167
|
-
}else {
|
|
168
|
-
// Use proper blur intensity control for regular blur
|
|
169
|
-
Rectangle()
|
|
170
|
-
.fill(Color(.clear))
|
|
171
|
-
.background(Blur(style: blurStyle, intensity: blurIntensity))
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// MARK: - UIKit Wrapper
|
|
178
|
-
|
|
179
|
-
@objc public class AdvancedBlurView: UIView {
|
|
180
|
-
|
|
181
|
-
private var hostingController: UIHostingController<BasicColoredView>?
|
|
182
|
-
|
|
183
|
-
@objc public var glassTintColor: UIColor = .clear {
|
|
184
|
-
didSet {
|
|
185
|
-
updateView()
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@objc public var glassOpacity: Double = 1.0 {
|
|
190
|
-
didSet {
|
|
191
|
-
updateView()
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
@objc public var blurAmount: Double = 10.0 {
|
|
196
|
-
didSet {
|
|
197
|
-
updateView()
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
@objc public var type: String = "blur" {
|
|
202
|
-
didSet {
|
|
203
|
-
updateView()
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
@objc public var blurTypeString: String = "xlight" {
|
|
208
|
-
didSet {
|
|
209
|
-
updateView()
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
@objc public var glassType: String = "clear" {
|
|
214
|
-
didSet {
|
|
215
|
-
updateView()
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
@objc public var reducedTransparencyFallbackColor: UIColor = .white {
|
|
220
|
-
didSet {
|
|
221
|
-
updateView()
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
@objc public var isInteractive: Bool = true {
|
|
226
|
-
didSet {
|
|
227
|
-
updateView()
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
public override init(frame: CGRect) {
|
|
232
|
-
super.init(frame: frame)
|
|
233
|
-
setupHostingController()
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
required init?(coder: NSCoder) {
|
|
237
|
-
super.init(coder: coder)
|
|
238
|
-
setupHostingController()
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private func setupHostingController() {
|
|
242
|
-
let blurStyle = blurStyleFromString(blurTypeString)
|
|
243
|
-
let swiftUIView = BasicColoredView(glassTintColor: glassTintColor, glassOpacity: glassOpacity, blurAmount: blurAmount, blurStyle: blurStyle, type: type, glassType: glassType, reducedTransparencyFallbackColor: reducedTransparencyFallbackColor, isInteractive: isInteractive)
|
|
244
|
-
let hosting = UIHostingController(rootView: swiftUIView)
|
|
245
|
-
|
|
246
|
-
hosting.view.backgroundColor = .clear
|
|
247
|
-
hosting.view.translatesAutoresizingMaskIntoConstraints = false
|
|
248
|
-
|
|
249
|
-
addSubview(hosting.view)
|
|
250
|
-
NSLayoutConstraint.activate([
|
|
251
|
-
hosting.view.topAnchor.constraint(equalTo: topAnchor),
|
|
252
|
-
hosting.view.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
253
|
-
hosting.view.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
254
|
-
hosting.view.bottomAnchor.constraint(equalTo: bottomAnchor)
|
|
255
|
-
])
|
|
256
|
-
|
|
257
|
-
self.hostingController = hosting
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
private func updateView() {
|
|
261
|
-
let blurStyle = blurStyleFromString(blurTypeString)
|
|
262
|
-
let newSwiftUIView = BasicColoredView(glassTintColor: glassTintColor, glassOpacity: glassOpacity, blurAmount: blurAmount, blurStyle: blurStyle, type:type, glassType: glassType, reducedTransparencyFallbackColor: reducedTransparencyFallbackColor, isInteractive: isInteractive)
|
|
263
|
-
hostingController?.rootView = newSwiftUIView
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// MARK: - Objective-C Bridging Helpers
|
|
268
|
-
|
|
269
|
-
@objc public class ReactNativeBlurViewHelper: NSObject {
|
|
270
|
-
|
|
271
|
-
/// Creates and returns a view containing a colored rectangle.
|
|
272
|
-
@objc public static func createBlurViewWithFrame(_ frame: CGRect) -> AdvancedBlurView {
|
|
273
|
-
return AdvancedBlurView(frame: frame)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/// Updates the blur view with a new glass tint color.
|
|
277
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassTintColor glassTintColor: UIColor) {
|
|
278
|
-
blurView.glassTintColor = glassTintColor
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/// Updates the blur view with a new glass opacity.
|
|
282
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassOpacity glassOpacity: Double) {
|
|
283
|
-
blurView.glassOpacity = glassOpacity
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/// Updates the blur view with a new blur amount.
|
|
287
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurAmount blurAmount: Double) {
|
|
288
|
-
blurView.blurAmount = blurAmount
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/// Updates the blur view with a new blur type.
|
|
292
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurType blurType: String) {
|
|
293
|
-
blurView.blurTypeString = blurType
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/// Updates the blur view with a new glass type.
|
|
297
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withGlassType glassType: String) {
|
|
298
|
-
blurView.glassType = glassType
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/// Updates the blur view with a new blur style.
|
|
302
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withType type: String) {
|
|
303
|
-
blurView.type = type
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/// Updates the blur view with a new blur style.
|
|
307
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withIsInteractive isInteractive: Bool) {
|
|
308
|
-
blurView.isInteractive = isInteractive
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/// Updates the blur view with a new reduced transparency fallback color.
|
|
312
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withReducedTransparencyFallbackColor fallbackColor: UIColor) {
|
|
313
|
-
blurView.reducedTransparencyFallbackColor = fallbackColor
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
/// No-op updater kept for API compatibility.
|
|
317
|
-
@objc public static func updateBlurView(_ blurView: AdvancedBlurView) {
|
|
318
|
-
// Nothing to update in the minimal implementation
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|