mirror of
https://github.com/phranck/TUIkit.git
synced 2026-05-21 09:50:35 +00:00
db8ea40c0a
- Fix 80 SwiftLint warnings (159 -> 79): vertical_whitespace, prefer_self_in_static_references, modifier_order, trailing_newline, trailing_whitespace, prefer_for_where, unneeded_synthesized_initializer, redundant_type_annotation, implicit_optional_initialization, superfluous_disable_command, shorthand_optional_binding, syntactic_sugar, empty_string, vertical_whitespace_closing_braces, identifier_name in BadgeModifier - Refactor StatusBar from direct Renderable to _StatusBarCore pattern (public View with real body wrapping private Renderable core)
162 lines
4.4 KiB
Swift
162 lines
4.4 KiB
Swift
// 🖥️ TUIKit — Terminal UI Kit for Swift
|
||
// PrimitiveViews.swift
|
||
//
|
||
// Created by LAYERED.work
|
||
// License: MIT
|
||
|
||
import TUIkitCore
|
||
// MARK: - EmptyView
|
||
|
||
/// A view that displays no content.
|
||
///
|
||
/// `EmptyView` is useful for placeholders or when a view
|
||
/// should display nothing under certain conditions.
|
||
///
|
||
/// ```swift
|
||
/// if showContent {
|
||
/// Text("Content")
|
||
/// } else {
|
||
/// EmptyView()
|
||
/// }
|
||
/// ```
|
||
public struct EmptyView: View, Equatable {
|
||
/// Creates an empty view.
|
||
public init() {}
|
||
|
||
public var body: Never {
|
||
fatalError("EmptyView has no body")
|
||
}
|
||
}
|
||
|
||
// MARK: - ConditionalView
|
||
|
||
/// A view that represents either the true or false branch of a conditional.
|
||
///
|
||
/// This type is used internally by `ViewBuilder` for if-else statements.
|
||
///
|
||
/// - Important: This is framework infrastructure. Created automatically by
|
||
/// `@ViewBuilder` for `if`/`else` branches. Do not instantiate directly.
|
||
public enum ConditionalView<TrueContent: View, FalseContent: View>: View {
|
||
/// The true branch was executed.
|
||
case trueContent(TrueContent)
|
||
|
||
/// The false branch was executed.
|
||
case falseContent(FalseContent)
|
||
|
||
public var body: Never {
|
||
fatalError("ConditionalView renders its children directly")
|
||
}
|
||
}
|
||
|
||
// MARK: - ViewArray
|
||
|
||
/// A view that contains an array of identical views.
|
||
///
|
||
/// This type is used internally by `ViewBuilder` for for-in loops.
|
||
///
|
||
/// ```swift
|
||
/// ForEach(items) { item in
|
||
/// Text(item.name)
|
||
/// }
|
||
/// ```
|
||
///
|
||
/// - Important: This is framework infrastructure. Created automatically by
|
||
/// `@ViewBuilder` for array content. Do not instantiate directly.
|
||
public struct ViewArray<Element: View>: View {
|
||
/// The contained views.
|
||
let elements: [Element]
|
||
|
||
/// Creates a ViewArray from an array of views.
|
||
///
|
||
/// - Parameter elements: The views this container holds.
|
||
public init(_ elements: [Element]) {
|
||
self.elements = elements
|
||
}
|
||
|
||
public var body: Never {
|
||
fatalError("ViewArray renders its children directly")
|
||
}
|
||
}
|
||
|
||
// MARK: - AnyView
|
||
|
||
/// A type-erased view for conditional returns.
|
||
///
|
||
/// Use `AnyView` when you need to return different view types
|
||
/// from a conditional expression.
|
||
///
|
||
/// ```swift
|
||
/// func content(showDetail: Bool) -> AnyView {
|
||
/// if showDetail {
|
||
/// return AnyView(DetailView())
|
||
/// } else {
|
||
/// return AnyView(SummaryView())
|
||
/// }
|
||
/// }
|
||
/// ```
|
||
public struct AnyView: View {
|
||
private let _render: (RenderContext) -> FrameBuffer
|
||
|
||
/// Creates an AnyView wrapping the given view.
|
||
///
|
||
/// - Parameter view: The view to type-erase.
|
||
public init<V: View>(_ view: V) {
|
||
self._render = { context in
|
||
TUIkitView.renderToBuffer(view, context: context)
|
||
}
|
||
}
|
||
|
||
public var body: Never {
|
||
fatalError("AnyView renders via Renderable")
|
||
}
|
||
}
|
||
|
||
// MARK: - AnyView Rendering
|
||
|
||
extension AnyView: Renderable {
|
||
public func renderToBuffer(context: RenderContext) -> FrameBuffer {
|
||
_render(context)
|
||
}
|
||
}
|
||
|
||
// MARK: - EmptyView Rendering
|
||
|
||
extension EmptyView: Renderable {
|
||
public func renderToBuffer(context: RenderContext) -> FrameBuffer {
|
||
FrameBuffer()
|
||
}
|
||
}
|
||
|
||
// MARK: - ConditionalView Rendering
|
||
|
||
extension ConditionalView: Renderable {
|
||
public func renderToBuffer(context: RenderContext) -> FrameBuffer {
|
||
let stateStorage = context.environment.stateStorage!
|
||
switch self {
|
||
case .trueContent(let content):
|
||
stateStorage.invalidateDescendants(of: context.identity.branch("false"))
|
||
return TUIkitView.renderToBuffer(content, context: context.withBranchIdentity("true"))
|
||
case .falseContent(let content):
|
||
stateStorage.invalidateDescendants(of: context.identity.branch("true"))
|
||
return TUIkitView.renderToBuffer(content, context: context.withBranchIdentity("false"))
|
||
}
|
||
}
|
||
}
|
||
|
||
// MARK: - ViewArray Rendering
|
||
|
||
extension ViewArray: Renderable, ChildInfoProvider {
|
||
public func renderToBuffer(context: RenderContext) -> FrameBuffer {
|
||
FrameBuffer(verticallyStacking: childInfos(context: context).compactMap(\.buffer))
|
||
}
|
||
|
||
public func childInfos(context: RenderContext) -> [ChildInfo] {
|
||
elements.enumerated().map { index, element in
|
||
makeChildInfo(
|
||
for: element,
|
||
context: context.withChildIdentity(type: type(of: element), index: index)
|
||
)
|
||
}
|
||
}
|
||
}
|