Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions Sources/BuilderIO/Components/BuilderBlock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,35 +57,65 @@ struct BuilderBlockLayout<Content: View>: View {
let minHeight = extractPixels(responsiveStyles["minHeight"])
let maxHeight = extractPixels(responsiveStyles["maxHeight"])
let minWidth = extractPixels(responsiveStyles["minWidth"])
let maxWidth = extractPixels(responsiveStyles["maxWidth"])
let maxWidth = extractPixels(responsiveStyles["maxWidth"]) ?? .infinity

let borderRadius = extractPixels(responsiveStyles["borderRadius"]) ?? 0

// 2. Build base layout (wrapped or not)
let layoutView: some View = Group {
if wrap {
LazyVGrid(
columns: [GridItem(.adaptive(minimum: 100), spacing: spacing)],
columns: [
GridItem(.flexible(minimum: minWidth ?? 0, maximum: maxWidth), spacing: spacing)
],
alignment: BuilderBlockLayout<Content>.horizontalAlignment(
marginsLeft: marginLeft, marginsRight: marginRight, justify: justify,
alignItems: alignItems),
spacing: spacing,
content: content
)
} else if direction == "row" {
let hStackAlignment = BuilderBlockLayout<Content>.verticalAlignment(
justify: justify, alignItems: alignItems)

let frameAlignment: Alignment =
switch hStackAlignment {
case .top: .top
case .center: .center
case .bottom: .bottom
default: .center
}

HStack(
alignment: BuilderBlockLayout<Content>.verticalAlignment(
justify: justify, alignItems: alignItems), spacing: spacing
alignment: hStackAlignment, spacing: spacing
) {
content()
content().padding(padding)
.frame(
minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight,
alignment: frameAlignment)
}
} else {

let vStackAlignment = BuilderBlockLayout<Content>.horizontalAlignment(
marginsLeft: marginLeft, marginsRight: marginRight, justify: justify,
alignItems: alignItems)

let frameAlignment: Alignment =
switch vStackAlignment {
case .leading: .leading
case .center: .center
case .trailing: .trailing
default: .center
}

VStack(
alignment: BuilderBlockLayout<Content>.horizontalAlignment(
marginsLeft: marginLeft, marginsRight: marginRight, justify: justify,
alignItems: alignItems), spacing: spacing
alignment: vStackAlignment, spacing: spacing
) {
content()

content().padding(padding)
.frame(
minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight,
alignment: frameAlignment)
}
}
}
Expand All @@ -104,8 +134,6 @@ struct BuilderBlockLayout<Content: View>: View {
// 4. Apply visual and layout modifiers
return
scrollableView
.padding(padding)
.frame(minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight)
.padding(margin) //margin
.cornerRadius(borderRadius)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ struct BuilderEmptyView: BuilderViewProtocol {
struct ResponsiveStylesBuilderView: ViewModifier {

var responsiveStyles: [String: String]
let horizontalAlignmentFrame: FrameDimensions
//let horizontalAlignmentFrame: FrameDimensions
let foregroundColor: Color?
let cornerRadius: CGFloat?
let fontSize: CGFloat?
Expand All @@ -50,17 +50,10 @@ struct ResponsiveStylesBuilderView: ViewModifier {
CSSStyleUtil.getFontWeightFromNumber(value: CSSStyleUtil.getFloatValue(cssString: fontWeight))
}

horizontalAlignmentFrame = CSSStyleUtil.getFrameFromHorizontalAlignment(
styles: responsiveStyles ?? [:], isText: true)
}

func body(content: Content) -> some View {
content
.frame(
idealWidth: horizontalAlignmentFrame.idealWidth,
maxWidth: horizontalAlignmentFrame.maxWidth, alignment: horizontalAlignmentFrame.alignment
)

}

}
Expand Down
28 changes: 26 additions & 2 deletions Sources/BuilderIO/Components/BuilderImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,40 @@ struct BuilderImage: BuilderViewProtocol {

var block: BuilderBlockModel
var responsiveStyles: [String: String]?
var aspectRatio: CGSize?

var imageURL: URL?

init(block: BuilderBlockModel) {
self.block = block
self.responsiveStyles = getFinalStyle(responsiveStyles: block.responsiveStyles)
self.imageURL = URL(string: block.component?.options?["image"].string ?? "")

if let ratio = block.component?.options?["aspectRatio"].doubleValue {
self.aspectRatio = CGSize(width: ratio, height: 1)
} else {
self.aspectRatio = nil
}

}

var body: some View {
AsyncImage(url: imageURL).frame(width: 5, height: 5)
}
AsyncImage(url: imageURL) { phase in
switch phase {
case .empty:
ProgressView()
case .success(let image):
image
.resizable()
.if(aspectRatio != nil) { view in
view.aspectRatio(self.aspectRatio!, contentMode: .fit)
}
case .failure:
Color.gray
@unknown default:
EmptyView()
}
}.responsiveStylesBuilderView(responsiveStyles: self.responsiveStyles ?? [:], isText: false)

}
}
58 changes: 57 additions & 1 deletion Sources/BuilderIO/Components/BuilderText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,63 @@ struct BuilderText: BuilderViewProtocol {
}

var body: some View {
Text(CSSStyleUtil.getTextWithoutHtml(text ?? ""))

Text(CSSStyleUtil.getTextWithoutHtml(text ?? "")).responsiveStylesBuilderView(
responsiveStyles: self.responsiveStyles ?? [:], isText: true)

}

}

struct BuilderText_Previews: PreviewProvider {
static let builderJSONString = """
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-ad756879bc6c4ee3ac7977d5af0b6811",
"meta": {
"previousId": "builder-e8da4929479a4abf9cd8e3959a1e6699"
},
"component": {
"name": "Text",
"options": {
"text": "<h1>Left Align Text</h1>"
}
},
"responsiveStyles": {
"large": {
"display": "flex",
"flexDirection": "column",
"position": "relative",
"flexShrink": "0",
"boxSizing": "border-box",
"marginTop": "20px",
"lineHeight": "normal",
"height": "auto",
"marginRight": "auto",
"paddingLeft": "20px",
"paddingRight": "20px"
}
}
}
"""

static func decodeBuilderBlockModel(from jsonString: String) -> BuilderBlockModel? {
let data = Data(jsonString.utf8)
do {
let decoder = JSONDecoder()
return try decoder.decode(BuilderBlockModel.self, from: data)
} catch {
print("Decoding failed:", error)
return nil
}
}

static var previews: some View {
if let block = decodeBuilderBlockModel(from: builderJSONString) {
BuilderText(block: block)
} else {
Text("Failed to decode block")
}
}
}