@@ -10,6 +10,8 @@ import Combine
1010import SwiftUI
1111import AmzdIntrospect
1212
13+ // MARK: Platform specifics
14+
1315@available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
1416typealias ResponderPublisher = AnyPublisher < PlatformResponder ? , Never >
1517
@@ -60,6 +62,27 @@ extension UIView {
6062}
6163#endif
6264
65+ // MARK: View Extension
66+
67+ @available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
68+ extension View {
69+ /// Tag the closest sibling view that can become first responder
70+ public func responderTag< Tag: Hashable > ( _ tag: Tag ) -> some View {
71+ inject ( FindResponderSibling ( tag: tag) )
72+ }
73+
74+ /// This attaches the ResponderChain for the current window as environmentObject
75+ ///
76+ /// Will not show anything for the first frame as it introspects the closest view to get the window
77+ ///
78+ /// Use `.environmentObject(ResponderChain(forWindow: window))` if possible.
79+ public func withResponderChainForCurrentWindow( ) -> some View {
80+ self . modifier ( ResponderChainWindowFinder ( ) )
81+ }
82+ }
83+
84+ // MARK: ResponderChain
85+
6386@available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
6487public class ResponderChain : ObservableObject {
6588 @Published public var firstResponder : AnyHashable ? {
@@ -118,12 +141,24 @@ public class ResponderChain: ObservableObject {
118141}
119142
120143@available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
121- extension View {
122- public func responderTag< Tag: Hashable > ( _ tag: Tag ) -> some View {
123- inject ( FindResponderSibling ( tag: tag) )
144+ private struct ResponderChainWindowFinder : ViewModifier {
145+ @State private var window : PlatformWindow ? = nil
146+
147+ func body( content: Content ) -> some View {
148+ Group {
149+ if let window = window {
150+ content. environmentObject ( ResponderChain ( forWindow: window) )
151+ } else {
152+ EmptyView ( )
153+ }
154+ } . introspect ( selector: { $0. self } ) {
155+ self . window = $0. window
156+ }
124157 }
125158}
126159
160+ // MARK: - Tag
161+
127162@available ( iOS 13 . 0 , OSX 10 . 15 , tvOS 13 . 0 , watchOS 6 . 0 , * )
128163private struct FindResponderSibling < Tag: Hashable > : View {
129164 @EnvironmentObject var responderChain : ResponderChain
0 commit comments