Skip to content

Instantly share code, notes, and snippets.

@tatsuz0u
Last active March 22, 2023 13:47
Show Gist options
  • Save tatsuz0u/219afa301f54e0d4722d243c34412185 to your computer and use it in GitHub Desktop.
Save tatsuz0u/219afa301f54e0d4722d243c34412185 to your computer and use it in GitHub Desktop.
//
// DividerGroup.swift
// BitRemote
//
// Created by 荒木辰造 on R 5/03/10.
//
import SwiftUI
struct DividerGroup<Content: View>: View {
var direction = Direction.horizontal
@DividerResultBuilder<Divider> var content: () -> Content
var body: some View {
switch direction {
case .vertical:
VStack(content: content)
case .horizontal:
HStack(content: content)
}
}
}
extension DividerGroup {
enum Direction {
case vertical, horizontal
}
}
extension DividerGroup {
@ViewBuilder
static func spacer(
direction: Direction = .horizontal,
@DividerResultBuilder<Spacer> _ content: () -> Content
) -> some View {
switch direction {
case .vertical:
VStack(content: content)
case .horizontal:
HStack(content: content)
}
}
}
protocol EmptyInitializable { init() }
protocol AppDivider: View, EmptyInitializable {}
extension Divider: AppDivider {}
extension Spacer: AppDivider {
init() { self.init(minLength: nil) }
}
@resultBuilder
struct DividerResultBuilder<Divider: AppDivider> {
static func buildOptional<Content: View>(_ content: Content?) -> Content? { content }
static func buildPartialBlock<Content: View>(first content: Content) -> Content { content }
static func buildPartialBlock<C0: View, C1: View>(accumulated: C0, next: C1) -> TupleView<(C0, Divider, C1)> {
.init((accumulated, Divider(), next))
}
@ViewBuilder
static func buildPartialBlock<C0: View, C1: View>(accumulated: C0, next: C1?) -> some View {
if let next {
TupleView((accumulated, Divider(), next))
} else {
accumulated
}
}
static func buildEither<TrueContent: View, FalseContent: View>(first content: TrueContent)
-> ConditionalContent<TrueContent, FalseContent> { .init(content: .first(content)) }
static func buildEither<TrueContent: View, FalseContent: View>(second content: FalseContent)
-> ConditionalContent<TrueContent, FalseContent> { .init(content: .second(content)) }
}
enum Either<First, Second> {
case first(First), second(Second)
}
struct ConditionalContent<TrueContent: View, FalseContent: View>: View {
let content: Either<TrueContent, FalseContent>
var body: some View {
switch content {
case .first(let first):
first
case .second(let second):
second
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment