Add _NavigationLinkStyle for sidebar lists

This commit is contained in:
Carson Katri 2020-08-03 18:09:40 -04:00
parent 4b05fd8523
commit cb6359431d
5 changed files with 82 additions and 17 deletions

View File

@ -79,8 +79,49 @@ public extension ForEach where Data == Range<Int>, ID == Int {
extension ForEach: ParentView {
public var children: [AnyView] {
data.map { AnyView(content($0)) }
data.map { AnyView(IDView(content($0), id: $0[keyPath: id])) }
}
}
extension ForEach: GroupView {}
struct _IDKey: EnvironmentKey {
static let defaultValue: AnyHashable? = nil
}
extension EnvironmentValues {
public var _id: AnyHashable? {
get {
self[_IDKey.self]
}
set {
self[_IDKey.self] = newValue
}
}
}
public protocol _AnyIDView {
var anyId: AnyHashable { get }
}
struct IDView<Content, ID>: View, _AnyIDView where Content: View, ID: Hashable {
let content: Content
let id: ID
var anyId: AnyHashable { AnyHashable(id) }
init(_ content: Content, id: ID) {
self.content = content
self.id = id
}
var body: some View {
content
.environment(\._id, AnyHashable(id))
}
}
extension View {
public func id<ID>(_ id: ID) -> some View where ID: Hashable {
IDView(self, id: id)
}
}

View File

@ -15,15 +15,24 @@
// Created by Jed Fox on 06/30/2020.
//
import OpenCombine
final class NavigationLinkDestination {
let view: AnyView
init<V: View>(_ destination: V) {
view = AnyView(destination)
}
}
public struct NavigationLink<Label, Destination>: View where Label: View, Destination: View {
let destination: Destination
@State var destination: NavigationLinkDestination
let label: Label
@Environment(\.navigationDestination) var navigationContext
@EnvironmentObject var navigationContext: NavigationContext
@Environment(\._navigationLinkStyle) var style
public init(destination: Destination, @ViewBuilder label: () -> Label) {
self.destination = destination
_destination = State(wrappedValue: NavigationLinkDestination(destination))
self.label = label()
}
@ -69,7 +78,9 @@ extension NavigationLink where Label == Text {
public struct _NavigationLinkProxy<Label, Destination> where Label: View, Destination: View {
public let subject: NavigationLink<Label, Destination>
public init(_ subject: NavigationLink<Label, Destination>) { self.subject = subject }
public init(_ subject: NavigationLink<Label, Destination>) {
self.subject = subject
}
public var label: AnyView {
subject.style.makeBody(configuration: .init(body: AnyView(subject.label),
@ -78,10 +89,10 @@ public struct _NavigationLinkProxy<Label, Destination> where Label: View, Destin
public var style: _AnyNavigationLinkStyle { subject.style }
public var isSelected: Bool {
true
ObjectIdentifier(subject.destination) == ObjectIdentifier(subject.navigationContext.destination)
}
public func activate() {
subject.navigationContext!.wrappedValue = AnyView(subject.destination)
subject.navigationContext.destination = subject.destination
}
}

View File

@ -15,10 +15,14 @@
// Created by Jed Fox on 06/30/2020.
//
final class NavigationContext: ObservableObject {
@Published var destination = NavigationLinkDestination(EmptyView())
}
public struct NavigationView<Content>: View where Content: View {
let content: Content
@State var destination = AnyView(EmptyView())
@ObservedObject var context = NavigationContext()
public init(@ViewBuilder content: () -> Content) {
self.content = content()
@ -39,8 +43,9 @@ public struct _NavigationViewProxy<Content: View>: View {
public var body: some View {
HStack {
content
subject.destination
}.environment(\.navigationDestination, subject.$destination)
subject.context.destination.view
}
.environmentObject(subject.context)
}
}

View File

@ -15,11 +15,17 @@
import TokamakCore
private extension DOMViewModifier {
func unwrapToStyle<T>(_ key: KeyPath<Self, T?>, property: String) -> String {
func unwrapToStyle<T>(_ key: KeyPath<Self, T?>,
property: String? = nil,
defaultValue: String = "") -> String {
if let val = self[keyPath: key] {
return "\(property): \(val)px;"
if let property = property {
return "\(property): \(val)px;"
} else {
return "\(val)px;"
}
} else {
return ""
return defaultValue
}
}
}
@ -40,12 +46,14 @@ extension _FrameLayout: DOMViewModifier {
extension _FlexFrameLayout: DOMViewModifier {
public var attributes: [String: String] {
["style": """
let flexibleWidth = minWidth == 0 && maxWidth == .infinity
let flexibleHeight = minHeight == 0 && maxHeight == .infinity
return ["style": """
\(unwrapToStyle(\.minWidth, property: "min-width"))
\(unwrapToStyle(\.idealWidth, property: "width"))
width: \(unwrapToStyle(\.idealWidth, defaultValue: flexibleWidth ? "100%" : "auto"));
\(unwrapToStyle(\.maxWidth, property: "max-width"))
\(unwrapToStyle(\.minHeight, property: "min-height"))
\(unwrapToStyle(\.idealHeight, property: "height"))
height: \(unwrapToStyle(\.idealHeight, defaultValue: flexibleHeight ? "100%" : "auto"));
\(unwrapToStyle(\.maxHeight, property: "max-height"))
overflow: hidden;
text-overflow: ellipsis;

View File

@ -91,7 +91,7 @@ extension InsetGroupedListStyle: ListStyleDeferredToRenderer {
extension SidebarListStyle: ListStyleDeferredToRenderer {
public func listRow<Row>(_ row: Row) -> AnyView where Row: View {
AnyView(row)
AnyView(row.frame(minWidth: 0, maxWidth: .infinity))
}
public func listBody<ListBody>(_ content: ListBody) -> AnyView where ListBody: View {