-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Part of #51.
- Loading branch information
Showing
10 changed files
with
234 additions
and
16 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
Sources/Slipstream/Documentation.docc/Views/TailwindCSS/Padding.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Padding | ||
|
||
## Topics | ||
|
||
### Modifiers | ||
|
||
- ``View/padding(_:_:)`` | ||
|
||
### Enumerations | ||
|
||
- ``Edge`` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/// A structure that represents the edges of a rectangle, used for specifying | ||
/// which sides to apply modifications to, such as padding or margin. | ||
/// | ||
/// This struct conforms to the `OptionSet` protocol, allowing for the combination | ||
/// of multiple edges using set operations. | ||
/// | ||
/// Usage: | ||
/// | ||
/// ```swift | ||
/// let edges: Edge = [.top, .left] | ||
/// ``` | ||
public enum Edge: Int8, CaseIterable { | ||
/// The top edge of a rectangle. | ||
case top = 0b0000_0001 | ||
|
||
/// The left edge of a rectangle. | ||
case left = 0b0000_0010 | ||
|
||
/// The bottom edge of a rectangle. | ||
case bottom = 0b0000_0100 | ||
|
||
/// The right edge of a rectangle. | ||
case right = 0b0000_1000 | ||
|
||
/// A set of edges. | ||
public struct Set: OptionSet { | ||
/// The element type of the option set. | ||
/// | ||
/// To inherit all the default implementations from the `OptionSet` protocol, | ||
/// the `Element` type must be `Self`, the default. | ||
public typealias Element = Edge.Set | ||
|
||
/// The raw integer value representing the edge. Used internally to distinguish | ||
/// different edges and combinations of edges. | ||
public let rawValue: Int8 | ||
|
||
/// Creates a new `Edge` instance from the given raw value. | ||
/// | ||
/// - Parameter rawValue: The raw integer value representing the edge. | ||
public init(rawValue: Int8) { | ||
self.rawValue = rawValue | ||
} | ||
|
||
/// Creates set of edges containing only the specified edge. | ||
public init(_ e: Edge) { | ||
self.rawValue = e.rawValue | ||
} | ||
|
||
/// The top edge of a rectangle. | ||
public static let top = Edge.Set(.top) | ||
|
||
/// The left edge of a rectangle. | ||
public static let left = Edge.Set(.left) | ||
|
||
/// The bottom edge of a rectangle. | ||
public static let bottom = Edge.Set(.bottom) | ||
|
||
/// The right edge of a rectangle. | ||
public static let right = Edge.Set(.right) | ||
|
||
/// A convenience option representing both the left and right edges. | ||
public static let horizontal: Edge.Set = [.left, .right] | ||
|
||
/// A convenience option representing both the top and bottom edges. | ||
public static let vertical: Edge.Set = [.top, .bottom] | ||
|
||
/// A convenience option representing all edges (top, left, bottom, right). | ||
public static let all: Edge.Set = [.top, .left, .bottom, .right] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
extension View { | ||
/// Set the padding for specific edges. | ||
/// | ||
/// - Parameters: | ||
/// - edges: The edges to which padding should be applied. | ||
/// - length: The size of the padding to apply, in points. If the padding is exactly between | ||
/// two padding classes, then the smaller padding class will be used. | ||
/// | ||
/// - SeeAlso: Tailwind CSS' [`padding`](https://tailwindcss.com/docs/padding) documentation. | ||
@available(iOS 17.0, macOS 14.0, *) | ||
public func padding(_ edges: Edge.Set, _ length: Double) -> some View { | ||
let paddingClass = closestTailwindPadding(ptLength: length) | ||
var classes = [String]() | ||
|
||
if edges == .all { | ||
classes = ["p-" + paddingClass] | ||
} else { | ||
if Edge.Set.horizontal.isSubset(of: edges) { | ||
classes.append("px-" + paddingClass) | ||
} else { | ||
if edges.contains(.left) { | ||
classes.append("pl-" + paddingClass) | ||
} | ||
if edges.contains(.right) { | ||
classes.append("pr-" + paddingClass) | ||
} | ||
} | ||
if Edge.Set.vertical.isSubset(of: edges) { | ||
classes.append("py-" + paddingClass) | ||
} else { | ||
if edges.contains(.top) { | ||
classes.append("pt-" + paddingClass) | ||
} | ||
if edges.contains(.bottom) { | ||
classes.append("pb-" + paddingClass) | ||
} | ||
} | ||
} | ||
return self.modifier(ClassModifier(add: classes.joined(separator: " "))) | ||
} | ||
|
||
/// Map a point size to the closest Tailwind CSS padding class. | ||
/// | ||
/// - Parameter size: The size in points to be mapped. | ||
/// - Returns: The Tailwind CSS padding class string. | ||
@available(iOS 17.0, macOS 14.0, *) | ||
private func closestTailwindPadding(ptLength: Double) -> String { | ||
// Tailwind padding classes and their corresponding sizes in points | ||
let paddingMapping: [(paddingClass: String, ptLength: Double)] = [ | ||
("0", 0), // 0pt | ||
("0.5", 2), // 0.125rem | ||
("1", 4), // 0.25rem | ||
("1.5", 6), // 0.375rem | ||
("2", 8), // 0.5rem | ||
("2.5", 10), // 0.625rem | ||
("3", 12), // 0.75rem | ||
("3.5", 14), // 0.875rem | ||
("4", 16), // 1rem | ||
("5", 20), // 1.25rem | ||
("6", 24), // 1.5rem | ||
("7", 28), // 1.75rem | ||
("8", 32), // 2rem | ||
("9", 36), // 2.25rem | ||
("10", 40), // 2.5rem | ||
("11", 44), // 2.75rem | ||
("12", 48), // 3rem | ||
("14", 56), // 3.5rem | ||
("16", 64), // 4rem | ||
("20", 80), // 5rem | ||
("24", 96), // 6rem | ||
("28", 112), // 7rem | ||
("32", 128), // 8rem | ||
("36", 144), // 9rem | ||
("40", 160), // 10rem | ||
("44", 176), // 11rem | ||
("48", 192), // 12rem | ||
("52", 208), // 13rem | ||
("56", 224), // 14rem | ||
("60", 240), // 15rem | ||
("64", 256), // 16rem | ||
("72", 288), // 18rem | ||
("80", 320), // 20rem | ||
("96", 384) // 24rem | ||
] | ||
|
||
// Find the closest matching padding size class | ||
let closestPadding = paddingMapping.min { abs($0.ptLength - ptLength) < abs($1.ptLength - ptLength) } | ||
return closestPadding?.paddingClass ?? "0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import Testing | ||
import Slipstream | ||
|
||
struct PaddingTests { | ||
@Test func paddingEdges() throws { | ||
try #expect(renderHTML(Div {}.padding(.all, 16)) == #"<div class="p-4"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.horizontal, 8)) == #"<div class="px-2"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.vertical, 12)) == #"<div class="py-3"></div>"#) | ||
try #expect(renderHTML(Div {}.padding([.top, .left], 24)) == #"<div class="pl-6 pt-6"></div>"#) | ||
|
||
try #expect(renderHTML(Div {}.padding(.top, 0)) == #"<div class="pt-0"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.left, 4)) == #"<div class="pl-1"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.bottom, 32)) == #"<div class="pb-8"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.right, 64)) == #"<div class="pr-16"></div>"#) | ||
} | ||
|
||
@Test func specificPaddingSizes() throws { | ||
try #expect(renderHTML(Div {}.padding(.top, 0)) == #"<div class="pt-0"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 0.5)) == #"<div class="pt-0"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 1)) == #"<div class="pt-0"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 2)) == #"<div class="pt-0.5"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 3)) == #"<div class="pt-0.5"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 4)) == #"<div class="pt-1"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 32)) == #"<div class="pt-8"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 64)) == #"<div class="pt-16"></div>"#) | ||
} | ||
|
||
@Test func repeatedPaddingModifications() throws { | ||
try #expect(renderHTML(Div {}.padding(.top, 0).padding(.right, 4)) == #"<div class="pt-0 pr-1"></div>"#) | ||
try #expect(renderHTML(Div {}.padding(.top, 0).padding(.top, 4)) == #"<div class="pt-0 pt-1"></div>"#) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters