Merge branch 'dev'
This commit is contained in:
commit
21404ec578
|
@ -3,3 +3,4 @@
|
||||||
/Packages
|
/Packages
|
||||||
/*.xcodeproj
|
/*.xcodeproj
|
||||||
xcuserdata/
|
xcuserdata/
|
||||||
|
.swiftpm/xcode
|
||||||
|
|
|
@ -5,6 +5,9 @@ import PackageDescription
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "UIPreview",
|
name: "UIPreview",
|
||||||
|
platforms: [
|
||||||
|
.iOS(.v13)
|
||||||
|
],
|
||||||
products: [
|
products: [
|
||||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||||
.library(
|
.library(
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
@available(iOS 13, *)
|
@available(iOS 13, *)
|
||||||
extension Binding {
|
extension Binding {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
struct CatalogPage<Content: UIViewCatalogPresentable>: View {
|
||||||
|
|
||||||
|
let schemes: [ColorScheme]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
ScrollView(.vertical, showsIndicators: true) {
|
||||||
|
ForEach(values: Content.previewModels) { model in
|
||||||
|
ForEach(values: schemes) { scheme in
|
||||||
|
item(title: "\(scheme): \(model)") {
|
||||||
|
ColorSchemePreview(scheme: scheme) {
|
||||||
|
Content.preview(with: model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.navigationBarTitle(String(describing: Content.self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func item<Content: View>(title: String,
|
||||||
|
@ViewBuilder content: @escaping () -> Content
|
||||||
|
) -> some View {
|
||||||
|
VStack(alignment: .center, spacing: 12.0) {
|
||||||
|
Text(title)
|
||||||
|
.font(.subheadline)
|
||||||
|
.fontWeight(.bold)
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
struct CatalogPage_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
CatalogPage<UISwitch>(schemes: [.light, .dark, ])
|
||||||
|
CatalogPage<UILabel>(schemes: [.light, .dark, ])
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,30 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
@available(iOS 13, *)
|
extension UISwitch: UICatalogPresentable {
|
||||||
struct ContentView: View {
|
public static var previewModels = [true, false]
|
||||||
var body: some View {
|
|
||||||
Text("Hello, world!")
|
public func apply(previewModel: Bool) {
|
||||||
.background(Color(.red)).padding()
|
isOn = previewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 13, *)
|
extension UILabel: UICatalogPresentable {
|
||||||
struct ContentView_Previews: PreviewProvider {
|
public static var previewModels: [String] {
|
||||||
static var previews: some View {
|
["123", "345", "Hello world", "How do you do"]
|
||||||
ContentView()
|
}
|
||||||
.previewDarkTheme()
|
|
||||||
|
public func apply(previewModel: String) {
|
||||||
|
text = previewModel
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makePreviewInstance() -> Self {
|
||||||
|
let label = UILabel()
|
||||||
|
label.adjustsFontForContentSizeCategory = true
|
||||||
|
label.font = UIFont.preferredFont(forTextStyle: .caption1)
|
||||||
|
return label as! Self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 13, *)
|
|
||||||
struct Demo_Previews: PreviewProvider {
|
|
||||||
static var previews: some View {
|
|
||||||
Group {
|
|
||||||
UIViewPreview(UIView())
|
|
||||||
.frame(width: 100, height: 30)
|
|
||||||
.background(Color(.red))
|
|
||||||
.previewLayout(.sizeThatFits)
|
|
||||||
UIViewPreview(UILabel(), update: {
|
|
||||||
$0.text = "Hello"
|
|
||||||
$0.font = UIFont.preferredFont(forTextStyle: .caption1)
|
|
||||||
$0.adjustsFontForContentSizeCategory = true
|
|
||||||
}).previewAsComponent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
|
||||||
@available(iOS 13, *)
|
@available(iOS 13, *)
|
||||||
extension ForEach where Data.Element: Hashable, ID == Data.Element, Content: View {
|
extension ForEach where Data.Element: Hashable, ID == Data.Element, Content: View {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
|
||||||
@available(iOS 13, *)
|
@available(iOS 13, *)
|
||||||
extension View {
|
extension View {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
|
||||||
@available(iOS 13, *)
|
@available(iOS 13, *)
|
||||||
extension View {
|
extension View {
|
||||||
|
@ -24,7 +26,7 @@ struct ComponentPreview<Component: View>: View {
|
||||||
ForEach(values: ColorScheme.allCases) { scheme in
|
ForEach(values: ColorScheme.allCases) { scheme in
|
||||||
ForEach(values: ContentSizeCategory.smallestAndLargest) { category in
|
ForEach(values: ContentSizeCategory.smallestAndLargest) { category in
|
||||||
self.component
|
self.component
|
||||||
.previewLayout(.sizeThatFits)
|
.previewLayout(.sizeThatFits).padding()
|
||||||
.background(Color(.systemBackground))
|
.background(Color(.systemBackground))
|
||||||
.colorScheme(scheme)
|
.colorScheme(scheme)
|
||||||
.environment(\.sizeCategory, category)
|
.environment(\.sizeCategory, category)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
|
||||||
//xcrun simctl list devicetypes
|
//xcrun simctl list devicetypes
|
||||||
public let defaultDeviceNames: [String] =
|
public let defaultDeviceNames: [String] =
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
public enum UICatalog {
|
||||||
|
public enum Theme {
|
||||||
|
case light, dark
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makePreviewPage<Content>(_ content: Content.Type,
|
||||||
|
themes: [Theme] = [.light, .dark]
|
||||||
|
) -> UIViewController where Content: UIViewCatalogPresentable {
|
||||||
|
guard #available(iOS 13, *) else {
|
||||||
|
return UIViewController()
|
||||||
|
}
|
||||||
|
return CatalogPage<Content>(schemes: themes.map(\.scheme)).asViewController()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
extension UICatalog.Theme {
|
||||||
|
var scheme: ColorScheme {
|
||||||
|
switch self {
|
||||||
|
case .light: return .light
|
||||||
|
case .dark: return .dark
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
public protocol UICatalogPresentable {
|
||||||
|
associatedtype PreviewModel: Hashable
|
||||||
|
|
||||||
|
func apply(previewModel: PreviewModel)
|
||||||
|
|
||||||
|
static var previewModels: [PreviewModel] { get }
|
||||||
|
|
||||||
|
static func makePreviewInstance() -> Self
|
||||||
|
}
|
||||||
|
|
||||||
|
public typealias UIViewCatalogPresentable = UIView & UICatalogPresentable
|
||||||
|
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
extension UICatalogPresentable where Self: UIView {
|
||||||
|
public func preview(with model: PreviewModel) -> some View {
|
||||||
|
UIViewPreview(self) { $0.apply(previewModel: model) }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func preview(with model: PreviewModel) -> some View {
|
||||||
|
makePreviewInstance().preview(with: model)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func makePreviewInstance() -> Self { self.init() }
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
public struct UIViewControllerPreview<ContentView: UIViewController>: UIViewControllerRepresentable {
|
public struct UIViewControllerPreview<ContentView: UIViewController>: UIViewControllerRepresentable {
|
||||||
let contextBuilder: () -> ViewCoordinator<ContentView>
|
let contextBuilder: () -> ViewCoordinator<ContentView>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
#endif
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
public struct UIViewPreview<ContentView: UIView>: UIViewRepresentable {
|
public struct UIViewPreview<ContentView: UIView>: UIViewRepresentable {
|
||||||
let contextBuilder: () -> ViewCoordinator<ContentView>
|
let contextBuilder: () -> ViewCoordinator<ContentView>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#if canImport(SwiftUI)
|
||||||
|
import SwiftUI
|
||||||
|
#endif
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
extension View {
|
||||||
|
public func asViewController() -> UIViewController {
|
||||||
|
UIHostingController(rootView: self)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue