168 lines
5.5 KiB
Swift
168 lines
5.5 KiB
Swift
import SwiftUI
|
|
|
|
// MARK: - VBox Control
|
|
|
|
struct VBoxControl: View {
|
|
let schema: ControlSchema
|
|
@ObservedObject var engine: BricksEngine
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: spacing) {
|
|
if let subwidgets = schema.subwidgets {
|
|
SubWidgetsView(subwidgets: subwidgets, engine: engine)
|
|
}
|
|
}
|
|
.padding(padding)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
|
|
.background(backgroundColor)
|
|
.cornerRadius(cornerRadius)
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: cornerRadius)
|
|
.stroke(borderColor, lineWidth: borderWidth)
|
|
)
|
|
.contentShape(Rectangle())
|
|
.onTapGesture {
|
|
Task {
|
|
await engine.triggerEvent(widgetId: schema.effectiveId, event: "click")
|
|
}
|
|
}
|
|
}
|
|
|
|
private var spacing: CGFloat { CGFloat(schema.options.spacing ?? 8) }
|
|
private var padding: CGFloat { parsePadding(schema.options.padding) }
|
|
private var cornerRadius: CGFloat {
|
|
(schema.options.css?.contains("card") ?? false) ? 8 : 0
|
|
}
|
|
private var borderWidth: CGFloat {
|
|
(schema.options.css?.contains("card") ?? false) ? 1 : 0
|
|
}
|
|
private var borderColor: Color {
|
|
(schema.options.css?.contains("card") ?? false) ? Color.secondary.opacity(0.2) : .clear
|
|
}
|
|
private var backgroundColor: Color {
|
|
if let bg = schema.options.bgcolor {
|
|
return Color.fromCSS(bg)
|
|
}
|
|
if schema.options.css?.contains("card") ?? false {
|
|
return Color.secondary.opacity(0.05)
|
|
}
|
|
return .clear
|
|
}
|
|
|
|
private func parsePadding(_ padding: String?) -> CGFloat {
|
|
guard let p = padding else { return 0 }
|
|
if let val = Double(p.replacingOccurrences(of: "px", with: "")) {
|
|
return CGFloat(val)
|
|
}
|
|
return 8
|
|
}
|
|
}
|
|
|
|
// MARK: - HBox Control
|
|
|
|
struct HBoxControl: View {
|
|
let schema: ControlSchema
|
|
@ObservedObject var engine: BricksEngine
|
|
|
|
var body: some View {
|
|
HStack(alignment: verticalAlignment, spacing: spacing) {
|
|
if let subwidgets = schema.subwidgets {
|
|
SubWidgetsView(subwidgets: subwidgets, engine: engine)
|
|
}
|
|
}
|
|
.padding(padding)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
|
|
.background(backgroundColor)
|
|
.cornerRadius(8)
|
|
}
|
|
|
|
private var spacing: CGFloat { CGFloat(schema.options.spacing ?? 8) }
|
|
private var padding: CGFloat { parsePadding(schema.options.padding) }
|
|
private var verticalAlignment: VerticalAlignment {
|
|
switch schema.options.alignItems {
|
|
case "center": return .center
|
|
case "flex-end", "end": return .bottom
|
|
default: return .top
|
|
}
|
|
}
|
|
private var backgroundColor: Color {
|
|
if let bg = schema.options.bgcolor { return Color.fromCSS(bg) }
|
|
return .clear
|
|
}
|
|
|
|
private func parsePadding(_ padding: String?) -> CGFloat {
|
|
guard let p = padding else { return 0 }
|
|
if let val = Double(p.replacingOccurrences(of: "px", with: "")) { return CGFloat(val) }
|
|
return 8
|
|
}
|
|
}
|
|
|
|
// MARK: - ScrollPanel Control
|
|
|
|
struct ScrollPanelControl: View {
|
|
let schema: ControlSchema
|
|
@ObservedObject var engine: BricksEngine
|
|
|
|
var body: some View {
|
|
if schema.widgettype == "HScrollPanel" {
|
|
ScrollView(.horizontal, showsIndicators: true) {
|
|
HStack(alignment: .top, spacing: spacing) {
|
|
if let subwidgets = schema.subwidgets {
|
|
SubWidgetsView(subwidgets: subwidgets, engine: engine)
|
|
}
|
|
}
|
|
.padding(padding)
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
} else {
|
|
ScrollView(.vertical, showsIndicators: true) {
|
|
VStack(alignment: .leading, spacing: spacing) {
|
|
if let subwidgets = schema.subwidgets {
|
|
SubWidgetsView(subwidgets: subwidgets, engine: engine)
|
|
}
|
|
}
|
|
.padding(padding)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
}
|
|
}
|
|
|
|
private var spacing: CGFloat { CGFloat(schema.options.spacing ?? 8) }
|
|
private var padding: CGFloat {
|
|
if let p = schema.options.padding, let val = Double(p.replacingOccurrences(of: "px", with: "")) {
|
|
return CGFloat(val)
|
|
}
|
|
return 8
|
|
}
|
|
}
|
|
|
|
// MARK: - DynamicColumn Control
|
|
|
|
struct DynamicColumnControl: View {
|
|
let schema: ControlSchema
|
|
@ObservedObject var engine: BricksEngine
|
|
|
|
private let columns = [GridItem(.adaptive(minimum: 200), spacing: 12)]
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
LazyVGrid(columns: resolvedColumns, spacing: gap) {
|
|
if let subwidgets = schema.subwidgets {
|
|
ForEach(Array(subwidgets.enumerated()), id: \.offset) { _, sub in
|
|
ControlRenderer(schema: sub, engine: engine)
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
}
|
|
}
|
|
.padding(8)
|
|
}
|
|
}
|
|
|
|
private var gap: CGFloat { CGFloat(schema.options.col_cgap ?? 1) * 12 }
|
|
private var resolvedColumns: [GridItem] {
|
|
let minWidth = CGFloat(schema.options.col_cwidth ?? 20) * 8
|
|
return [GridItem(.adaptive(minimum: minWidth), spacing: gap)]
|
|
}
|
|
}
|