Cascading Action system for SwiftUI. Read more about it here: http://www.magnuskahr.dk/posts/2021/12/cascading-environment-actions-in-swiftui/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
extension View { | |
func cascadingAction<ActionInput>(path: CascadingActionNodeModifier<ActionInput>.Path, handler: @escaping (ActionInput) -> Void) -> some View { | |
self.modifier(CascadingActionNodeModifier(path: path, handler: handler)) | |
} | |
func cascadingAction(path: CascadingActionNodeModifier<Void>.Path, handler: @escaping () -> Void) -> some View { | |
self.modifier(CascadingActionNodeModifier(path: path, handler: handler)) | |
} | |
} | |
struct CascadingActionNodeModifier<ActionInput>: ViewModifier { | |
typealias Path = WritableKeyPath<EnvironmentValues, CascadingAction<ActionInput>> | |
@Environment private var parent: CascadingAction<ActionInput> | |
let handler: (ActionInput) -> Void | |
let path: Path | |
init(path: Path, handler: @escaping (ActionInput) -> Void) { | |
self._parent = Environment(path) | |
self.handler = handler | |
self.path = path | |
} | |
func body(content: Content) -> some View { | |
content.environment(path, node) | |
} | |
private var node: CascadingAction<ActionInput> { | |
.node(parent: parent, action: handler) | |
} | |
} | |
indirect enum CascadingAction<Input> { | |
typealias Action = (Input) -> Void | |
case root | |
case node(parent: Self, action: Action) | |
func callAsFunction(_ input: Input) { | |
if case let .node(parent, action) = self { | |
action(input) | |
parent(input) | |
} | |
} | |
} | |
extension CascadingAction where Input == Void { | |
func callAsFunction() { | |
self.callAsFunction(_: ()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment