Skip to content

Commit 466e7eb

Browse files
committed
feat(styles): add support for more padding options, initial absolute positionning support
1 parent 19db7bc commit 466e7eb

File tree

2 files changed

+116
-15
lines changed

2 files changed

+116
-15
lines changed

ios/components/StyleProps.swift

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,26 @@ public struct StyleProps: Decodable {
44
// ViewStyle
55
public var backgroundColor: Color?
66
// - Frame
7-
public var width: CGFloat?
8-
public var height: CGFloat?
7+
public var width: Size?
8+
public var minWidth: Size?
9+
public var maxWidth: Size?
10+
public var height: Size?
11+
public var minHeight: Size?
12+
public var maxHeight: Size?
13+
// - Position
14+
public var position: String? // "absolute" or "relative"
15+
public var top: CGFloat?
16+
public var left: CGFloat?
17+
public var bottom: CGFloat?
18+
public var right: CGFloat?
919
// - Padding
1020
public var padding: CGFloat?
1121
public var paddingHorizontal: CGFloat?
1222
public var paddingVertical: CGFloat?
23+
public var paddingLeft: CGFloat?
24+
public var paddingRight: CGFloat?
25+
public var paddingTop: CGFloat?
26+
public var paddingBottom: CGFloat?
1327
// - Border
1428
public var borderColor: Color?
1529
public var borderWidth: CGFloat?
@@ -21,33 +35,51 @@ public struct StyleProps: Decodable {
2135
public var fontWeight: Font.Weight?
2236
public var fontSize: CGFloat?
2337
public var font: Font?
38+
public var fontFamily: String?
2439

2540
enum CodingKeys: String, CodingKey {
26-
case color, backgroundColor, foregroundColor, width, height, padding, paddingHorizontal, paddingVertical, borderColor, borderWidth, borderRadius, cornerRadius, fontWeight, fontSize, font
41+
case color, backgroundColor, foregroundColor, width, minWidth, maxWidth, height, minHeight, maxHeight, position, top, left, bottom, right, padding, paddingHorizontal, paddingVertical, paddingLeft, paddingRight, paddingTop, paddingBottom, borderColor, borderWidth, borderRadius, cornerRadius, fontWeight, fontSize, font, fontFamily
2742
}
2843

2944
public init(from decoder: Decoder) throws {
3045
let container = try decoder.container(keyedBy: CodingKeys.self)
3146

3247
// ViewStyle
3348
backgroundColor = try container.decodeColorIfPresent(forKey: .backgroundColor)
49+
// - Frame
50+
width = try container.decodeIfPresent(Size.self, forKey: .width)
51+
minWidth = try container.decodeIfPresent(Size.self, forKey: .minWidth)
52+
maxWidth = try container.decodeIfPresent(Size.self, forKey: .maxWidth)
53+
height = try container.decodeIfPresent(Size.self, forKey: .height)
54+
minHeight = try container.decodeIfPresent(Size.self, forKey: .minHeight)
55+
maxHeight = try container.decodeIfPresent(Size.self, forKey: .maxHeight)
56+
// - Position
57+
position = try container.decodeIfPresent(String.self, forKey: .position)
58+
top = try container.decodeIfPresent(CGFloat.self, forKey: .top)
59+
left = try container.decodeIfPresent(CGFloat.self, forKey: .left)
60+
bottom = try container.decodeIfPresent(CGFloat.self, forKey: .bottom)
61+
right = try container.decodeIfPresent(CGFloat.self, forKey: .right)
62+
// - Padding
63+
padding = try container.decodeIfPresent(CGFloat.self, forKey: .padding)
64+
paddingHorizontal = try container.decodeIfPresent(CGFloat.self, forKey: .paddingHorizontal)
65+
paddingVertical = try container.decodeIfPresent(CGFloat.self, forKey: .paddingVertical)
66+
paddingLeft = try container.decodeIfPresent(CGFloat.self, forKey: .paddingLeft)
67+
paddingRight = try container.decodeIfPresent(CGFloat.self, forKey: .paddingRight)
68+
paddingTop = try container.decodeIfPresent(CGFloat.self, forKey: .paddingTop)
69+
paddingBottom = try container.decodeIfPresent(CGFloat.self, forKey: .paddingBottom)
70+
// - Border
3471
borderColor = try container.decodeColorIfPresent(forKey: .borderColor)
3572
borderWidth = try container.decodeIfPresent(CGFloat.self, forKey: .borderWidth)
3673
borderRadius = try container.decodeIfPresent(CGFloat.self, forKey: .borderRadius) // alias for cornerRadius
3774
cornerRadius = try container.decodeIfPresent(CGFloat.self, forKey: .cornerRadius)
3875

39-
width = try container.decodeIfPresent(CGFloat.self, forKey: .width)
40-
height = try container.decodeIfPresent(CGFloat.self, forKey: .height)
41-
padding = try container.decodeIfPresent(CGFloat.self, forKey: .padding)
42-
paddingHorizontal = try container.decodeIfPresent(CGFloat.self, forKey: .paddingHorizontal)
43-
paddingVertical = try container.decodeIfPresent(CGFloat.self, forKey: .paddingVertical)
44-
4576
// TextStyle
4677
color = try container.decodeColorIfPresent(forKey: .color) // alias for foregroundColor
4778
foregroundColor = try container.decodeColorIfPresent(forKey: .foregroundColor)
4879
fontWeight = try container.decodeFontWeightIfPresent(forKey: .fontWeight)
4980
fontSize = try container.decodeIfPresent(CGFloat.self, forKey: .fontSize)
5081
font = try container.decodeFontIfPresent(forKey: .font)
82+
fontFamily = try container.decodeIfPresent(String.self, forKey: .fontFamily)
5183
}
5284
}
5385

ios/extensions/View+Styling.swift

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,68 @@ extension View {
99
)
1010
}
1111

12-
func applyBoxStyles(_ style: StyleProps?) -> some View {
12+
func applyFrameStyles(_ style: StyleProps?) -> some View {
1313
guard let style = style else { return AnyView(self) }
14-
return AnyView(
15-
applyIf(style.width != nil || style.height != nil) { $0.frame(width: style.width, height: style.height)
14+
15+
let needsGeometry = [style.width, style.minWidth, style.maxWidth, style.height, style.minHeight, style.maxHeight].contains { size in
16+
if case let .percentage(fraction) = size {
17+
return fraction != 1.0
1618
}
19+
return false
20+
}
21+
22+
if needsGeometry {
23+
return AnyView(
24+
GeometryReader { geometry in
25+
let width = style.width?.calculate(from: geometry.size.width)
26+
let minWidth = style.minWidth?.calculate(from: geometry.size.width)
27+
let maxWidth = style.maxWidth?.calculate(from: geometry.size.width)
28+
let height = style.height?.calculate(from: geometry.size.height)
29+
let minHeight = style.minHeight?.calculate(from: geometry.size.height)
30+
let maxHeight = style.maxHeight?.calculate(from: geometry.size.height)
31+
32+
self.frame(
33+
minWidth: minWidth,
34+
idealWidth: width,
35+
maxWidth: maxWidth,
36+
minHeight: minHeight,
37+
idealHeight: height,
38+
maxHeight: maxHeight
39+
)
40+
}
41+
)
42+
} else {
43+
let params = computeFrameParameters(from: style)
44+
45+
if params.maxHeight == nil && params.maxWidth == nil && params.minWidth == nil && params.minHeight == nil {
46+
return AnyView(frame(width: params.width, height: params.height))
47+
}
48+
49+
return AnyView(
50+
frame(
51+
minWidth: params.minWidth,
52+
idealWidth: params.width,
53+
maxWidth: params.maxWidth,
54+
minHeight: params.minHeight,
55+
idealHeight: params.height,
56+
maxHeight: params.maxHeight
57+
)
58+
)
59+
}
60+
}
61+
62+
func applyBoxStyles(_ style: StyleProps?) -> some View {
63+
guard let style = style else { return AnyView(self) }
64+
65+
return AnyView(applyFrameStyles(style)
66+
.modifier(AbsolutePositionModifier(style: style))
1767
.applyIf(style.padding != nil) { $0.padding(style.padding!) }
1868
.applyIf(style.paddingHorizontal != nil) { $0.padding(.horizontal, style.paddingHorizontal!) }
19-
.applyIf(style.paddingVertical != nil) { $0.padding(.vertical, style.paddingVertical!) }
20-
)
69+
.applyIf(style.paddingVertical != nil) { $0.padding(.vertical, style.paddingVertical!) })
70+
.applyIf(style.paddingLeft != nil) { $0.padding(.leading, style.paddingLeft!) }
71+
.applyIf(style.paddingRight != nil) { $0.padding(.trailing, style.paddingRight!) }
72+
.applyIf(style.paddingTop != nil) { $0.padding(.top, style.paddingTop!) }
73+
.applyIf(style.paddingBottom != nil) { $0.padding(.bottom, style.paddingBottom!) }
2174
}
2275

2376
func applyViewStyles(_ style: StyleProps?) -> some View {
@@ -41,7 +94,8 @@ extension View {
4194
private func applyTextStyles(_ style: StyleProps) -> some View {
4295
return applyIf(style.color != nil) { $0.foregroundStyle(style.color!) }
4396
.applyIf(style.font != nil) { $0.font(style.font!) }
44-
.applyIf(style.fontSize != nil) { $0.font(.system(size: style.fontSize!)) }
97+
.applyIf(style.fontFamily != nil) { $0.font(.custom(style.fontFamily!, size: style.fontSize ?? 17)) }
98+
.applyIf(style.fontFamily == nil && style.fontSize != nil) { $0.font(.system(size: style.fontSize!)) }
4599
.applyIf(style.fontWeight != nil) { view in
46100
if #available(iOS 16.0, *) {
47101
return AnyView(view.fontWeight(style.fontWeight!))
@@ -69,3 +123,18 @@ extension Shape {
69123
.applyBoxStyles(style))
70124
}
71125
}
126+
127+
struct AbsolutePositionModifier: ViewModifier {
128+
let style: StyleProps
129+
func body(content: Content) -> some View {
130+
if style.position == "absolute" {
131+
// Use .position() for absolute positioning relative to parent
132+
content.position(
133+
x: (style.left ?? 0) + (style.right != nil ? UIScreen.main.bounds.width - (style.right ?? 0) : 0),
134+
y: (style.top ?? 0) + (style.bottom != nil ? UIScreen.main.bounds.height - (style.bottom ?? 0) : 0)
135+
)
136+
} else {
137+
content // Default to relative positioning
138+
}
139+
}
140+
}

0 commit comments

Comments
 (0)