@sbaiahmed1/react-native-blur 4.6.1-beta.5 → 4.6.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
|
@@ -7,7 +7,7 @@ A modern React Native library providing **six specialized components** for advan
|
|
|
7
7
|
<div align="center">
|
|
8
8
|
<p>
|
|
9
9
|
<img src="https://img.shields.io/npm/v/@sbaiahmed1/react-native-blur?style=for-the-badge&color=blue" alt="npm version" />
|
|
10
|
-
<img src="https://img.shields.io/npm/
|
|
10
|
+
<img src="https://img.shields.io/npm/dm/%40sbaiahmed1%2Freact-native-blur?style=for-the-badge" alt="downloads per month" />
|
|
11
11
|
<img src="https://img.shields.io/github/license/sbaiahmed1/react-native-blur?style=for-the-badge&color=orange" alt="license" />
|
|
12
12
|
<img src="https://img.shields.io/github/stars/sbaiahmed1/react-native-blur?style=for-the-badge&color=yellow" alt="stars" />
|
|
13
13
|
</p>
|
|
@@ -1001,6 +1001,7 @@ MIT
|
|
|
1001
1001
|
|
|
1002
1002
|
<div align="center">
|
|
1003
1003
|
<img src="https://img.shields.io/github/contributors/sbaiahmed1/react-native-blur?style=for-the-badge" alt="contributors" />
|
|
1004
|
+
<img src="https://img.shields.io/npm/dt/@sbaiahmed1/react-native-blur?style=for-the-badge&color=green" alt="downloads" />
|
|
1004
1005
|
<img src="https://img.shields.io/github/last-commit/sbaiahmed1/react-native-blur?style=for-the-badge" alt="last commit" />
|
|
1005
1006
|
<img src="https://img.shields.io/github/issues/sbaiahmed1/react-native-blur?style=for-the-badge" alt="issues" />
|
|
1006
1007
|
<img src="https://img.shields.io/github/issues-pr/sbaiahmed1/react-native-blur?style=for-the-badge" alt="pull requests" />
|
|
@@ -1,23 +1,35 @@
|
|
|
1
|
+
// ReactNativeBlurViewHelper.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
1
4
|
import UIKit
|
|
2
5
|
|
|
6
|
+
// MARK: - Objective-C Bridging Helpers
|
|
7
|
+
|
|
3
8
|
@objc public class ReactNativeBlurViewHelper: NSObject {
|
|
9
|
+
|
|
10
|
+
/// Creates and returns a blur view.
|
|
4
11
|
@objc public static func createBlurViewWithFrame(_ frame: CGRect) -> AdvancedBlurView {
|
|
5
12
|
return AdvancedBlurView(frame: frame)
|
|
6
13
|
}
|
|
7
14
|
|
|
15
|
+
/// Updates the blur view with a new blur amount.
|
|
8
16
|
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurAmount blurAmount: Double) {
|
|
9
17
|
blurView.blurAmount = blurAmount
|
|
10
18
|
}
|
|
11
19
|
|
|
20
|
+
/// Updates the blur view with a new blur type.
|
|
12
21
|
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withBlurType blurType: String) {
|
|
13
22
|
blurView.blurTypeString = blurType
|
|
14
23
|
}
|
|
15
24
|
|
|
25
|
+
/// Updates the blur view with a new reduced transparency fallback color.
|
|
16
26
|
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withReducedTransparencyFallbackColor reducedTransparencyFallbackColor: UIColor) {
|
|
17
27
|
blurView.reducedTransparencyFallbackColor = reducedTransparencyFallbackColor
|
|
18
28
|
}
|
|
19
29
|
|
|
30
|
+
/// Updates the blur view with a new ignoreSafeArea value.
|
|
20
31
|
@objc public static func updateBlurView(_ blurView: AdvancedBlurView, withIgnoringSafeArea ignoreSafeArea: Bool) {
|
|
21
32
|
blurView.ignoreSafeArea = ignoreSafeArea
|
|
22
33
|
}
|
|
23
34
|
}
|
|
35
|
+
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import SwiftUI
|
|
1
2
|
import UIKit
|
|
2
3
|
|
|
4
|
+
// MARK: - UIKit Wrapper for Blur
|
|
5
|
+
|
|
3
6
|
@objc public class AdvancedBlurView: UIView {
|
|
4
|
-
|
|
5
|
-
private
|
|
7
|
+
|
|
8
|
+
private var hostingController: UIHostingController<BasicColoredView>?
|
|
6
9
|
|
|
7
10
|
@objc public var blurAmount: Double = 10.0 {
|
|
8
11
|
didSet {
|
|
@@ -26,63 +29,79 @@ import UIKit
|
|
|
26
29
|
didSet {
|
|
27
30
|
updateView()
|
|
28
31
|
}
|
|
29
|
-
|
|
32
|
+
}
|
|
30
33
|
|
|
31
34
|
public override init(frame: CGRect) {
|
|
32
35
|
super.init(frame: frame)
|
|
33
|
-
setupViews()
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
required init?(coder: NSCoder) {
|
|
37
39
|
super.init(coder: coder)
|
|
38
|
-
setupViews()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
private func setupViews() {
|
|
42
|
-
blurEffectView.isUserInteractionEnabled = false
|
|
43
|
-
fallbackView.isUserInteractionEnabled = false
|
|
44
|
-
addSubview(fallbackView)
|
|
45
|
-
addSubview(blurEffectView)
|
|
46
|
-
syncBackgroundLayersToBack()
|
|
47
|
-
updateView()
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if
|
|
55
|
-
|
|
42
|
+
public override func layoutSubviews() {
|
|
43
|
+
super.layoutSubviews()
|
|
44
|
+
// Defer controller setup until we have a valid frame to avoid issues with initial render
|
|
45
|
+
// in complex layouts (e.g. FlashList with dynamic content)
|
|
46
|
+
if hostingController == nil && bounds.width > 0 && bounds.height > 0 {
|
|
47
|
+
setupHostingController()
|
|
56
48
|
}
|
|
57
49
|
}
|
|
58
50
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if
|
|
62
|
-
|
|
51
|
+
private func setupHostingController() {
|
|
52
|
+
// Completely remove old hosting controller
|
|
53
|
+
if let oldHosting = hostingController {
|
|
54
|
+
oldHosting.view.removeFromSuperview()
|
|
55
|
+
oldHosting.removeFromParent()
|
|
63
56
|
}
|
|
64
|
-
|
|
57
|
+
hostingController = nil
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
let blurStyle = blurStyleFromString(blurTypeString)
|
|
60
|
+
let swiftUIView = BasicColoredView(
|
|
61
|
+
blurAmount: blurAmount,
|
|
62
|
+
blurStyle: blurStyle,
|
|
63
|
+
ignoreSafeArea: ignoreSafeArea,
|
|
64
|
+
reducedTransparencyFallbackColor: reducedTransparencyFallbackColor
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
let hosting = UIHostingController(rootView: swiftUIView)
|
|
68
|
+
hosting.view.backgroundColor = .clear
|
|
69
|
+
hosting.view.translatesAutoresizingMaskIntoConstraints = false
|
|
70
|
+
|
|
71
|
+
// Insert at index 0 to ensure it stays behind any potential subviews (though usually this view has no children)
|
|
72
|
+
// This fixes the z-ordering bug where blur covers content
|
|
73
|
+
if !subviews.isEmpty {
|
|
74
|
+
insertSubview(hosting.view, at: 0)
|
|
75
|
+
} else {
|
|
76
|
+
addSubview(hosting.view)
|
|
77
|
+
}
|
|
78
|
+
|
|
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
|
|
70
87
|
}
|
|
71
88
|
|
|
72
89
|
private func updateView() {
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
if let hosting = hostingController {
|
|
91
|
+
// Update the existing controller's root view to avoid expensive recreation
|
|
92
|
+
// This fixes performance bottlenecks and state synchronization issues
|
|
93
|
+
let blurStyle = blurStyleFromString(blurTypeString)
|
|
94
|
+
let swiftUIView = BasicColoredView(
|
|
95
|
+
blurAmount: blurAmount,
|
|
96
|
+
blurStyle: blurStyle,
|
|
97
|
+
ignoreSafeArea: ignoreSafeArea,
|
|
98
|
+
reducedTransparencyFallbackColor: reducedTransparencyFallbackColor
|
|
99
|
+
)
|
|
100
|
+
hosting.rootView = swiftUIView
|
|
101
|
+
hosting.view.setNeedsLayout()
|
|
102
|
+
} else {
|
|
103
|
+
setupHostingController()
|
|
78
104
|
}
|
|
79
|
-
|
|
80
|
-
fallbackView.isHidden = true
|
|
81
|
-
blurEffectView.isHidden = false
|
|
82
|
-
let blurStyle = blurStyleFromString(blurTypeString)
|
|
83
|
-
let intensity = mapBlurAmountToIntensity(blurAmount)
|
|
84
|
-
blurEffectView.updateBlur(style: blurStyle, intensity: intensity)
|
|
85
|
-
blurEffectView.setNeedsDisplay()
|
|
86
105
|
}
|
|
87
106
|
|
|
88
107
|
public override func didMoveToSuperview() {
|
|
@@ -91,10 +110,13 @@ import UIKit
|
|
|
91
110
|
|
|
92
111
|
public override func didMoveToWindow() {
|
|
93
112
|
super.didMoveToWindow()
|
|
94
|
-
if window != nil {
|
|
95
|
-
updateView()
|
|
96
|
-
}
|
|
97
113
|
}
|
|
98
114
|
|
|
99
|
-
deinit {
|
|
115
|
+
deinit {
|
|
116
|
+
if let hosting = hostingController {
|
|
117
|
+
hosting.view.removeFromSuperview()
|
|
118
|
+
hosting.removeFromParent()
|
|
119
|
+
}
|
|
120
|
+
hostingController = nil
|
|
121
|
+
}
|
|
100
122
|
}
|
|
@@ -1,68 +1,77 @@
|
|
|
1
|
+
// BlurEffectView.swift
|
|
2
|
+
|
|
3
|
+
import SwiftUI
|
|
1
4
|
import UIKit
|
|
2
5
|
|
|
6
|
+
// MARK: - Blur View with proper intensity control
|
|
7
|
+
|
|
3
8
|
class BlurEffectView: UIVisualEffectView {
|
|
4
9
|
private var animator: UIViewPropertyAnimator?
|
|
5
|
-
private var blurStyle: UIBlurEffect.Style = .systemMaterial
|
|
6
|
-
|
|
7
|
-
visualEffect = UIBlurEffect(style: blurStyle)
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
private var intensity: Double = 0.1 {
|
|
11
|
-
didSet {
|
|
12
|
-
setNeedsDisplay()
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
private var visualEffect: UIVisualEffect = UIBlurEffect(style: .systemMaterial) {
|
|
16
|
-
didSet {
|
|
17
|
-
setNeedsDisplay()
|
|
18
|
-
}
|
|
19
|
-
}
|
|
10
|
+
private var blurStyle: UIBlurEffect.Style = .systemMaterial
|
|
11
|
+
private var intensity: Double = 1.0
|
|
20
12
|
|
|
21
13
|
override init(effect: UIVisualEffect?) {
|
|
22
|
-
super.init(effect:
|
|
14
|
+
super.init(effect: effect)
|
|
15
|
+
setupBlur()
|
|
23
16
|
}
|
|
24
17
|
|
|
25
18
|
required init?(coder: NSCoder) {
|
|
26
|
-
|
|
19
|
+
super.init(coder: coder)
|
|
20
|
+
setupBlur()
|
|
27
21
|
}
|
|
28
22
|
|
|
29
23
|
func updateBlur(style: UIBlurEffect.Style, intensity: Double) {
|
|
30
|
-
blurStyle = style
|
|
31
|
-
self.intensity =
|
|
32
|
-
|
|
24
|
+
self.blurStyle = style
|
|
25
|
+
self.intensity = intensity
|
|
26
|
+
setupBlur()
|
|
33
27
|
}
|
|
34
28
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
effect = intensity > 0 ? visualEffect : nil
|
|
41
|
-
return
|
|
29
|
+
private func setupBlur() {
|
|
30
|
+
// Clean up existing animator
|
|
31
|
+
if let animator = animator {
|
|
32
|
+
animator.stopAnimation(true)
|
|
33
|
+
animator.finishAnimation(at: .current)
|
|
42
34
|
}
|
|
35
|
+
animator = nil
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
animator?.stopAnimation(true)
|
|
47
|
-
return
|
|
48
|
-
}
|
|
37
|
+
// Reset effect
|
|
38
|
+
effect = nil
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
// Create new animator
|
|
41
|
+
animator = UIViewPropertyAnimator(duration: 1, curve: .linear)
|
|
42
|
+
animator?.addAnimations { [weak self] in
|
|
43
|
+
self?.effect = UIBlurEffect(style: self?.blurStyle ?? .systemMaterial)
|
|
44
|
+
}
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
animator?.
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
// Set intensity
|
|
47
|
+
animator?.fractionComplete = intensity
|
|
48
|
+
// Stop the animation at the current state
|
|
49
|
+
DispatchQueue.main.async { [weak self] in
|
|
50
|
+
self?.animator?.stopAnimation(true)
|
|
51
|
+
self?.animator?.finishAnimation(at: .current)
|
|
56
52
|
}
|
|
57
|
-
animator?.fractionComplete = CGFloat(normalizedIntensity)
|
|
58
53
|
}
|
|
59
54
|
|
|
60
55
|
deinit {
|
|
61
|
-
animator
|
|
56
|
+
guard let animator = animator, animator.state == .active else { return }
|
|
57
|
+
animator.stopAnimation(true)
|
|
58
|
+
animator.finishAnimation(at: .current)
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
// MARK: - SwiftUI Blur Wrapper
|
|
63
|
+
|
|
64
|
+
struct Blur: UIViewRepresentable {
|
|
65
|
+
var style: UIBlurEffect.Style = .systemMaterial
|
|
66
|
+
var intensity: Double = 1.0
|
|
67
|
+
|
|
68
|
+
func makeUIView(context: Context) -> BlurEffectView {
|
|
69
|
+
let effectView = BlurEffectView(effect: nil)
|
|
70
|
+
effectView.updateBlur(style: style, intensity: intensity)
|
|
71
|
+
return effectView
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func updateUIView(_ uiView: BlurEffectView, context: Context) {
|
|
75
|
+
uiView.updateBlur(style: style, intensity: intensity)
|
|
76
|
+
}
|
|
68
77
|
}
|