From 7b891d68b5d4ad2c98b546340a60bde725d1a9f9 Mon Sep 17 00:00:00 2001 From: Muukii Date: Sat, 12 Aug 2023 22:50:08 +0900 Subject: [PATCH] :zap: WIP --- Development/Demo/RootView.swift | 44 +-- Development/Demo/ViewController.swift | 57 ---- .../Storybook.xcodeproj/project.pbxproj | 11 - .../BookViewPresentableType.swift | 40 --- .../Compositions/BookForEach.swift | 42 --- .../StorybookKit/Compositions/BookGroup.swift | 33 -- .../Compositions/BookPadding.swift | 13 +- .../StorybookKit/Compositions/BookScope.swift | 37 --- .../Compositions/BookSection.swift | 52 +--- .../Deprecates/BookHeadline.swift | 41 --- .../Hosting/_ViewControllerHost.swift | 29 ++ Sources/StorybookKit/Hosting/_ViewHost.swift | 29 ++ Sources/StorybookKit/Primitives/Book.swift | 27 +- .../StorybookKit/Primitives/BookAction.swift | 26 +- .../StorybookKit/Primitives/BookCallout.swift | 187 ------------ .../Primitives/BookInteractive.swift | 129 -------- .../Primitives/BookNavigationLink.swift | 38 +-- .../StorybookKit/Primitives/BookPage.swift | 22 +- .../StorybookKit/Primitives/BookPresent.swift | 13 +- .../StorybookKit/Primitives/BookPreview.swift | 283 ++++++++---------- .../StorybookKit/Primitives/BookPush.swift | 16 +- .../StorybookKit/Primitives/BookText.swift | 62 +--- .../StorybookKit/Primitives/BookTree.swift | 42 --- .../StorybookKit/Primitives/BookView.swift | 32 +- .../Primitives/ComponentBuilder.swift | 78 ----- .../StorybookDisplayRootView.swift | 19 ++ .../TargetViewControllerKey.swift | 14 + .../Typography/BookHeading1.swift | 40 --- .../Typography/BookHeading2.swift | 40 --- .../Typography/BookHeading3.swift | 42 --- .../Typography/BookParagraph.swift | 40 --- .../BookNodePreview.swift | 7 +- Sources/StorybookUI/Extensions.swift | 120 -------- .../SwiftUI/StorybookDisplayRootView.swift | 107 ------- 34 files changed, 347 insertions(+), 1465 deletions(-) delete mode 100644 Development/Demo/ViewController.swift delete mode 100644 Sources/StorybookKit/BookViewPresentableType.swift delete mode 100644 Sources/StorybookKit/Compositions/BookForEach.swift delete mode 100644 Sources/StorybookKit/Compositions/BookGroup.swift delete mode 100644 Sources/StorybookKit/Compositions/BookScope.swift delete mode 100644 Sources/StorybookKit/Deprecates/BookHeadline.swift create mode 100644 Sources/StorybookKit/Hosting/_ViewControllerHost.swift create mode 100644 Sources/StorybookKit/Hosting/_ViewHost.swift delete mode 100644 Sources/StorybookKit/Primitives/BookCallout.swift delete mode 100644 Sources/StorybookKit/Primitives/BookInteractive.swift delete mode 100644 Sources/StorybookKit/Primitives/BookTree.swift delete mode 100644 Sources/StorybookKit/Primitives/ComponentBuilder.swift create mode 100644 Sources/StorybookKit/StorybookDisplayRootView.swift create mode 100644 Sources/StorybookKit/TargetViewControllerKey.swift delete mode 100644 Sources/StorybookKit/Typography/BookHeading1.swift delete mode 100644 Sources/StorybookKit/Typography/BookHeading2.swift delete mode 100644 Sources/StorybookKit/Typography/BookHeading3.swift delete mode 100644 Sources/StorybookKit/Typography/BookParagraph.swift delete mode 100644 Sources/StorybookUI/Extensions.swift delete mode 100644 Sources/StorybookUI/SwiftUI/StorybookDisplayRootView.swift diff --git a/Development/Demo/RootView.swift b/Development/Demo/RootView.swift index 5f2a3cc..cdd3d25 100644 --- a/Development/Demo/RootView.swift +++ b/Development/Demo/RootView.swift @@ -21,8 +21,8 @@ import Foundation import MyUIKit -import StorybookUI import SwiftUI +import StorybookKit import SwiftUISupport struct RootView: View { @@ -38,27 +38,27 @@ struct RootView: View { ) } - NavigationLink("Open classic") { - ViewControllerHost( - instantiated: { - let controller = StorybookViewController(book: myBook) { - $0.dismiss(animated: true, completion: nil) - } - return controller - }() - ) - } - - NavigationLink("Open filter") { - ViewControllerHost( - instantiated: { - let controller = StorybookFilterViewController(book: myBook) { - $0.dismiss(animated: true, completion: nil) - } - return controller - }() - ) - } +// NavigationLink("Open classic") { +// ViewControllerHost( +// instantiated: { +// let controller = StorybookViewController(book: myBook) { +// $0.dismiss(animated: true, completion: nil) +// } +// return controller +// }() +// ) +// } +// +// NavigationLink("Open filter") { +// ViewControllerHost( +// instantiated: { +// let controller = StorybookFilterViewController(book: myBook) { +// $0.dismiss(animated: true, completion: nil) +// } +// return controller +// }() +// ) +// } } } diff --git a/Development/Demo/ViewController.swift b/Development/Demo/ViewController.swift deleted file mode 100644 index 81834a3..0000000 --- a/Development/Demo/ViewController.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -import MyUIKit -import StorybookUI - -class ViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - } - - @IBAction private func didTapPresentButton(_ sender: Any) { - - let controller = StorybookViewController(book: myBook) { - $0.dismiss(animated: true, completion: nil) - } - - controller.modalPresentationStyle = .fullScreen - - present(controller, animated: true, completion: nil) - } - - @IBAction private func didTapFilterButton(_ sender: Any) { - - let controller = StorybookFilterViewController(book: myBook) { - $0.dismiss(animated: true, completion: nil) - } - - controller.modalPresentationStyle = .fullScreen - - present(controller, animated: true, completion: nil) - } - -} - diff --git a/Development/Storybook.xcodeproj/project.pbxproj b/Development/Storybook.xcodeproj/project.pbxproj index 27e567f..5a6d926 100644 --- a/Development/Storybook.xcodeproj/project.pbxproj +++ b/Development/Storybook.xcodeproj/project.pbxproj @@ -9,11 +9,9 @@ /* Begin PBXBuildFile section */ 4B0BDD7F2A87A4C800CF2633 /* StorybookKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4B0BDD7E2A87A4C800CF2633 /* StorybookKit */; }; 4B0BDD812A87A4C800CF2633 /* StorybookKitTextureSupport in Frameworks */ = {isa = PBXBuildFile; productRef = 4B0BDD802A87A4C800CF2633 /* StorybookKitTextureSupport */; }; - 4B0BDD832A87A4C800CF2633 /* StorybookUI in Frameworks */ = {isa = PBXBuildFile; productRef = 4B0BDD822A87A4C800CF2633 /* StorybookUI */; }; 4B0BDD852A87A4DA00CF2633 /* StorybookKit in Frameworks */ = {isa = PBXBuildFile; productRef = 4B0BDD842A87A4DA00CF2633 /* StorybookKit */; }; 4B81F791246F34BE009C7602 /* DSLCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B81F790246F34BE009C7602 /* DSLCheck.swift */; }; 4BB03C0922267064006E9E49 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB03C0822267064006E9E49 /* AppDelegate.swift */; }; - 4BB03C0B22267064006E9E49 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB03C0A22267064006E9E49 /* ViewController.swift */; }; 4BB03C1022267065006E9E49 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BB03C0F22267065006E9E49 /* Assets.xcassets */; }; 4BB03C1322267065006E9E49 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BB03C1122267065006E9E49 /* LaunchScreen.storyboard */; }; 4BB03C2A2226709D006E9E49 /* MyUIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BB03C282226709D006E9E49 /* MyUIKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -57,7 +55,6 @@ 4B81F790246F34BE009C7602 /* DSLCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DSLCheck.swift; sourceTree = ""; }; 4BB03C0622267064006E9E49 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4BB03C0822267064006E9E49 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 4BB03C0A22267064006E9E49 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 4BB03C0F22267065006E9E49 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 4BB03C1222267065006E9E49 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4BB03C1422267065006E9E49 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -79,7 +76,6 @@ files = ( 4BB655BA2A87B0C200F2E2D7 /* SwiftUISupport in Frameworks */, 4B0BDD812A87A4C800CF2633 /* StorybookKitTextureSupport in Frameworks */, - 4B0BDD832A87A4C800CF2633 /* StorybookUI in Frameworks */, 4B0BDD7F2A87A4C800CF2633 /* StorybookKit in Frameworks */, 4BB03C2D2226709D006E9E49 /* MyUIKit.framework in Frameworks */, ); @@ -107,7 +103,6 @@ isa = PBXGroup; children = ( 4BB03C0822267064006E9E49 /* AppDelegate.swift */, - 4BB03C0A22267064006E9E49 /* ViewController.swift */, 4BB03C0F22267065006E9E49 /* Assets.xcassets */, 4BB03C1122267065006E9E49 /* LaunchScreen.storyboard */, 4BB03C1422267065006E9E49 /* Info.plist */, @@ -193,7 +188,6 @@ packageProductDependencies = ( 4B0BDD7E2A87A4C800CF2633 /* StorybookKit */, 4B0BDD802A87A4C800CF2633 /* StorybookKitTextureSupport */, - 4B0BDD822A87A4C800CF2633 /* StorybookUI */, 4BB655B92A87B0C200F2E2D7 /* SwiftUISupport */, ); productName = Demo; @@ -288,7 +282,6 @@ buildActionMask = 2147483647; files = ( 4BB655B72A87B01000F2E2D7 /* RootView.swift in Sources */, - 4BB03C0B22267064006E9E49 /* ViewController.swift in Sources */, 4BB03C0922267064006E9E49 /* AppDelegate.swift in Sources */, 4B81F791246F34BE009C7602 /* DSLCheck.swift in Sources */, ); @@ -603,10 +596,6 @@ isa = XCSwiftPackageProductDependency; productName = StorybookKitTextureSupport; }; - 4B0BDD822A87A4C800CF2633 /* StorybookUI */ = { - isa = XCSwiftPackageProductDependency; - productName = StorybookUI; - }; 4B0BDD842A87A4DA00CF2633 /* StorybookKit */ = { isa = XCSwiftPackageProductDependency; productName = StorybookKit; diff --git a/Sources/StorybookKit/BookViewPresentableType.swift b/Sources/StorybookKit/BookViewPresentableType.swift deleted file mode 100644 index 816c421..0000000 --- a/Sources/StorybookKit/BookViewPresentableType.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -public protocol BookViewRepresentableType: BookView { - @MainActor - func makeView() -> UIView -} - -extension BookViewRepresentableType { - - public var body: BookView { - fatalError() - } - - public func asTree() -> BookTree { - .viewRepresentable(AnyBookViewRepresentable(self)) - } -} - - diff --git a/Sources/StorybookKit/Compositions/BookForEach.swift b/Sources/StorybookKit/Compositions/BookForEach.swift deleted file mode 100644 index 4a15a9f..0000000 --- a/Sources/StorybookKit/Compositions/BookForEach.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -public struct BookForEach: BookView { - - private let components: [Content] - - public init(data: S, @ComponentBuilder make: (S.Element) -> Content) { - let components = data.map { - make($0) - } - self.components = components - } - - public var body: BookView { - self - } - - public func asTree() -> BookTree { - .array(components.map { $0.asTree() }) - } -} diff --git a/Sources/StorybookKit/Compositions/BookGroup.swift b/Sources/StorybookKit/Compositions/BookGroup.swift deleted file mode 100644 index ae1c177..0000000 --- a/Sources/StorybookKit/Compositions/BookGroup.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -/// An affordance for grouping view content. -public struct BookGroup: BookView { - - public let body: BookView - - public init(@ComponentBuilder closure: () -> BookView) { - self.body = closure() - } - -} diff --git a/Sources/StorybookKit/Compositions/BookPadding.swift b/Sources/StorybookKit/Compositions/BookPadding.swift index b7da021..d252417 100644 --- a/Sources/StorybookKit/Compositions/BookPadding.swift +++ b/Sources/StorybookKit/Compositions/BookPadding.swift @@ -19,22 +19,23 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI public struct BookSpacer: BookView { - public func asTree() -> BookTree { - return .spacer(self) - } - public let height: CGFloat public init(height: CGFloat) { self.height = height } - public var body: BookView { + public var bookBody: any BookView { fatalError() } + public var body: some View { + Spacer(minLength: 0) + .frame(height: height) + } + } diff --git a/Sources/StorybookKit/Compositions/BookScope.swift b/Sources/StorybookKit/Compositions/BookScope.swift deleted file mode 100644 index d3be9e5..0000000 --- a/Sources/StorybookKit/Compositions/BookScope.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -public struct BookScope: BookView { - - let content: BookView - - public init(_ closure: () -> BookView) { - self.content = closure() - } - - - public var body: BookView { - content - } - -} diff --git a/Sources/StorybookKit/Compositions/BookSection.swift b/Sources/StorybookKit/Compositions/BookSection.swift index 8cb4fc1..81e03b3 100644 --- a/Sources/StorybookKit/Compositions/BookSection.swift +++ b/Sources/StorybookKit/Compositions/BookSection.swift @@ -19,58 +19,28 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI -public struct BookSection: BookView { +public struct BookSection: BookView { public let title: String - public let content: BookView + public let content: Content - @MainActor public init( title: String, - @ComponentBuilder content: @MainActor () -> BookView - ) { - self.title = title - self.content = content() - - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 8) - BookText(title) - .font(.systemFont(ofSize: 24, weight: .bold)) - BookSpacer(height: 16) - content - BookSpacer(height: 24) - } - } - -} - -public struct BookAlphabeticalNavigationLinkSection: BookView { - - public let title: String - public let content: BookView - - public init( - title: String, - @AlphabeticalNavigationLinkBuilder content: () -> BookView + @ViewBuilder content: () -> Content ) { self.title = title self.content = content() } - public var body: BookView { - BookGroup { - BookSpacer(height: 8) - BookText(title) - .font(.systemFont(ofSize: 24, weight: .bold)) - BookSpacer(height: 16) - content - BookSpacer(height: 24) - } + public var body: some View { + BookSpacer(height: 8) + BookText(title) + .font(.system(size: 24, weight: .bold)) + BookSpacer(height: 16) + content + BookSpacer(height: 24) } } diff --git a/Sources/StorybookKit/Deprecates/BookHeadline.swift b/Sources/StorybookKit/Deprecates/BookHeadline.swift deleted file mode 100644 index 8a2801f..0000000 --- a/Sources/StorybookKit/Deprecates/BookHeadline.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -@available(*, deprecated, renamed: "BookHeading1") -public struct BookHeadline: BookView { - - public let text: String - - public init(_ text: String) { - self.text = text - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 16) - BookText(text) - .font(.systemFont(ofSize: 24, weight: .medium)) - BookSpacer(height: 16) - } - } -} diff --git a/Sources/StorybookKit/Hosting/_ViewControllerHost.swift b/Sources/StorybookKit/Hosting/_ViewControllerHost.swift new file mode 100644 index 0000000..e7d7a02 --- /dev/null +++ b/Sources/StorybookKit/Hosting/_ViewControllerHost.swift @@ -0,0 +1,29 @@ +import SwiftUI + +struct _ViewControllerHost: + UIViewControllerRepresentable +{ + + private let instantiate: @MainActor () -> ContentViewController + private let _update: + @MainActor (_ uiViewController: ContentViewController, _ context: Context) -> Void + + init( + instantiate: @escaping @MainActor () -> ContentViewController, + update: @escaping @MainActor (_ uiViewController: ContentViewController, _ context: Context) -> + Void = { _, _ in } + ) { + self.instantiate = instantiate + self._update = update + } + + func makeUIViewController(context: Context) -> ContentViewController { + let instantiated = instantiate() + return instantiated + } + + func updateUIViewController(_ uiViewController: ContentViewController, context: Context) { + _update(uiViewController, context) + } + +} diff --git a/Sources/StorybookKit/Hosting/_ViewHost.swift b/Sources/StorybookKit/Hosting/_ViewHost.swift new file mode 100644 index 0000000..c03a5a8 --- /dev/null +++ b/Sources/StorybookKit/Hosting/_ViewHost.swift @@ -0,0 +1,29 @@ +import SwiftUI + +struct _ViewHost: + UIViewRepresentable +{ + + private let instantiate: @MainActor () -> ContentView + private let _update: + @MainActor (_ uiView: ContentView, _ context: Context) -> Void + + init( + instantiate: @escaping @MainActor () -> ContentView, + update: @escaping @MainActor (_ uiViewController: ContentView, _ context: Context) -> + Void = { _, _ in } + ) { + self.instantiate = instantiate + self._update = update + } + + func makeUIView(context: Context) -> ContentView { + let instantiated = instantiate() + return instantiated + } + + func updateUIView(_ uiView: ContentView, context: Context) { + _update(uiView, context) + } + +} diff --git a/Sources/StorybookKit/Primitives/Book.swift b/Sources/StorybookKit/Primitives/Book.swift index 2dcad37..305dc42 100644 --- a/Sources/StorybookKit/Primitives/Book.swift +++ b/Sources/StorybookKit/Primitives/Book.swift @@ -19,17 +19,30 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import Foundation +import SwiftUI -public struct Book { +public struct Book: View { - public let component: BookTree + public let content: Content public let title: String - - @MainActor - public init(title: String, @ComponentBuilder closure: @MainActor () -> _BookView) { + + public init( + title: String, + @ViewBuilder content: () -> Content + ) { self.title = title - self.component = closure().asTree() + self.content = content() + } + + public var body: some View { + NavigationView { + ScrollView { + VStack { + content + } + } + } + .navigationTitle(title) } } diff --git a/Sources/StorybookKit/Primitives/BookAction.swift b/Sources/StorybookKit/Primitives/BookAction.swift index 972117c..2b946b4 100644 --- a/Sources/StorybookKit/Primitives/BookAction.swift +++ b/Sources/StorybookKit/Primitives/BookAction.swift @@ -19,33 +19,35 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import Foundation -import UIKit +import SwiftUI public struct BookAction: BookView { - + + @Environment(\._targetViewController) var targetViewController + public let declarationIdentifier: DeclarationIdentifier public let action: @MainActor (UIViewController) -> Void public let title: String - public var body: BookView { - fatalError() - } - - @MainActor public init( title: String, - action: @escaping @MainActor (UIViewController) -> Void + action: @escaping (UIViewController) -> Void ) { self.title = title self.action = action self.declarationIdentifier = .init() } - public func asTree() -> BookTree { - return .action(self) + public var body: some View { + Button(title) { + if let targetViewController { + action(targetViewController) + } else { + + } + } } - + } diff --git a/Sources/StorybookKit/Primitives/BookCallout.swift b/Sources/StorybookKit/Primitives/BookCallout.swift deleted file mode 100644 index aef1145..0000000 --- a/Sources/StorybookKit/Primitives/BookCallout.swift +++ /dev/null @@ -1,187 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -public struct BookCallout: BookViewRepresentableType { - - public static func info(text: String) -> Self { - return .init(symbol: "☝️", text: text) - } - - public static func warning(text: String) -> Self { - return .init(symbol: "⚠️", text: text) - } - - public static func danger(text: String) -> Self { - return .init(symbol: "🚨", text: text) - } - - public static func success(text: String) -> Self { - return .init(symbol: "✅", text: text) - } - - public let symbol: String? - public let text: String - public var foregroundColor: UIColor = { - if #available(iOS 13.0, *) { - return .label - } else { - return .darkText - } - }() - - public var font: UIFont = .preferredFont(forTextStyle: .body) - - public init( - symbol: String? = nil, - text: String - ) { - self.symbol = symbol - self.text = text - } - - public func foregroundColor(_ color: UIColor) -> Self { - modified { - $0.foregroundColor = color - } - } - - public func font(_ font: UIFont) -> Self { - modified { - $0.font = font - } - } - - public func makeView() -> UIView { - _View( - symbol: symbol.map { - .init( - string: $0, - attributes: [ - .font: font, - .foregroundColor: foregroundColor, - ] - ) - }, - attributedString: .init( - string: text, - attributes: [ - .font: font, - .foregroundColor: foregroundColor, - ] - ) - ) - } - - private final class _View: UIView { - - private let symbolLabel: UILabel? - private let label: UILabel - private let backgroundView = UIView() - - public init( - symbol: NSAttributedString?, - attributedString: NSAttributedString - ) { - - self.label = .init() - - if symbol != nil { - symbolLabel = .init() - } else { - symbolLabel = nil - } - - super.init(frame: .zero) - - label.numberOfLines = 0 - - label.translatesAutoresizingMaskIntoConstraints = false - backgroundView.translatesAutoresizingMaskIntoConstraints = false - - addSubview(backgroundView) - backgroundView.addSubview(label) - - if let symbolLabel = symbolLabel { - - symbolLabel.setContentHuggingPriority(.required, for: .horizontal) - symbolLabel.translatesAutoresizingMaskIntoConstraints = false - symbolLabel.attributedText = symbol - backgroundView.addSubview(symbolLabel) - - NSLayoutConstraint.activate([ - - backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: 8), - backgroundView.rightAnchor.constraint(equalTo: rightAnchor, constant: -22), - backgroundView.leftAnchor.constraint(equalTo: leftAnchor, constant: 22), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8), - - symbolLabel.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 12), - symbolLabel.leftAnchor.constraint(equalTo: backgroundView.leftAnchor, constant: 12), - symbolLabel.bottomAnchor.constraint( - lessThanOrEqualTo: backgroundView.bottomAnchor, - constant: -12 - ), - - label.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 12), - label.rightAnchor.constraint(equalTo: backgroundView.rightAnchor, constant: -12), - label.leftAnchor.constraint(equalTo: symbolLabel.rightAnchor, constant: 8), - label.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -12), - - ]) - } else { - NSLayoutConstraint.activate([ - - backgroundView.topAnchor.constraint(equalTo: topAnchor, constant: 0), - backgroundView.rightAnchor.constraint(equalTo: rightAnchor, constant: -22), - backgroundView.leftAnchor.constraint(equalTo: leftAnchor, constant: 22), - backgroundView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0), - - label.topAnchor.constraint(equalTo: backgroundView.topAnchor, constant: 12), - label.rightAnchor.constraint(equalTo: backgroundView.rightAnchor, constant: -12), - label.leftAnchor.constraint(equalTo: backgroundView.leftAnchor, constant: 12), - label.bottomAnchor.constraint(equalTo: backgroundView.bottomAnchor, constant: -12), - - ]) - } - - backgroundView.backgroundColor = UIColor(white: 0.8, alpha: 0.3) - backgroundView.layer.cornerRadius = 8 - if #available(iOS 13.0, *) { - backgroundView.layer.cornerCurve = .continuous - } else { - // Fallback on earlier versions - } - - label.attributedText = attributedString - - } - - public required init?( - coder: NSCoder - ) { - fatalError("init(coder:) has not been implemented") - } - - } - -} diff --git a/Sources/StorybookKit/Primitives/BookInteractive.swift b/Sources/StorybookKit/Primitives/BookInteractive.swift deleted file mode 100644 index 76e9cb1..0000000 --- a/Sources/StorybookKit/Primitives/BookInteractive.swift +++ /dev/null @@ -1,129 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -/// A component descriptor that can control a UI-Component with specified button. -// TODO: Integrate BookDisplay -struct _BookButtons: BookViewRepresentableType { - - private var buttons: ContiguousArray<(title: String, handler: () -> Void)> = .init() - - init(buttons: ContiguousArray<(title: String, handler: () -> Void)>) { - self.buttons = buttons - } - - func makeView() -> UIView { - let view = _View( - actionDiscriptors: buttons.map { - _View.ActionDescriptor(title: $0.title, action: $0.handler) - }) - return view - } - -} - -fileprivate final class _View : UIView { - - // MARK: - Properties - - private let stackView: UIStackView = .init() - - // MARK: - Initializers - - public init(actionDiscriptors: [ActionDescriptor]) { - - super.init(frame: .zero) - - stack: do { - - stackView.distribution = .equalSpacing - stackView.spacing = 8 - stackView.axis = .horizontal - stackView.alignment = .fill - stackView.setContentHuggingPriority(.defaultHigh, for: .vertical) - - actionDiscriptors.forEach { descriptor in - - let button = ActionButton(type: .system) - - button.setTitle(descriptor.title, for: .normal) - button.addTarget(self, action: #selector(actionButtonTouchUpInside), for: .touchUpInside) - button.action = { - descriptor.action() - } - - stackView.addArrangedSubview(button) - - } - - } - - addSubview(stackView) - - stackView.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - stackView.topAnchor.constraint(equalTo: topAnchor), - stackView.rightAnchor.constraint(equalTo: rightAnchor), - stackView.leftAnchor.constraint(equalTo: leftAnchor), - stackView.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - - } - - @available(*, unavailable) - public required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - @objc - private func actionButtonTouchUpInside(button: ActionButton) { - button.action() - } - - // MARK: - Nested types - - private final class ActionButton : UIButton { - var action: () -> Void = {} - } - -} - -extension _View { - - struct ActionDescriptor { - - // MARK: - Properties - let title: String - - let action: () -> Void - - // MARK: - Initializers - - init(title: String, action: @escaping () -> Void) { - - self.title = title - self.action = action - } - } - -} diff --git a/Sources/StorybookKit/Primitives/BookNavigationLink.swift b/Sources/StorybookKit/Primitives/BookNavigationLink.swift index 5df1bda..9d3d00a 100644 --- a/Sources/StorybookKit/Primitives/BookNavigationLink.swift +++ b/Sources/StorybookKit/Primitives/BookNavigationLink.swift @@ -20,45 +20,49 @@ // THE SOFTWARE. import Foundation +import SwiftUI public struct DeclarationIdentifier: Hashable, Codable { public let index: Int - @MainActor - init() { - index = counter - counter += 1 + nonisolated init() { + index = issueUniqueNumber() } } -//private var map: [String : Int] = -@MainActor -private var counter: Int = 0 +private let _lock = NSLock() +private var _counter: Int = 0 +private func issueUniqueNumber() -> Int { + _lock.lock() + defer { + _lock.unlock() + } + _counter += 1 + return _counter +} /// A component that displays a disclosure view. -public struct BookNavigationLink: BookView { +public struct BookNavigationLink: BookView { public let title: String - public let component: BookTree + public let destination: Destination public let declarationIdentifier: DeclarationIdentifier @MainActor public init( title: String, - @ComponentBuilder closure: @MainActor () -> _BookView + @ViewBuilder destination: () -> Destination ) { self.title = title - self.component = closure().asTree() + self.destination = destination() self.declarationIdentifier = .init() } - public var body: BookView { - self - } - - public func asTree() -> BookTree { - .folder(self) + public var body: some View { + NavigationLink(title, destination: { + destination + }) } } diff --git a/Sources/StorybookKit/Primitives/BookPage.swift b/Sources/StorybookKit/Primitives/BookPage.swift index 985b3aa..0493ec9 100644 --- a/Sources/StorybookKit/Primitives/BookPage.swift +++ b/Sources/StorybookKit/Primitives/BookPage.swift @@ -20,29 +20,27 @@ // THE SOFTWARE. import Foundation +import SwiftUI -public struct BookPage: BookView { +public struct BookPage: BookView { public let title: String - public let content: BookView + public let content: Content public init( title: String, - @ComponentBuilder content: () -> BookView + @ViewBuilder content: () -> Content ) { self.title = title self.content = content() } - public var body: BookView { - BookGroup { - BookSpacer(height: 24) - BookText(title) - .font(.systemFont(ofSize: 32, weight: .bold)) - BookSpacer(height: 18) - content - } - + public var body: some View { + BookSpacer(height: 24) + BookText(title) + .font(.system(size: 32, weight: .bold)) + BookSpacer(height: 18) + content } } diff --git a/Sources/StorybookKit/Primitives/BookPresent.swift b/Sources/StorybookKit/Primitives/BookPresent.swift index 1cbe5d9..2378d04 100644 --- a/Sources/StorybookKit/Primitives/BookPresent.swift +++ b/Sources/StorybookKit/Primitives/BookPresent.swift @@ -19,14 +19,12 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI /// A component descriptor that just displays UI-Component public struct BookPresent: BookView { - public func asTree() -> BookTree { - return .present(self) - } + @Environment(\._targetViewController) private var targetViewController public let declarationIdentifier: DeclarationIdentifier public let presentedViewControllerBlock: @MainActor () -> UIViewController @@ -43,8 +41,11 @@ public struct BookPresent: BookView { self.declarationIdentifier = .init() } - public var body: BookView { - fatalError() + public var body: some View { + Button(title) { + let viewController = presentedViewControllerBlock() + targetViewController?.present(viewController, animated: true) + } } } diff --git a/Sources/StorybookKit/Primitives/BookPreview.swift b/Sources/StorybookKit/Primitives/BookPreview.swift index 7663972..f2b3e23 100644 --- a/Sources/StorybookKit/Primitives/BookPreview.swift +++ b/Sources/StorybookKit/Primitives/BookPreview.swift @@ -19,7 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI private struct FrameConstraint { var minWidth: CGFloat? = nil @@ -30,7 +30,7 @@ private struct FrameConstraint { var maxHeight: CGFloat? = nil } -public struct BookPreview: BookView { +public struct BookPreview: BookView { public var backgroundColor: UIColor = { if #available(iOS 13.0, *) { @@ -40,11 +40,11 @@ public struct BookPreview: BookView { } }() - public let viewBlock: @MainActor () -> View + public let viewBlock: @MainActor () -> PlatformView public let declarationIdentifier: DeclarationIdentifier - private var buttons: ContiguousArray<(title: String, handler: (View) -> Void)> = .init() + private var buttons: ContiguousArray<(title: String, handler: (PlatformView) -> Void)> = .init() private let file: StaticString private let line: UInt @@ -59,7 +59,7 @@ public struct BookPreview: BookView { expandsWidth: Bool = false, maxHeight: CGFloat? = nil, minHeight: CGFloat? = nil, - viewBlock: @escaping @MainActor () -> View + viewBlock: @escaping @MainActor () -> PlatformView ) { self.file = file @@ -81,7 +81,7 @@ public struct BookPreview: BookView { public init( _ file: StaticString = #file, _ line: UInt = #line, - viewBlock: @escaping @MainActor () -> View + viewBlock: @escaping @MainActor () -> PlatformView ) { self.file = file @@ -92,46 +92,25 @@ public struct BookPreview: BookView { } - public var body: BookView { - - weak var createdView: View? - - return BookGroup { - _BookPreview( - frameConstraint: frameConstraint, - backgroundColor: backgroundColor, - viewBlock: { - let view = self.viewBlock() - createdView = view - return view - } - ) - if buttons.isEmpty == false { - BookSpacer(height: 8) - _BookButtons( - buttons: ContiguousArray( - buttons.map { args in - (args.0, { args.1(createdView!) }) - } - ) - ) - } - BookCallout( - text: """ - \(file):\(line) - """ - ) - .font( - { - if #available(iOS 13, *) { - return .monospacedSystemFont(ofSize: 8, weight: .regular) - } else { - return .systemFont(ofSize: 8, weight: .regular) - } - }() - ) - BookSpacer(height: 16) + public var body: some View { + + _ViewHost(instantiate: { + _View(element: viewBlock(), frameConstraint: frameConstraint) + }, update: { _, _ in }) + + if buttons.isEmpty == false { +// BookSpacer(height: 8) +// _BookButtons( +// buttons: ContiguousArray( +// buttons.map { args in +// (args.0, { args.1(createdView!) }) +// } +// ) +// ) } + Text("\(file.description):\(line.description)") + .font(.body.monospacedDigit()) + BookSpacer(height: 16) } public func previewFrame( @@ -169,157 +148,151 @@ public struct BookPreview: BookView { } } - public func addButton(_ title: String, handler: @escaping (View) -> Void) -> Self { + public func addButton(_ title: String, handler: @escaping (PlatformView) -> Void) -> Self { modified { $0.buttons.append((title: title, handler: handler)) } } - public func title(_ text: String) -> BookGroup { - .init { + public func title(_ text: String) -> some View { + Group { BookSpacer(height: 8) BookText(text) - .font( - { - if #available(iOS 13, *) { - return .monospacedSystemFont(ofSize: 17, weight: .semibold) - } else { - return .systemFont(ofSize: 17, weight: .semibold) - } - }() - ) + .font(.system(size: 17, weight: .semibold)) self } } } -/// A component descriptor that just displays UI-Component -private struct _BookPreview: BookViewRepresentableType { - - let viewBlock: @MainActor () -> View - - let backgroundColor: UIColor - let frameConstraint: FrameConstraint +///// A component descriptor that just displays UI-Component +//private struct _BookPreview: BookViewRepresentableType { +// +// let viewBlock: @MainActor () -> View +// +// let backgroundColor: UIColor +// let frameConstraint: FrameConstraint +// +// init( +// frameConstraint: FrameConstraint, +// backgroundColor: UIColor, +// viewBlock: @escaping @MainActor () -> View +// ) { +// +// self.frameConstraint = frameConstraint +// self.backgroundColor = backgroundColor +// self.viewBlock = viewBlock +// } +// +// func makeView() -> UIView { +// let view = _View( +// element: viewBlock(), +// frameConstraint: frameConstraint +// ) +// view.backgroundColor = backgroundColor +// return view +// } +// +// +// +//} - init( - frameConstraint: FrameConstraint, - backgroundColor: UIColor, - viewBlock: @escaping @MainActor () -> View - ) { +private final class _View: UIView { - self.frameConstraint = frameConstraint - self.backgroundColor = backgroundColor - self.viewBlock = viewBlock + init() { + super.init(frame: .zero) } - func makeView() -> UIView { - let view = _View( - element: viewBlock(), - frameConstraint: frameConstraint - ) - view.backgroundColor = backgroundColor - return view + @available(*, unavailable) + required init?( + coder aDecoder: NSCoder + ) { + fatalError("init(coder:) has not been implemented") } - private final class _View: UIView { - - init() { - super.init(frame: .zero) - } - - @available(*, unavailable) - required init?( - coder aDecoder: NSCoder - ) { - fatalError("init(coder:) has not been implemented") - } + convenience init( + element: UIView, + frameConstraint: FrameConstraint + ) { - convenience init( - element: UIView, - frameConstraint: FrameConstraint - ) { - - self.init() - - element.translatesAutoresizingMaskIntoConstraints = false - element.setContentHuggingPriority(.defaultLow, for: .horizontal) - element.setContentHuggingPriority(.defaultLow, for: .vertical) - - addSubview(element) - - var constraints: [NSLayoutConstraint] = [] - - if let maxWidth = frameConstraint.maxWidth { - if (maxWidth == .infinity) || (maxWidth == .greatestFiniteMagnitude) { - let c = element.widthAnchor.constraint(equalToConstant: 5000) - c.priority = .defaultHigh + 1 - constraints.append( - c - ) - } else { - constraints.append( - element.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth) - ) - } - } + self.init() - if let maxHeight = frameConstraint.minHeight { + element.translatesAutoresizingMaskIntoConstraints = false + element.setContentHuggingPriority(.defaultLow, for: .horizontal) + element.setContentHuggingPriority(.defaultLow, for: .vertical) - if (maxHeight == .infinity) || (maxHeight == .greatestFiniteMagnitude) { - let c = element.heightAnchor.constraint(equalToConstant: 5000) - c.priority = .defaultHigh + 1 - constraints.append( - c - ) - } else { + addSubview(element) - constraints.append( - element.heightAnchor.constraint(lessThanOrEqualToConstant: maxHeight) - ) - } - } + var constraints: [NSLayoutConstraint] = [] - if let minWidth = frameConstraint.minWidth { + if let maxWidth = frameConstraint.maxWidth { + if (maxWidth == .infinity) || (maxWidth == .greatestFiniteMagnitude) { + let c = element.widthAnchor.constraint(equalToConstant: 5000) + c.priority = .defaultHigh + 1 constraints.append( - element.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth) + c ) - } - - if let minHeight = frameConstraint.minHeight { - + } else { constraints.append( - element.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight) + element.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth) ) } + } - if let idealWidth = frameConstraint.idealWidth { + if let maxHeight = frameConstraint.minHeight { + + if (maxHeight == .infinity) || (maxHeight == .greatestFiniteMagnitude) { + let c = element.heightAnchor.constraint(equalToConstant: 5000) + c.priority = .defaultHigh + 1 constraints.append( - element.widthAnchor.constraint(equalToConstant: idealWidth) + c ) - } + } else { - if let idealHeight = frameConstraint.idealHeight { constraints.append( - element.heightAnchor.constraint(equalToConstant: idealHeight) + element.heightAnchor.constraint(lessThanOrEqualToConstant: maxHeight) ) } + } - constraints.append(contentsOf: [ - - element.centerXAnchor.constraint(equalTo: centerXAnchor), - element.centerYAnchor.constraint(equalTo: centerYAnchor), + if let minWidth = frameConstraint.minWidth { + constraints.append( + element.widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth) + ) + } - element.topAnchor.constraint(greaterThanOrEqualTo: topAnchor), - element.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor), - element.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor), - element.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor), + if let minHeight = frameConstraint.minHeight { - ]) + constraints.append( + element.heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight) + ) + } - NSLayoutConstraint.activate(constraints) + if let idealWidth = frameConstraint.idealWidth { + constraints.append( + element.widthAnchor.constraint(equalToConstant: idealWidth) + ) + } + if let idealHeight = frameConstraint.idealHeight { + constraints.append( + element.heightAnchor.constraint(equalToConstant: idealHeight) + ) } + constraints.append(contentsOf: [ + + element.centerXAnchor.constraint(equalTo: centerXAnchor), + element.centerYAnchor.constraint(equalTo: centerYAnchor), + + element.topAnchor.constraint(greaterThanOrEqualTo: topAnchor), + element.leftAnchor.constraint(greaterThanOrEqualTo: leftAnchor), + element.rightAnchor.constraint(lessThanOrEqualTo: rightAnchor), + element.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor), + + ]) + + NSLayoutConstraint.activate(constraints) + } -} + } diff --git a/Sources/StorybookKit/Primitives/BookPush.swift b/Sources/StorybookKit/Primitives/BookPush.swift index a457274..38e1b05 100644 --- a/Sources/StorybookKit/Primitives/BookPush.swift +++ b/Sources/StorybookKit/Primitives/BookPush.swift @@ -19,7 +19,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI /// A component descriptor that previewing with push presentation. public struct BookPush: BookView { @@ -29,11 +29,6 @@ public struct BookPush: BookView { public let title: String - public var body: BookView { - fatalError() - } - - @MainActor public init( title: String, pushingViewControllerBlock: @escaping @MainActor () -> UIViewController @@ -43,8 +38,11 @@ public struct BookPush: BookView { self.declarationIdentifier = .init() } - public func asTree() -> BookTree { - return .push(self) - } + public var body: some View { + NavigationLink(title, destination: { + _ViewControllerHost(instantiate: pushingViewControllerBlock) + }) + + } } diff --git a/Sources/StorybookKit/Primitives/BookText.swift b/Sources/StorybookKit/Primitives/BookText.swift index efb5400..d72da96 100644 --- a/Sources/StorybookKit/Primitives/BookText.swift +++ b/Sources/StorybookKit/Primitives/BookText.swift @@ -19,9 +19,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -import UIKit +import SwiftUI -public struct BookText: BookViewRepresentableType { +public struct BookText: View { public let text: String public var foregroundColor: UIColor = { @@ -38,62 +38,8 @@ public struct BookText: BookViewRepresentableType { self.text = text } - public func foregroundColor(_ color: UIColor) -> Self { - modified { - $0.foregroundColor = color - } - } - - public func font(_ font: UIFont) -> Self { - modified { - $0.font = font - } - } - - public func makeView() -> UIView { - _View(attributedString: .init( - string: text, - attributes: [ - .font : font, - .foregroundColor : foregroundColor - ] - ) - ) - } - - private final class _View: UIView { - - private let label: UILabel - - public init(attributedString: NSAttributedString) { - - self.label = .init() - - super.init(frame: .zero) - - label.numberOfLines = 0 - - label.translatesAutoresizingMaskIntoConstraints = false - - addSubview(label) - - NSLayoutConstraint.activate([ - - label.topAnchor.constraint(equalTo: topAnchor, constant: 0), - label.rightAnchor.constraint(equalTo: rightAnchor, constant: -24), - label.leftAnchor.constraint(equalTo: leftAnchor, constant: 24), - label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0), - - ]) - - label.attributedText = attributedString - - } - - public required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - + public var body: some View { + Text(text) } } diff --git a/Sources/StorybookKit/Primitives/BookTree.swift b/Sources/StorybookKit/Primitives/BookTree.swift deleted file mode 100644 index f3f429f..0000000 --- a/Sources/StorybookKit/Primitives/BookTree.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -/// A structure of Book -public indirect enum BookTree: BookView { - - case folder(BookNavigationLink) - case viewRepresentable(AnyBookViewRepresentable) - case present(BookPresent) - case push(BookPush) - case spacer(BookSpacer) - case single(_BookView?) - case array([BookTree]) - case action(BookAction) - - public var body: BookView { - self - } - - public func asTree() -> BookTree { - self - } -} - diff --git a/Sources/StorybookKit/Primitives/BookView.swift b/Sources/StorybookKit/Primitives/BookView.swift index 61cd228..6a71d85 100644 --- a/Sources/StorybookKit/Primitives/BookView.swift +++ b/Sources/StorybookKit/Primitives/BookView.swift @@ -20,24 +20,13 @@ // THE SOFTWARE. import UIKit +import SwiftUI -public protocol _BookView { +public protocol BookView: SwiftUI.View { - func asTree() -> BookTree -} - -public protocol BookView: _BookView { - - var body: BookView { get } } extension BookView { - public func asTree() -> BookTree { - return .single(body) - } -} - -extension _BookView { public func modified(_ modify: (inout Self) -> Void) -> Self { var s = self @@ -47,20 +36,3 @@ extension _BookView { } -public struct AnyBookViewRepresentable: BookViewRepresentableType { - - private let _makeView: @MainActor () -> UIView - - public init(_ element: E) { - - self._makeView = element.makeView - } - - public func asTree() -> BookTree { - return .viewRepresentable(self) - } - - public func makeView() -> UIView { - _makeView() - } -} diff --git a/Sources/StorybookKit/Primitives/ComponentBuilder.swift b/Sources/StorybookKit/Primitives/ComponentBuilder.swift deleted file mode 100644 index 1a59094..0000000 --- a/Sources/StorybookKit/Primitives/ComponentBuilder.swift +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -@resultBuilder -public enum ComponentBuilder { - - public static func buildBlock(_ element: E) -> BookTree { - return .viewRepresentable(.init(element)) - } - - public static func buildExpression(_ component: _BookView) -> BookTree { - return component.asTree() - } - - public static func buildBlock(_ component: _BookView) -> BookTree { - return component.asTree() - } - - public static func buildBlock(_ components: _BookView...) -> BookTree { - return .array(components.map { $0.asTree() }) - } - - public static func buildExpression(_ components: [_BookView]) -> BookTree { - return .array(components.map { $0.asTree() }) - } - - public static func buildExpression(_ components: [BookView]) -> BookTree { - return .array(components.map { $0.asTree() }) - } - - public static func buildIf(_ value: _BookView?) -> BookTree { - return .single(value) - } - - public static func buildEither(first component: BookTree) -> BookTree { - return .single(component) - } - - public static func buildEither(second component: BookTree) -> BookTree { - return .single(component) - } - -} - -@resultBuilder -public enum AlphabeticalNavigationLinkBuilder { - - public static func buildBlock(_ component: BookNavigationLink) -> BookTree { - return component.asTree() - } - - public static func buildBlock(_ components: BookNavigationLink...) -> BookTree { - let sortedComponents = components.sorted { - $0.title.lowercased() < $1.title.lowercased() - } - return .array(sortedComponents.map { $0.asTree() }) - } -} diff --git a/Sources/StorybookKit/StorybookDisplayRootView.swift b/Sources/StorybookKit/StorybookDisplayRootView.swift new file mode 100644 index 0000000..88e035b --- /dev/null +++ b/Sources/StorybookKit/StorybookDisplayRootView.swift @@ -0,0 +1,19 @@ +import SwiftUI +import UIKit +import SwiftUISupport + +public struct StorybookDisplayRootView: View { + + public let book: Book + public let targetViewController: UIViewController + + public init(book: Book, targetViewController: UIViewController) { + self.book = book + self.targetViewController = targetViewController + } + + public var body: some View { + book + .environment(\._targetViewController, targetViewController) + } +} diff --git a/Sources/StorybookKit/TargetViewControllerKey.swift b/Sources/StorybookKit/TargetViewControllerKey.swift new file mode 100644 index 0000000..8eab4bc --- /dev/null +++ b/Sources/StorybookKit/TargetViewControllerKey.swift @@ -0,0 +1,14 @@ +import SwiftUI + +enum _ViewControllerKey: EnvironmentKey { + typealias Value = UIViewController? + + static var defaultValue: UIViewController? +} + +extension EnvironmentValues { + var _targetViewController: UIViewController? { + get { self[_ViewControllerKey.self] } + set { self[_ViewControllerKey.self] = newValue } + } +} diff --git a/Sources/StorybookKit/Typography/BookHeading1.swift b/Sources/StorybookKit/Typography/BookHeading1.swift deleted file mode 100644 index ccc39bf..0000000 --- a/Sources/StorybookKit/Typography/BookHeading1.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -public struct BookHeading1: BookView { - - public let text: String - - public init(_ text: String) { - self.text = text - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 16) - BookText(text) - .font(.systemFont(ofSize: 24, weight: .medium)) - BookSpacer(height: 16) - } - } -} diff --git a/Sources/StorybookKit/Typography/BookHeading2.swift b/Sources/StorybookKit/Typography/BookHeading2.swift deleted file mode 100644 index 4068278..0000000 --- a/Sources/StorybookKit/Typography/BookHeading2.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation - -public struct BookHeading2: BookView { - - public let text: String - - public init(_ text: String) { - self.text = text - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 16) - BookText(text) - .font(.systemFont(ofSize: 20, weight: .medium)) - BookSpacer(height: 16) - } - } -} diff --git a/Sources/StorybookKit/Typography/BookHeading3.swift b/Sources/StorybookKit/Typography/BookHeading3.swift deleted file mode 100644 index cbf26a2..0000000 --- a/Sources/StorybookKit/Typography/BookHeading3.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -public struct BookHeading3: BookView { - - public let text: String - - public init( - _ text: String - ) { - self.text = text - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 16) - BookText(text) - .font(.systemFont(ofSize: 20, weight: .medium)) - BookSpacer(height: 16) - } - } -} diff --git a/Sources/StorybookKit/Typography/BookParagraph.swift b/Sources/StorybookKit/Typography/BookParagraph.swift deleted file mode 100644 index 0a5e10b..0000000 --- a/Sources/StorybookKit/Typography/BookParagraph.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import UIKit - -public struct BookParagraph: BookView { - - public let text: String - - public init(_ text: String) { - self.text = text - } - - public var body: BookView { - BookGroup { - BookSpacer(height: 12) - BookText(text) - .font(.systemFont(ofSize: 16, weight: .medium)) - BookSpacer(height: 12) - } - } -} diff --git a/Sources/StorybookKitTextureSupport/BookNodePreview.swift b/Sources/StorybookKitTextureSupport/BookNodePreview.swift index eb2b902..3a6d298 100644 --- a/Sources/StorybookKitTextureSupport/BookNodePreview.swift +++ b/Sources/StorybookKitTextureSupport/BookNodePreview.swift @@ -20,7 +20,7 @@ // THE SOFTWARE. import AsyncDisplayKit -import Foundation +import SwiftUI import StorybookKit import TextureBridging import TextureSwiftSupport @@ -92,8 +92,7 @@ public struct BookNodePreview: BookView { } - - public var body: BookView { + public var body: some View { backing .backgroundColor(backgroundColor) } @@ -127,7 +126,7 @@ public struct BookNodePreview: BookView { } } - public func title(_ text: String) -> BookGroup { + public func title(_ text: String) -> some View { backing.title(text) } diff --git a/Sources/StorybookUI/Extensions.swift b/Sources/StorybookUI/Extensions.swift deleted file mode 100644 index f05190c..0000000 --- a/Sources/StorybookUI/Extensions.swift +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2020 Eureka, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import Foundation -import StorybookKit - -extension BookTree { - - func findLinks(byQuery string: String) -> [BookNavigationLink] { - - guard string.isEmpty == false else { - return [] - } - - var results: [BookNavigationLink] = [] - - func findLinks(_ tree: BookTree) { - switch tree { - case .folder(let v): - if v.title.contains(string) { - results.append(v) - } else { - findLinks(v.component.asTree()) - } - case .viewRepresentable: - break - case .single(let v?): - findLinks(v.asTree()) - case .single(.none): - break - case .array(let v): - for i in v { - findLinks(i) - } - case .present: - break - case .push: - break - case .spacer: - break - case .action: - break - } - } - - findLinks(self) - - return results - - } - - func findLink(by identifier: DeclarationIdentifier) -> BookView? { - - func findLink(_ tree: BookTree) -> BookView? { - switch tree { - case .folder(let v): - if v.declarationIdentifier == identifier { - return v - } else { - return findLink(v.component.asTree()) - } - case .viewRepresentable: - return nil - case .single(let v?): - return findLink(v.asTree()) - case .single(.none): - return nil - case .array(let v): - for i in v { - if let result = findLink(i) { - return result - } - } - return nil - case .present(let v): - if v.declarationIdentifier == identifier { - return v - } else { - return nil - } - case .push(let v): - if v.declarationIdentifier == identifier { - return v - } else { - return nil - } - case .spacer: - return nil - case .action(let v): - if v.declarationIdentifier == identifier { - return v - } else { - return nil - } - } - } - - return findLink(self) - - } - -} diff --git a/Sources/StorybookUI/SwiftUI/StorybookDisplayRootView.swift b/Sources/StorybookUI/SwiftUI/StorybookDisplayRootView.swift deleted file mode 100644 index da04567..0000000 --- a/Sources/StorybookUI/SwiftUI/StorybookDisplayRootView.swift +++ /dev/null @@ -1,107 +0,0 @@ -import StorybookKit -import SwiftUI -import UIKit -import SwiftUISupport - -public struct StorybookDisplayRootView: View { - - public let book: Book - public let targetViewController: UIViewController - - public init(book: Book, targetViewController: UIViewController) { - self.book = book - self.targetViewController = targetViewController - } - - public var body: some View { - NavigationView { - ScrollView { - VStack { - Text(book.title) - BookTreeWrapper(tree: book.component) - } - } - .environment(\._targetViewController, targetViewController) - } - } -} - -enum _ViewControllerKey: EnvironmentKey { - typealias Value = UIViewController? - - static var defaultValue: UIViewController? -} - -extension EnvironmentValues { - var _targetViewController: UIViewController? { - get { self[_ViewControllerKey.self] } - set { self[_ViewControllerKey.self] = newValue } - } -} - -struct BookTreeWrapper: View { - - @Environment(\._targetViewController) var targetViewController - - let tree: BookTree - - var body: some View { - switch tree { - case .action(let action): - Button(action.title) { - action.action(targetViewController!) - } - case .array(let trees): - ForEach(Array(trees.enumerated()), id: \.offset) { e in - BookTreeWrapper(tree: e.element) - } - case .folder(let link): - NavigationLink(link.title, destination: { - BookTreeWrapper(tree: link.component) - }) - case .present(let presentation): - Button(presentation.title) { - let viewController = presentation.presentedViewControllerBlock() - targetViewController?.present(viewController, animated: true) - } - case .push(let push): - Button(push.title) { - Text("push") - } - case .single(let bookView): - if let tree = bookView?.asTree() { - BookTreeWrapper(tree: tree) - } - case .spacer(let spacer): - Spacer(minLength: 0) - .frame(height: spacer.height) - case .viewRepresentable(let representable): - ViewHost(instantiated: representable.makeView()) - } - } - -} - -#if DEBUG - -enum Preview_StorybookDisplayRootView: PreviewProvider { - - static var previews: some View { - - Group { - StorybookDisplayRootView( - book: .init( - title: "Hello", - closure: { - BookText("Hey") - } - ), - targetViewController: UIViewController() - ) - } - - } - -} - -#endif