diff --git a/Sources/SkeletonUI/Enumerations/ShapeType.swift b/Sources/SkeletonUI/Enumerations/ShapeType.swift index 9c9c567..43928d6 100644 --- a/Sources/SkeletonUI/Enumerations/ShapeType.swift +++ b/Sources/SkeletonUI/Enumerations/ShapeType.swift @@ -3,6 +3,10 @@ import SwiftUI public enum RoundedType: Equatable { case radius(CGFloat, style: RoundedCornerStyle = .continuous) case size(CGSize, style: RoundedCornerStyle = .continuous) + case corners(topLeadingRadius: CGFloat, + bottomLeadingRadius: CGFloat, + bottomTrailingRadius: CGFloat, + topTrailingRadius: CGFloat) } public enum ShapeType: Equatable { @@ -18,6 +22,18 @@ public enum ShapeType: Equatable { return RoundedRectangle(cornerRadius: radius, style: style) case let .rounded(.size(size, style)): return RoundedRectangle(cornerSize: size, style: style) + case let .rounded(.corners(topLeadingRadius, bottomLeadingRadius, bottomTrailingRadius, topTrailingRadius)): + if #available(iOS 16.0, *) { + return .rect(topLeadingRadius: topLeadingRadius, + bottomLeadingRadius: bottomLeadingRadius, + bottomTrailingRadius: bottomTrailingRadius, + topTrailingRadius: topTrailingRadius) + } else { + return RoundedCorners(topLeadingRadius: topLeadingRadius, + topTrailingRadius: topTrailingRadius, + bottomLeadingRadius: bottomLeadingRadius, + bottomTrailingRadius: bottomTrailingRadius) + } case .rectangle: return Rectangle() case .circle: diff --git a/Sources/SkeletonUI/Extensions/Image+OptionalType.swift b/Sources/SkeletonUI/Extensions/Image+OptionalType.swift index 3b4f4e5..2a503de 100644 --- a/Sources/SkeletonUI/Extensions/Image+OptionalType.swift +++ b/Sources/SkeletonUI/Extensions/Image+OptionalType.swift @@ -1,6 +1,6 @@ import SwiftUI -public extension Image { +extension Image { #if os(iOS) || os(tvOS) || os(watchOS) || os(visionOS) init(uiImage: UIImage?) { if let uiImage = uiImage { diff --git a/Sources/SkeletonUI/Extensions/SecureField+OptionalType.swift b/Sources/SkeletonUI/Extensions/SecureField+OptionalType.swift index ca29b1b..1d0d554 100644 --- a/Sources/SkeletonUI/Extensions/SecureField+OptionalType.swift +++ b/Sources/SkeletonUI/Extensions/SecureField+OptionalType.swift @@ -1,6 +1,6 @@ import SwiftUI -public extension SecureField where Label == Text { +extension SecureField where Label == Text { init(_ titleKey: LocalizedStringKey?, text: Binding, onCommit: @escaping () -> Void = {}) { if let titleKey = titleKey { self.init(titleKey, text: text, onCommit: onCommit) diff --git a/Sources/SkeletonUI/Extensions/Text+OptionalType.swift b/Sources/SkeletonUI/Extensions/Text+OptionalType.swift index 7f12d97..67b894d 100644 --- a/Sources/SkeletonUI/Extensions/Text+OptionalType.swift +++ b/Sources/SkeletonUI/Extensions/Text+OptionalType.swift @@ -1,6 +1,6 @@ import SwiftUI -public extension Text { +extension Text { init(_ content: S?) where S: OptionalType, S.Wrapped: StringProtocol { if let content = content?.wrapped { self.init(content) diff --git a/Sources/SkeletonUI/Extensions/TextField+OptionalType.swift b/Sources/SkeletonUI/Extensions/TextField+OptionalType.swift index 00e945d..ad04c98 100644 --- a/Sources/SkeletonUI/Extensions/TextField+OptionalType.swift +++ b/Sources/SkeletonUI/Extensions/TextField+OptionalType.swift @@ -1,6 +1,6 @@ import SwiftUI -public extension TextField where Label == Text { +extension TextField where Label == Text { init(titleKey: LocalizedStringKey?, text: Binding, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {}) { if let titleKey = titleKey { self.init(titleKey, text: text, onEditingChanged: onEditingChanged, onCommit: onCommit) diff --git a/Sources/SkeletonUI/Extensions/Toggle+OptionalType.swift b/Sources/SkeletonUI/Extensions/Toggle+OptionalType.swift index 78ee3fa..ef74603 100644 --- a/Sources/SkeletonUI/Extensions/Toggle+OptionalType.swift +++ b/Sources/SkeletonUI/Extensions/Toggle+OptionalType.swift @@ -1,6 +1,6 @@ import SwiftUI -public extension Toggle where Label: View { +extension Toggle where Label: View { init(isOn: Binding?, @ViewBuilder label: () -> Label) { if let isOn = isOn { self.init(isOn: isOn, label: label) @@ -10,7 +10,7 @@ public extension Toggle where Label: View { } } -public extension Toggle where Label == Text { +extension Toggle where Label == Text { init(_ titleKey: LocalizedStringKey?, isOn: Binding) { if let titleKey = titleKey { self.init(titleKey, isOn: isOn) diff --git a/Sources/SkeletonUI/Shapes/RoundedCorners.swift b/Sources/SkeletonUI/Shapes/RoundedCorners.swift new file mode 100644 index 0000000..075fbaa --- /dev/null +++ b/Sources/SkeletonUI/Shapes/RoundedCorners.swift @@ -0,0 +1,42 @@ +import SwiftUI +import UIKit + +struct RoundedCorners: Shape { + var topLeadingRadius: CGFloat = 0.0 + var topTrailingRadius: CGFloat = 0.0 + var bottomLeadingRadius: CGFloat = 0.0 + var bottomTrailingRadius: CGFloat = 0.0 + + func path(in rect: CGRect) -> Path { + var path = Path() + + let w = rect.size.width + let h = rect.size.height + + // Make sure we do not exceed the size of the rectangle + let tr = min(min(self.topTrailingRadius, h/2), w/2) + let tl = min(min(self.topLeadingRadius, h/2), w/2) + let bl = min(min(self.bottomLeadingRadius, h/2), w/2) + let br = min(min(self.bottomTrailingRadius, h/2), w/2) + + path.move(to: CGPoint(x: w / 2.0, y: 0)) + path.addLine(to: CGPoint(x: w - tr, y: 0)) + path.addArc(center: CGPoint(x: w - tr, y: tr), radius: tr, + startAngle: Angle(degrees: -90), endAngle: Angle(degrees: 0), clockwise: false) + + path.addLine(to: CGPoint(x: w, y: h - br)) + path.addArc(center: CGPoint(x: w - br, y: h - br), radius: br, + startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 90), clockwise: false) + + path.addLine(to: CGPoint(x: bl, y: h)) + path.addArc(center: CGPoint(x: bl, y: h - bl), radius: bl, + startAngle: Angle(degrees: 90), endAngle: Angle(degrees: 180), clockwise: false) + + path.addLine(to: CGPoint(x: 0, y: tl)) + path.addArc(center: CGPoint(x: tl, y: tl), radius: tl, + startAngle: Angle(degrees: 180), endAngle: Angle(degrees: 270), clockwise: false) + path.closeSubpath() + + return path + } +}