121 lines
3.3 KiB
Swift
121 lines
3.3 KiB
Swift
//
|
|
// NavigationStack.swift
|
|
// MacBackend
|
|
//
|
|
// Created by david-swift on 14.12.2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
/// The navigation stack view.
|
|
public struct NavigationStack<Component>: SwiftUIWidget where Component: CustomStringConvertible {
|
|
|
|
/// The current navigation path.
|
|
@Meta.Binding var path: NavigationPath
|
|
/// The content.
|
|
var content: (Component) -> Body
|
|
/// The initial view.
|
|
var initialView: Body
|
|
|
|
/// The wrapped views.
|
|
public var wrappedViews: [String: Meta.AnyView] {
|
|
if let current = path.current {
|
|
_ = current
|
|
return [.mainContent: initialView, current.description: content(current)]
|
|
} else {
|
|
return [.mainContent: initialView]
|
|
}
|
|
}
|
|
|
|
/// Initialize the navigation stack.
|
|
/// - Parameters:
|
|
/// - path: The path.
|
|
/// - content: The content.
|
|
/// - initialView: The initial view.
|
|
public init(
|
|
path: Meta.Binding<NavigationPath>,
|
|
@Meta.ViewBuilder content: @escaping (Component) -> Body,
|
|
@Meta.ViewBuilder initialView: () -> Body
|
|
) {
|
|
self._path = path
|
|
self.content = content
|
|
self.initialView = initialView()
|
|
}
|
|
|
|
/// The navigation path.
|
|
public struct NavigationPath {
|
|
|
|
/// The path.
|
|
var path: [Component] = []
|
|
/// The current component.
|
|
var current: Component? { path.last }
|
|
|
|
/// The path as an array of strings.
|
|
var hashable: [String] {
|
|
get {
|
|
path.map { $0.description }
|
|
}
|
|
set {
|
|
if newValue.count < hashable.count {
|
|
_ = path.popLast()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Initialize a navigation stack.
|
|
public init() { }
|
|
|
|
/// Pop the last element.
|
|
public mutating func pop() {
|
|
_ = path.popLast()
|
|
}
|
|
|
|
/// Add a new element.
|
|
/// - Parameter component: The element.
|
|
public mutating func push(_ component: Component) {
|
|
path.append(component)
|
|
}
|
|
|
|
}
|
|
|
|
/// Receive the SwiftUI view.
|
|
/// - Parameter properties: The properties.
|
|
/// - Returns: The SwiftUI view.
|
|
public static func view(properties: Self) -> some SwiftUI.View {
|
|
SwiftUINavigationStack(path: properties.$path.swiftUI)
|
|
}
|
|
|
|
}
|
|
|
|
/// The SwiftUI navigation stack.
|
|
struct SwiftUINavigationStack<Component>: SwiftUI.View where Component: CustomStringConvertible {
|
|
|
|
/// The path.
|
|
@SwiftUI.Binding var path: NavigationPath<Component>
|
|
/// The views.
|
|
@SwiftUI.Environment(\.views)
|
|
var views
|
|
|
|
/// The view's body.
|
|
var body: some SwiftUI.View {
|
|
SwiftUI.NavigationStack(path: $path.hashable) {
|
|
let view = MacBackendView(.mainContent)
|
|
if path.current != nil {
|
|
view
|
|
.navigationDestination(for: String.self) { string in
|
|
SwiftUI.VStack {
|
|
MacBackendView(string)
|
|
.environment(\.views, views)
|
|
}
|
|
}
|
|
} else {
|
|
view
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// The navigation path.
|
|
public typealias NavigationPath<Component: CustomStringConvertible> = NavigationStack<Component>.NavigationPath
|