diff --git a/Assets/RoutingBannerArt.png b/Assets/RoutingBannerArt.png
deleted file mode 100644
index aacdaaa..0000000
Binary files a/Assets/RoutingBannerArt.png and /dev/null differ
diff --git a/ExampleApp/ContentView.swift b/ExampleApp/ContentView.swift
index c76a26e..460c746 100644
--- a/ExampleApp/ContentView.swift
+++ b/ExampleApp/ContentView.swift
@@ -1,21 +1,21 @@
//
// ContentView.swift
-// Routing
+// SwiftUI-Navigation
//
// Created by James Sedlacek on 5/7/25.
//
-import Routing
+import Navigation
import SwiftUI
@MainActor
public struct ContentView: View {
- @Router private var router: [TestRoute] = []
+ @DestinationState private var destinations: [TestDestination] = []
public init() {}
public var body: some View {
- RoutingView(path: $router) {
+ Navigator(path: $destinations) {
VStack {
Button("Push Screen", action: pushScreenAction)
}
@@ -24,7 +24,7 @@ public struct ContentView: View {
@MainActor
private func pushScreenAction() {
- router.navigate(to: .example("Hello World!"))
+ destinations.navigate(to: .example("Hello World!"))
}
}
diff --git a/ExampleApp/ExampleApp.swift b/ExampleApp/ExampleApp.swift
index da70011..7eb423e 100644
--- a/ExampleApp/ExampleApp.swift
+++ b/ExampleApp/ExampleApp.swift
@@ -1,6 +1,6 @@
//
// ExampleApp.swift
-// Routing
+// SwiftUI-Navigation
//
// Created by James Sedlacek on 5/7/25.
//
diff --git a/ExampleApp/ExampleView.swift b/ExampleApp/ExampleView.swift
index 20ca0ea..35b5f83 100644
--- a/ExampleApp/ExampleView.swift
+++ b/ExampleApp/ExampleView.swift
@@ -1,9 +1,9 @@
-import Routing
+import Navigation
import SwiftUI
public struct ExampleView: View {
- @Router private var router: [TestRoute] = []
- @State private var sheetRoute: SheetRoute? = nil
+ @DestinationState private var destinations: [TestDestination] = []
+ @State private var sheetDestination: SheetDestination? = nil
private let title: String
@MainActor
@@ -19,21 +19,21 @@ public struct ExampleView: View {
Button("Present Sheet", action: presentSheetAction)
}
- .sheet(item: $sheetRoute)
+ .sheet(item: $sheetDestination)
}
@MainActor
private func pushScreenAction() {
- router.navigate(to: .lastExample)
+ destinations.navigate(to: .lastExample)
}
private func presentSheetAction() {
- sheetRoute = .sheetExample("It's a whole new world!")
+ sheetDestination = .sheetExample("It's a whole new world!")
}
}
public struct SheetExampleView: View {
- @State private var route: AnotherRoute? = nil
+ @State private var destination: AnotherDestination? = nil
private let title: String
public init(title: String) {
@@ -47,12 +47,12 @@ public struct SheetExampleView: View {
Text(title)
}
- .navigationDestination(item: $route)
+ .navigationDestination(item: $destination)
}
}
private func pushScreenAction() {
- route = .anotherExample("Testing")
+ destination = .anotherExample("Testing")
}
}
@@ -69,7 +69,7 @@ public struct AnotherExampleView: View {
}
public struct LastExampleView: View {
- @Router private var router: [TestRoute] = []
+ @DestinationState private var destinations: [TestDestination] = []
@MainActor
public init() {}
@@ -80,6 +80,6 @@ public struct LastExampleView: View {
@MainActor
private func navigateToRootAction() {
- router.navigateToRoot()
+ destinations.navigateToRoot()
}
}
diff --git a/ExampleApp/TestRoute.swift b/ExampleApp/TestDestination.swift
similarity index 75%
rename from ExampleApp/TestRoute.swift
rename to ExampleApp/TestDestination.swift
index 36cd5ec..36fbcba 100644
--- a/ExampleApp/TestRoute.swift
+++ b/ExampleApp/TestDestination.swift
@@ -1,14 +1,14 @@
//
-// TestRoute.swift
-// Routing
+// TestDestination.swift
+// SwiftUI-Navigation
//
// Created by James Sedlacek on 5/7/25.
//
-import Routing
+import Navigation
import SwiftUI
-public enum TestRoute: Routable {
+public enum TestDestination: Destination {
case example(String)
case lastExample
@@ -22,7 +22,7 @@ public enum TestRoute: Routable {
}
}
-public enum SheetRoute: Routable {
+public enum SheetDestination: Destination {
case sheetExample(String)
public var body: some View {
@@ -33,11 +33,11 @@ public enum SheetRoute: Routable {
}
}
-extension SheetRoute: Identifiable {
+extension SheetDestination: Identifiable {
public nonisolated var id: Self { self }
}
-public enum AnotherRoute: Routable {
+public enum AnotherDestination: Destination {
case anotherExample(String)
public var body: some View {
diff --git a/Package.swift b/Package.swift
index 7c2c7cf..1539d82 100644
--- a/Package.swift
+++ b/Package.swift
@@ -4,7 +4,7 @@
import PackageDescription
let package = Package(
- name: "Routing",
+ name: "SwiftUI-Navigation",
platforms: [
.iOS(.v16),
.macOS(.v13),
@@ -13,8 +13,8 @@ let package = Package(
],
products: [
.library(
- name: "Routing",
- targets: ["Routing"]
+ name: "Navigation",
+ targets: ["Navigation"]
),
.executable(
name: "ExampleApp",
@@ -22,15 +22,15 @@ let package = Package(
)
],
targets: [
- .target(name: "Routing"),
+ .target(name: "Navigation"),
.executableTarget(
name: "ExampleApp",
- dependencies: ["Routing"],
+ dependencies: ["Navigation"],
path: "ExampleApp"
),
.testTarget(
- name: "RoutingTests",
- dependencies: ["Routing"]
+ name: "SwiftUINavigationTests",
+ dependencies: ["Navigation"]
),
]
)
diff --git a/README.md b/README.md
index dd059ce..1143b68 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,15 @@
-
-
-
+# SwiftUI-Navigation
[](https://github.com/apple/swift-package-manager)
-[](https://github.com/JamesSedlacek/Routing/stargazers)
-[](https://github.com/JamesSedlacek/Routing/network)
-[](https://github.com/JamesSedlacek/Routing/network)
-
-
+[](https://github.com/JamesSedlacek/SwiftUI-Navigation/stargazers)
+[](https://github.com/JamesSedlacek/SwiftUI-Navigation/network)
+[](https://github.com/JamesSedlacek/SwiftUI-Navigation/network)
+
+
## Description
-`Routing` is a **lightweight** SwiftUI navigation library.
+`SwiftUI-Navigation` is a **lightweight** SwiftUI navigation library.
- Leverages 1st-party APIs `NavigationStack` & `NavigationDestination`.
- Never be confused about `NavigationLink` or `NavigationPath` again! (You don't need them)
- Type-Safe Navigation (better performance than type-erasing).
@@ -29,7 +27,6 @@
4. [Passing Data Example](#passing-data-example)
5. [View Extensions](#view-extensions)
6. [Under the hood](#under-the-hood)
-7. [Author](#author)
@@ -46,30 +43,30 @@
## Installation
-You can install `Routing` using the Swift Package Manager.
+You can install `SwiftUI-Navigation` using the Swift Package Manager.
1. In Xcode, select `File` > `Add Package Dependencies`.
2. Copy & paste the following into the `Search or Enter Package URL` search bar.
```
-https://github.com/JamesSedlacek/Routing.git
+https://github.com/JamesSedlacek/SwiftUI-Navigation.git
```
-3. Xcode will fetch the repository & the `Routing` library will be added to your project.
+3. Xcode will fetch the repository & the `SwiftUI-Navigation` library will be added to your project.
## Getting Started
-1. Create a `Route` enum that conforms to the `Routable` protocol.
+1. Create a `Destination` enum that conforms to the `Destination` protocol.
``` swift
-import Routing
+import Navigation
import SwiftUI
-enum ExampleRoute: Routable {
+enum ExampleDestination: Destination {
case detail
case settings
@@ -84,26 +81,26 @@ enum ExampleRoute: Routable {
}
```
-2. Create a `Router` object and wrap your `RootView` with a `RoutingView`.
+2. Create a `DestinationState` object and wrap your `RootView` with a `Navigator`.
``` swift
import SwiftUI
-import Routing
+import Navigation
struct ContentView: View {
- @Router private var router: [ExampleRoute] = []
+ @DestinationState private var destinations: [ExampleDestination] = []
var body: some View {
- RoutingView(path: $router) {
+ Navigator(path: $destinations) {
Button("Go to Settings") {
- router.navigate(to: .settings)
+ destinations.navigate(to: .settings)
}
}
}
}
```
-3. Handle navigation using the `Router` functions
+3. Handle navigation using the `DestinationState` functions
```swift
/// Navigate back in the stack by a specified count.
@@ -130,10 +127,10 @@ func replace(with destinations: [Destination])
## Passing Data Example
```swift
-import Routing
+import Navigation
import SwiftUI
-enum ContentRoute: Routable {
+enum ContentDestination: Destination {
case detail(Color)
case settings
@@ -148,15 +145,15 @@ enum ContentRoute: Routable {
}
struct ContentView: View {
- @Router private var router: [ContentRoute] = []
+ @DestinationState private var destinations: [ContentDestination] = []
private let colors: [Color] = [.red, .green, .blue]
var body: some View {
- RoutingView(path: $router) {
+ Navigator(path: $destinations) {
List(colors, id: \.self) { color in
color
.onTapGesture {
- router.navigate(to: .detail(color))
+ destinations.navigate(to: .detail(color))
}
}
}
@@ -180,34 +177,34 @@ struct ColorDetail: View {
## View Extensions
-`Routing` provides several `View` extensions to simplify common navigation and presentation patterns when working with `Routable` types.
+`SwiftUI-Navigation` provides several `View` extensions to simplify common navigation and presentation patterns when working with `Destination` types.
-### `navigationDestination(for: RouteType.self)`
+### `navigationDestination(for: DestinationType.self)`
-This extension is a convenience wrapper around the standard SwiftUI `navigationDestination(for:destination:)` modifier. It's tailored for use with types conforming to `Routable`, automatically using the `Routable` instance itself as the destination view.
+This extension is a convenience wrapper around the standard SwiftUI `navigationDestination(for:destination:)` modifier. It's tailored for use with types conforming to `Destination`, automatically using the `Destination` instance itself as the destination view.
```swift
// Usage within a view:
-// SomeView().navigationDestination(for: MyRoute.self)
-// This is often handled automatically by RoutingView.
+// SomeView().navigationDestination(for: MyDestination.self)
+// This is often handled automatically by Navigator.
```
-`RoutingView` uses this extension internally to set up navigation for your `Routable` enum.
+`Navigator` uses this extension internally to set up navigation for your `Destination` enum.
### `sheet(item:onDismiss:)`
-Presents a sheet when a binding to an optional `Routable & Identifiable` item becomes non-nil. The content of the sheet is the `Routable` item itself.
+Presents a sheet when a binding to an optional `Destination & Identifiable` item becomes non-nil. The content of the sheet is the `Destination` item itself.
-- `item`: A `Binding` to an optional `Routable & Identifiable` item.
+- `item`: A `Binding` to an optional `Destination & Identifiable` item.
- `onDismiss`: An optional closure executed when the sheet dismisses.
-**Note:** The `Routable` type used with this modifier must also conform to `Identifiable`.
+**Note:** The `Destination` type used with this modifier must also conform to `Identifiable`.
```swift
import SwiftUI
-import Routing
+import Navigation
-// Ensure your Routable enum conforms to Identifiable.
+// Ensure your Destination enum conforms to Identifiable.
// For enums with associated values, you might need to add an explicit `id`.
-enum ModalRoute: Routable, Identifiable {
+enum ModalDestination: Destination, Identifiable {
case helpPage
case userDetails(id: String)
@@ -232,7 +229,7 @@ enum ModalRoute: Routable, Identifiable {
}
struct MyContentView: View {
- @State private var sheetItem: ModalRoute?
+ @State private var sheetItem: ModalDestination?
var body: some View {
Button("Show Help Sheet") {
@@ -254,23 +251,23 @@ struct UserDetailsView: View {
Available on iOS 17.0+, macOS 14.0+, tvOS 17.0+, watchOS 10.0+.
-Presents a view using `navigationDestination(item:destination:)` when a binding to an optional `Routable` item becomes non-nil. The destination view is the `Routable` item itself. This is useful for modal-style presentations or alternative navigation flows that don't necessarily push onto the main `NavigationStack`.
+Presents a view using `navigationDestination(item:destination:)` when a binding to an optional `Destination` item becomes non-nil. The destination view is the `Destination` item itself. This is useful for modal-style presentations or alternative navigation flows that don't necessarily push onto the main `NavigationStack`.
-- `item`: A `Binding` to an optional `Routable` item.
+- `item`: A `Binding` to an optional `Destination` item.
```swift
import SwiftUI
-import Routing
+import Navigation
-// Assuming MyDetailRoute is a Routable enum
-// enum MyDetailRoute: Routable { case info, settings ... }
+// Assuming MyDetailDestination is a Destination enum
+// enum MyDetailDestination: Destination { case info, settings ... }
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
struct AnotherScreen: View {
- @State private var presentedDetail: MyDetailRoute? // MyDetailRoute conforms to Routable
+ @State private var presentedDetail: MyDetailDestination? // MyDetailDestination conforms to Destination
var body: some View {
Button("Show Info Modally") {
- presentedDetail = .info // Assuming .info is a case in MyDetailRoute
+ presentedDetail = .info // Assuming .info is a case in MyDetailDestination
}
.navigationDestination(item: $presentedDetail)
}
@@ -281,15 +278,11 @@ struct AnotherScreen: View {
## Under the hood
-The `RoutingView` essentially wraps your view with a `NavigationStack`. It uses the `navigationDestination(for: RouteType.self)` view extension (detailed in the "View Extensions" section) to automatically handle presenting the views associated with your `Routable` types.
+The `Navigator` essentially wraps your view with a `NavigationStack`. It uses the `navigationDestination(for: DestinationType.self)` view extension (detailed in the "View Extensions" section) to automatically handle presenting the views associated with your `Destination` types.
```swift
-// Simplified structure of RoutingView's body:
-NavigationStack(path: $path) { // $path is your @Router's binding
+// Simplified structure of Navigator's body:
+NavigationStack(path: $path) { // $path is your @DestinationState's binding
rootContent()
- .navigationDestination(for: RouteType.self) // Uses the Routable-specific extension
+ .navigationDestination(for: DestinationType.self) // Uses the Destination-specific extension
}
```
-
-## Author
-
-James Sedlacek, find me on [X/Twitter](https://twitter.com/jsedlacekjr) or [LinkedIn](https://www.linkedin.com/in/jamessedlacekjr/)
diff --git a/Sources/Routing/Extensions/Array+Truncate.swift b/Sources/Navigation/Models/Array+Truncate.swift
similarity index 100%
rename from Sources/Routing/Extensions/Array+Truncate.swift
rename to Sources/Navigation/Models/Array+Truncate.swift
diff --git a/Sources/Routing/Protocols/Routable.swift b/Sources/Navigation/Models/Destination.swift
similarity index 67%
rename from Sources/Routing/Protocols/Routable.swift
rename to Sources/Navigation/Models/Destination.swift
index 819ccc3..97049e0 100644
--- a/Sources/Routing/Protocols/Routable.swift
+++ b/Sources/Navigation/Models/Destination.swift
@@ -1,5 +1,5 @@
//
-// Routable.swift
+// Destination.swift
//
// Created by James Sedlacek on 12/14/23.
//
@@ -8,14 +8,14 @@ import SwiftUI
/// A convenience type-alias used throughout the routing system.
///
-/// It bundles the three capabilities a “route” typically needs:
+/// It bundles the three capabilities a “destination” typically needs:
/// • `View` – supplies the screen’s UI
-/// • `Hashable` – lets the route live inside navigation paths/sets
+/// • `Hashable` – lets the destination live inside navigation paths/sets
/// • `Codable` – enables persistence & deep-link restoration
///
/// Usage:
/// ```swift
-///public enum TestRoute: Routable {
+///public enum TestDestination: Destination {
/// case example(String)
/// case lastExample
///
@@ -29,4 +29,4 @@ import SwiftUI
/// }
///}
/// ```
-public typealias Routable = View & Hashable & Codable
+public typealias Destination = View & Hashable & Codable
diff --git a/Sources/Routing/Extensions/Array+Routing.swift b/Sources/Navigation/Models/DestinationArray+.swift
similarity index 96%
rename from Sources/Routing/Extensions/Array+Routing.swift
rename to Sources/Navigation/Models/DestinationArray+.swift
index b48ca03..85e1908 100644
--- a/Sources/Routing/Extensions/Array+Routing.swift
+++ b/Sources/Navigation/Models/DestinationArray+.swift
@@ -1,5 +1,5 @@
//
-// Array+Routing.swift
+// DestinationArray+.swift
//
// Created by James Sedlacek on 12/16/23.
//
@@ -7,7 +7,7 @@
import SwiftUI
@MainActor
-public extension Array where Element: Routable {
+public extension Array where Element: Destination {
/// Navigate back in the navigation stack by a specified number of destinations.
///
diff --git a/Sources/Routing/PropertyWrappers/Router.swift b/Sources/Navigation/Models/DestinationState.swift
similarity index 61%
rename from Sources/Routing/PropertyWrappers/Router.swift
rename to Sources/Navigation/Models/DestinationState.swift
index 8a26c05..15d3a30 100644
--- a/Sources/Routing/PropertyWrappers/Router.swift
+++ b/Sources/Navigation/Models/DestinationState.swift
@@ -1,52 +1,52 @@
//
-// Router.swift
+// DestinationState.swift
//
// Created by James Sedlacek on 12/15/23.
//
import SwiftUI
-/// A property-wrapper that keeps a stack of `Routable` values in `UserDefaults`
+/// A property-wrapper that keeps a stack of `Destination` values in `UserDefaults`
/// (via `@AppStorage`) and exposes it to SwiftUI as mutable state.
///
-/// The encoded array is stored under the supplied key (default: `"RouterKey"`),
+/// The encoded array is stored under the supplied key (default: `"DestinationStateKey"`),
/// allowing the navigation stack to survive app launches or scene re-creation.
///
/// Basic usage:
///
/// ```swift
-/// enum AppRoute: String, Routable {
+/// enum AppDestination: String, Destination {
/// case home, detail, settings
/// }
///
/// struct ContentView: View {
-/// @Router var routes: [AppRoute] = [.home] // stored under "RouterKey"
+/// @DestinationState var destinations: [AppDestination] = [.home] // stored under "DestinationStateKey"
///
/// var body: some View { /* … */ }
/// }
///
/// // Custom key / UserDefaults instance
-/// @Router("OnboardingRoutes", store: .standard)
-/// var onboarding: [OnboardingRoute] = [.welcome]
+/// @DestinationState("OnboardingDestinations", store: .standard)
+/// var onboarding: [OnboardingDestination] = [.welcome]
/// ```
///
/// Access patterns:
-/// • Read/Write: `routes.append(.detail)`
-/// • Bindable: `$routes` to drive a `NavigationStack` or similar.
+/// • Read/Write: `destinations.append(.detail)`
+/// • Bindable: `$destinations` to drive a `NavigationStack` or similar.
///
/// - Note: Encoding/decoding uses `JSONEncoder` / `JSONDecoder`. If encoding
/// fails the `defaultValue` is returned silently.
@MainActor
@propertyWrapper
-public struct Router: DynamicProperty {
+public struct DestinationState: DynamicProperty {
@AppStorage private var storage: Data
private let encoder: JSONEncoder = .init()
private let decoder: JSONDecoder = .init()
- private let defaultValue: [RouteType]
+ private let defaultValue: [T]
- public var wrappedValue: [RouteType] {
+ public var wrappedValue: [T] {
get {
- guard let decoded = try? decoder.decode([RouteType].self, from: storage) else {
+ guard let decoded = try? decoder.decode([T].self, from: storage) else {
return defaultValue
}
return decoded
@@ -57,7 +57,7 @@ public struct Router: DynamicProperty {
}
}
- public var projectedValue: Binding<[RouteType]> {
+ public var projectedValue: Binding<[T]> {
Binding(
get: { wrappedValue },
set: { wrappedValue = $0 }
@@ -65,8 +65,8 @@ public struct Router: DynamicProperty {
}
public init(
- wrappedValue: [RouteType],
- _ key: String = "RouterKey",
+ wrappedValue: [T],
+ _ key: String = "DestinationStateKey",
store: UserDefaults? = nil
) {
defaultValue = wrappedValue
diff --git a/Sources/Routing/Views/RoutingView.swift b/Sources/Navigation/Views/Navigator.swift
similarity index 55%
rename from Sources/Routing/Views/RoutingView.swift
rename to Sources/Navigation/Views/Navigator.swift
index c49a8cc..f53f436 100644
--- a/Sources/Routing/Views/RoutingView.swift
+++ b/Sources/Navigation/Views/Navigator.swift
@@ -1,23 +1,23 @@
//
-// RoutingView.swift
-// Routing
+// Navigator.swift
+// SwiftUI-Navigation
//
import SwiftUI
/// A thin convenience wrapper around `NavigationStack` that
-/// drives navigation from an external `[RouteType]` array.
+/// drives navigation from an external `[DestinationType]` array.
///
-/// `RoutingView` lets you keep the navigation “path” outside
-/// of your view hierarchy (e.g. in `@AppStorage` via `@Router`)
+/// `Navigator` lets you keep the navigation “path” outside
+/// of your view hierarchy (e.g. in `@AppStorage` via `@DestinationState`)
/// while still enjoying type-safe `NavigationStack` behaviour.
/// The view creates its own `NavigationStack` under-the-hood
/// and forwards a binding to the caller-supplied `path`.
///
/// Usage:
/// ```swift
-/// enum MyRoute: Routable { // 1️⃣ Conform to Routable
-/// case profile(Int) // Your route cases
+/// enum MyDestination: Destination { // 1️⃣ Conform to Destination
+/// case profile(Int) // Your destination cases
///
/// var body: some View { // Each case returns a view
/// switch self {
@@ -28,10 +28,10 @@ import SwiftUI
/// }
///
/// struct RootView: View {
-/// @Router private var path: [MyRoute] = [] // 2️⃣ Persist the path
+/// @DestinationState private var path: [MyDestination] = [] // 2️⃣ Persist the path
///
/// var body: some View {
-/// RoutingView(path: $path) { // 3️⃣ Wrap your root UI
+/// Navigator(path: $path) { // 3️⃣ Wrap your root UI
/// VStack {
/// Button("Show profile") {
/// path.navigate(to: .profile(42))
@@ -43,15 +43,15 @@ import SwiftUI
/// ```
///
/// - Parameters:
-/// - RouteType: The enum/struct you use to describe destinations.
-/// Must conform to `Routable`.
+/// - DestinationType: The enum/struct you use to describe destinations.
+/// Must conform to `Destination`.
/// - RootContent: The root view shown at the bottom of the stack.
-public struct RoutingView: View {
- @Binding private var path: [RouteType]
+public struct Navigator: View {
+ @Binding private var path: [DestinationType]
private let rootContent: () -> RootContent
public init(
- path: Binding<[RouteType]>,
+ path: Binding<[DestinationType]>,
@ViewBuilder rootContent: @escaping () -> RootContent
) {
self._path = path
@@ -61,7 +61,7 @@ public struct RoutingView: View {
public var body: some View {
NavigationStack(path: $path) {
rootContent()
- .navigationDestination(for: RouteType.self)
+ .navigationDestination(for: DestinationType.self)
}
}
}
diff --git a/Sources/Routing/Views/View+Extensions.swift b/Sources/Navigation/Views/View+Extensions.swift
similarity index 56%
rename from Sources/Routing/Views/View+Extensions.swift
rename to Sources/Navigation/Views/View+Extensions.swift
index bdcd348..27b83f2 100644
--- a/Sources/Routing/Views/View+Extensions.swift
+++ b/Sources/Navigation/Views/View+Extensions.swift
@@ -1,6 +1,6 @@
//
// View+Extensions.swift
-// Routing
+// SwiftUI-Navigation
//
// Created by James Sedlacek on 5/6/25.
//
@@ -11,43 +11,43 @@ public extension View {
/// Associates a destination view with a presented data type for use within a navigation stack.
///
/// This is a convenience wrapper around the standard SwiftUI `navigationDestination(for:destination:)` modifier,
- /// tailored for use with types conforming to `Routable`. The destination view is the presented `Routable` instance itself.
+ /// tailored for use with types conforming to `Destination`. The destination view is the presented `Destination` instance itself.
///
- /// - Parameter routeType: The type of `Routable` data that this destination binding supports.
- /// This should be the metatype (e.g., `MyRoute.self`).
- /// - Returns: A view that has a navigation destination associated with the specified `Routable` data type.
- func navigationDestination(for routeType: D.Type) -> some View {
+ /// - Parameter destinationType: The type of `Destination` data that this destination binding supports.
+ /// This should be the metatype (e.g., `MyDestination.self`).
+ /// - Returns: A view that has a navigation destination associated with the specified `Destination` data type.
+ func navigationDestination(for destinationType: D.Type) -> some View {
self.navigationDestination(for: D.self, destination: { $0 })
}
- /// Presents a sheet when a binding to an optional `Routable` item becomes non-nil.
+ /// Presents a sheet when a binding to an optional `Destination` item becomes non-nil.
///
/// This is a convenience wrapper around the standard SwiftUI `sheet(item:onDismiss:content:)` modifier,
- /// tailored for use with types conforming to `Routable`. The content of the sheet is the item itself.
+ /// tailored for use with types conforming to `Destination`. The content of the sheet is the item itself.
///
/// - Parameters:
- /// - item: A `Binding` to an optional `Routable` item. When `item` is non-nil,
+ /// - item: A `Binding` to an optional `Destination` item. When `item` is non-nil,
/// the system passes the unwrapped item to the `content` closure, which then provides
/// the view for the sheet. If `item` becomes `nil`, the system dismisses the sheet.
/// - onDismiss: An optional closure that SwiftUI executes when the sheet dismisses.
/// - Returns: A view that presents a sheet when the bound item is non-nil.
- func sheet(item: Binding, onDismiss: (() -> Void)? = nil) -> some View {
+ func sheet(item: Binding, onDismiss: (() -> Void)? = nil) -> some View {
self.sheet(item: item, onDismiss: onDismiss, content: { $0 })
}
}
@available(iOS 17.0, macOS 14.0, tvOS 17.0, watchOS 10.0, *)
public extension View {
- /// Presents a view when a binding to an optional `Routable` item becomes non-nil.
+ /// Presents a view when a binding to an optional `Destination` item becomes non-nil.
///
/// This is a convenience wrapper around the standard SwiftUI `navigationDestination(item:destination:)` modifier,
- /// tailored for use with types conforming to `Routable`. The destination view is the item itself.
+ /// tailored for use with types conforming to `Destination`. The destination view is the item itself.
///
- /// - Parameter item: A `Binding` to an optional `Routable` item. When `item` is non-nil,
+ /// - Parameter item: A `Binding` to an optional `Destination` item. When `item` is non-nil,
/// the system passes the unwrapped item to the `destination` closure, which then provides
/// the view to display. If `item` becomes `nil`, the system dismisses the presented view.
/// - Returns: A view that presents another view when the bound item is non-nil.
- func navigationDestination(item: Binding) -> some View {
+ func navigationDestination(item: Binding) -> some View {
self.navigationDestination(item: item, destination: { $0 })
}
}
diff --git a/Tests/RoutingTests/ArrayRoutingTests.swift b/Tests/SwiftUINavigationTests/ArraySwiftUINavigationTests.swift
similarity index 75%
rename from Tests/RoutingTests/ArrayRoutingTests.swift
rename to Tests/SwiftUINavigationTests/ArraySwiftUINavigationTests.swift
index 40857a7..d1e733a 100644
--- a/Tests/RoutingTests/ArrayRoutingTests.swift
+++ b/Tests/SwiftUINavigationTests/ArraySwiftUINavigationTests.swift
@@ -1,17 +1,17 @@
//
-// ArrayRoutingTests.swift
+// ArraySwiftUINavigationTests.swift
//
// Created by James Sedlacek on 12/16/23.
//
import Testing
-@testable import Routing
+@testable import Navigation
@MainActor
-struct ArrayRoutingTests {
+struct ArraySwiftUINavigationTests {
@Test("Navigate to a single destination")
func navigateToSingleDestination() {
- var stack: [MockRoute] = []
+ var stack: [MockDestination] = []
stack.navigate(to: .settings)
#expect(stack.count == 1)
#expect(stack.last == .settings)
@@ -19,7 +19,7 @@ struct ArrayRoutingTests {
@Test("Navigate to multiple destinations")
func navigateToMultipleDestinations() {
- var stack: [MockRoute] = []
+ var stack: [MockDestination] = []
stack.navigate(to: [.settings, .profile, .settings])
#expect(stack.count == 3)
#expect(stack == [.settings, .profile, .settings])
@@ -27,7 +27,7 @@ struct ArrayRoutingTests {
@Test("Navigate back one step")
func navigateBackOneStep() {
- var stack: [MockRoute] = [.settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile]
stack.navigateBack()
#expect(stack.count == 1)
#expect(stack == [.settings])
@@ -35,7 +35,7 @@ struct ArrayRoutingTests {
@Test("Navigate back zero steps")
func navigateBackZeroSteps() {
- var stack: [MockRoute] = [.settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile]
stack.navigateBack(0)
#expect(stack.count == 2)
#expect(stack == [.settings, .profile])
@@ -43,7 +43,7 @@ struct ArrayRoutingTests {
@Test("Navigate back negative steps")
func navigateBackNegativeSteps() {
- var stack: [MockRoute] = [.settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile]
stack.navigateBack(-1)
#expect(stack.count == 2)
#expect(stack == [.settings, .profile])
@@ -51,7 +51,7 @@ struct ArrayRoutingTests {
@Test("Navigate back multiple steps")
func navigateBackMultipleSteps() {
- var stack: [MockRoute] = [.settings, .profile, .settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile, .settings, .profile]
stack.navigateBack(2)
#expect(stack.count == 2)
#expect(stack == [.settings, .profile])
@@ -59,21 +59,21 @@ struct ArrayRoutingTests {
@Test("Navigate back too many steps")
func navigateBackTooManySteps() {
- var stack: [MockRoute] = [.settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile]
stack.navigateBack(3)
#expect(stack.isEmpty)
}
@Test("Navigate to root")
func navigateToRoot() {
- var stack: [MockRoute] = [.settings, .profile, .settings]
+ var stack: [MockDestination] = [.settings, .profile, .settings]
stack.navigateToRoot()
#expect(stack.isEmpty)
}
@Test("Navigate back to a specific destination")
func navigateBackToSpecificDestination() {
- var stack: [MockRoute] = [.settings, .profile, .settings, .profile, .settings]
+ var stack: [MockDestination] = [.settings, .profile, .settings, .profile, .settings]
stack.navigateBack(to: .profile) // Navigates back to the last occurrence of .profile
#expect(stack.count == 4)
#expect(stack == [.settings, .profile, .settings, .profile])
@@ -81,7 +81,7 @@ struct ArrayRoutingTests {
@Test("Navigate back to a non-existent destination in the stack")
func navigateBackToNonExistentDestination() {
- var stack: [MockRoute] = [.settings, .settings, .settings]
+ var stack: [MockDestination] = [.settings, .settings, .settings]
// .profile is not in the stack, so it should do nothing.
stack.navigateBack(to: .profile)
#expect(stack.count == 3)
@@ -90,7 +90,7 @@ struct ArrayRoutingTests {
@Test("Navigate back to a specific destination that is currently on top")
func navigateBackToDestinationOnTop() {
- var stack: [MockRoute] = [.settings, .profile]
+ var stack: [MockDestination] = [.settings, .profile]
stack.navigateBack(to: .profile)
#expect(stack.count == 2)
#expect(stack == [.settings, .profile])
@@ -98,21 +98,21 @@ struct ArrayRoutingTests {
@Test("Navigate back to the first occurrence of a destination")
func navigateBackToFirstOccurrence() {
- var stack: [MockRoute] = [.profile, .settings, .profile, .settings]
+ var stack: [MockDestination] = [.profile, .settings, .profile, .settings]
stack.navigateBack(to: .profile) // Should go to the second .profile
#expect(stack == [.profile, .settings, .profile])
}
@Test("Replace stack with empty destinations")
func replaceWithEmptyDestinations() {
- var stack: [MockRoute] = [.settings, .profile, .settings]
+ var stack: [MockDestination] = [.settings, .profile, .settings]
stack.replace(with: [])
#expect(stack.isEmpty)
}
@Test("Replace stack with new destinations")
func replaceWithNewDestinations() {
- var stack: [MockRoute] = [.settings, .settings]
+ var stack: [MockDestination] = [.settings, .settings]
stack.replace(with: [.profile, .settings, .profile])
#expect(stack.count == 3)
#expect(stack == [.profile, .settings, .profile])
diff --git a/Tests/RoutingTests/ArrayTruncationTests.swift b/Tests/SwiftUINavigationTests/ArrayTruncationTests.swift
similarity index 97%
rename from Tests/RoutingTests/ArrayTruncationTests.swift
rename to Tests/SwiftUINavigationTests/ArrayTruncationTests.swift
index 04ce284..012500c 100644
--- a/Tests/RoutingTests/ArrayTruncationTests.swift
+++ b/Tests/SwiftUINavigationTests/ArrayTruncationTests.swift
@@ -6,7 +6,7 @@
//
import Testing
-@testable import Routing
+@testable import Navigation
struct ArrayTruncationTests {
@Test func truncateToValidIndex() {
diff --git a/Tests/RoutingTests/Mocks/MockRoute.swift b/Tests/SwiftUINavigationTests/Mocks/MockDestination.swift
similarity index 85%
rename from Tests/RoutingTests/Mocks/MockRoute.swift
rename to Tests/SwiftUINavigationTests/Mocks/MockDestination.swift
index 640ca94..52a680d 100644
--- a/Tests/RoutingTests/Mocks/MockRoute.swift
+++ b/Tests/SwiftUINavigationTests/Mocks/MockDestination.swift
@@ -1,14 +1,14 @@
//
-// MockRoute.swift
+// MockDestination.swift
//
//
// Created by James Sedlacek on 2/10/24.
//
-import Routing
+import Navigation
import SwiftUI
-enum MockRoute: Routable {
+enum MockDestination: Destination {
case settings
case profile