portico/Sources/Portico/Core/ViewBuilder.swift

67 lines
2.9 KiB
Swift

/// Result builder for composing ``View`` hierarchies.
@resultBuilder public enum ViewBuilder {
/// Wraps a single ``View`` in an ``AnyView``.
public static func buildExpression<V: View>(_ v: V) -> [AnyView] { [AnyView(v)] }
/// Keeps one contribution per source statement while flattening its array.
public static func buildBlock(_ parts: [AnyView]...) -> [AnyView] { parts.flatMap { $0 } }
/// Records the optional branch as one stable conditional slot.
public static func buildOptional(_ part: [AnyView]?) -> [AnyView] {
[AnyView.conditional(.taken(index: part == nil ? nil : 0, content: part ?? []))]
}
/// Records the first branch as one stable conditional slot.
public static func buildEither(first: [AnyView]) -> [AnyView] {
[AnyView.conditional(.taken(index: 0, content: first))]
}
/// Records the second branch as one stable conditional slot.
public static func buildEither(second: [AnyView]) -> [AnyView] {
[AnyView.conditional(.taken(index: 1, content: second))]
}
/// Records loop rows as one positional list slot.
public static func buildArray(_ parts: [[AnyView]]) -> [AnyView] { [AnyView.list(parts)] }
/// Treats availability branches as one positional list slot.
public static func buildLimitedAvailability(_ part: [AnyView]) -> [AnyView] {
[AnyView.list([part])]
}
}
/// Result builder for a slot that must receive exactly one ``View``.
@resultBuilder public enum SingleViewBuilder {
/// Wraps a single ``View`` in an ``AnyView``.
public static func buildExpression<V: View>(_ v: V) -> AnyView { AnyView(v) }
/// Preserves the terminal ``Never`` body witness.
public static func buildExpression(_ content: Never) -> Never { content }
/// Passes through the block's single view.
public static func buildBlock(_ view: AnyView) -> AnyView { view }
/// Preserves a terminal ``Never`` body witness in a block.
public static func buildBlock(_ content: Never) -> Never { content }
/// Records the first branch as a conditional slot.
public static func buildEither(first: AnyView) -> AnyView {
AnyView.conditional(.taken(index: 0, content: [first]))
}
/// Records the second branch as a conditional slot.
public static func buildEither(second: AnyView) -> AnyView {
AnyView.conditional(.taken(index: 1, content: [second]))
}
/// Produces a stable conditional node for an absent or present optional body.
public static func buildOptional(_ part: AnyView?) -> AnyView {
AnyView.conditional(.taken(index: part == nil ? nil : 0, content: part.map { [$0] } ?? []))
}
/// Passes through an availability-guarded branch unchanged.
public static func buildLimitedAvailability(_ part: AnyView) -> AnyView { part }
/// Preserves a terminal ``Never`` body witness in an availability branch.
public static func buildLimitedAvailability(_ content: Never) -> Never { content }
}