Skip to content

Commit c5f2f71

Browse files
authored
Add ring and shadow style modifiers back in (#57)
1 parent 6d6109a commit c5f2f71

File tree

5 files changed

+345
-38
lines changed

5 files changed

+345
-38
lines changed

Sources/WebUI/Styles/Appearance/Border/BorderTypes.swift

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,3 @@ public enum BorderStyle: String {
8383
/// Divider style for child elements
8484
case divide = "divide"
8585
}
86-
87-
/// Specifies sizes for box shadows.
88-
///
89-
/// Defines shadow sizes from none to extra-large.
90-
///
91-
/// ## Example
92-
/// ```swift
93-
/// Stack(classes: ["card"])
94-
/// .shadow(size: .lg, color: .gray(._300, opacity: 0.5))
95-
/// ```
96-
public enum ShadowSize: String {
97-
/// No shadow
98-
case none = "none"
99-
/// Extra small shadow (2xs)
100-
case xs2 = "2xs"
101-
/// Extra small shadow (xs)
102-
case xs = "xs"
103-
/// Small shadow (sm)
104-
case sm = "sm"
105-
/// Medium shadow (default)
106-
case md = "md"
107-
/// Large shadow (lg)
108-
case lg = "lg"
109-
/// Extra large shadow (xl)
110-
case xl = "xl"
111-
/// 2x large shadow (2xl)
112-
case xl2 = "2xl"
113-
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
//
2+
// RingStyleOperation.swift
3+
// web-ui
4+
//
5+
// Created by Mac Long on 2025.05.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Style operation for ring styling
11+
///
12+
/// Provides a unified implementation for ring styling that can be used across
13+
/// Element methods and the Declaritive DSL functions.
14+
public struct RingStyleOperation: StyleOperation, @unchecked Sendable {
15+
/// Parameters for ring styling
16+
public struct Parameters {
17+
/// The ring width
18+
public let size: Int?
19+
20+
/// The ring color
21+
public let color: Color?
22+
23+
/// Creates parameters for ring styling
24+
///
25+
/// - Parameters:
26+
/// - size: the width of the ring
27+
/// - color: The ring color
28+
public init(
29+
size: Int? = 1,
30+
color: Color? = nil
31+
) {
32+
self.size = size
33+
self.color = color
34+
}
35+
36+
/// Creates parameters from a StyleParameters container
37+
///
38+
/// - Parameter params: The style parameters container
39+
/// - Returns: RingStyleOperation.Parameters
40+
public static func from(_ params: StyleParameters) -> Parameters {
41+
Parameters(
42+
size: params.get("size"),
43+
color: params.get("color")
44+
)
45+
}
46+
}
47+
48+
/// Applies the ring style and returns the appropriate CSS classes
49+
///
50+
/// - Parameter params: The parameters for ring styling
51+
/// - Returns: An array of CSS class names to be applied to elements
52+
public func applyClasses(params: Parameters) -> [String] {
53+
var classes: [String] = []
54+
let size = params.size ?? 1
55+
let color = params.color
56+
57+
classes.append("ring-\(size)")
58+
59+
if let color = color {
60+
classes.append("ring-\(color.rawValue)")
61+
}
62+
63+
return classes
64+
}
65+
66+
/// Shared instance for use across the framework
67+
public static let shared = RingStyleOperation()
68+
69+
/// Private initializer to enforce singleton usage
70+
private init() {}
71+
}
72+
73+
// Extension for Element to provide ring styling
74+
extension Element {
75+
/// Applies ring styling to the element with specified attributes.
76+
///
77+
/// Adds rings with custom width, style, and color to specified edges of an element.
78+
///
79+
/// - Parameters:
80+
/// - width: The ring width in pixels.
81+
/// - edges: One or more edges to apply the ring to. Defaults to `.all`.
82+
/// - style: The ring style (solid, dashed, etc.).
83+
/// - color: The ring color.
84+
/// - modifiers: Zero or more modifiers (e.g., `.hover`, `.md`) to scope the styles.
85+
/// - Returns: A new element with updated ring classes.
86+
///
87+
/// ## Example
88+
/// ```swift
89+
/// Stack()
90+
/// .ring(of: 2, at: .bottom, color: .blue(._500))
91+
/// .ring(of: 1, at: .horizontal, color: .gray(._200), on: .hover)
92+
/// ```
93+
public func ring(
94+
size: Int = 1,
95+
color: Color? = nil,
96+
on modifiers: Modifier...
97+
) -> Element {
98+
let params = RingStyleOperation.Parameters(
99+
size: size,
100+
color: color
101+
)
102+
103+
return RingStyleOperation.shared.applyToElement(
104+
self,
105+
params: params,
106+
modifiers: modifiers
107+
)
108+
}
109+
}
110+
111+
// Extension for ResponsiveBuilder to provide ring styling
112+
extension ResponsiveBuilder {
113+
/// Applies ring styling in a responsive context.
114+
///
115+
/// - Parameters:
116+
/// - size: The width of the ring.
117+
/// - color: The ring color.
118+
/// - Returns: The builder for method chaining.
119+
@discardableResult
120+
public func ring(
121+
size: Int = 1,
122+
color: Color? = nil
123+
) -> ResponsiveBuilder {
124+
let params = RingStyleOperation.Parameters(
125+
size: size,
126+
color: color
127+
)
128+
129+
return RingStyleOperation.shared.applyToBuilder(self, params: params)
130+
}
131+
132+
/// Helper method to apply just a ring color.
133+
///
134+
/// - Parameter color: The ring color to apply.
135+
/// - Returns: The builder for method chaining.
136+
@discardableResult
137+
public func ring(color: Color) -> ResponsiveBuilder {
138+
let params = RingStyleOperation.Parameters(color: color)
139+
return RingStyleOperation.shared.applyToBuilder(self, params: params)
140+
}
141+
}
142+
143+
// Global function for Declaritive DSL
144+
/// Applies ring styling in the responsive context.
145+
///
146+
/// - Parameters:
147+
/// - size: The width of the ring.
148+
/// - color: The ring color.
149+
/// - Returns: A responsive modification for rings.
150+
public func ring(
151+
of size: Int = 1,
152+
color: Color? = nil
153+
) -> ResponsiveModification {
154+
let params = RingStyleOperation.Parameters(
155+
size: size,
156+
color: color
157+
)
158+
159+
return RingStyleOperation.shared.asModification(params: params)
160+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import Foundation
2+
3+
/// Style operation for box shadow styling
4+
///
5+
/// Provides a unified implementation for box shadow styling that can be used across
6+
/// Element methods and the Declaritive DSL functions.
7+
public struct ShadowStyleOperation: StyleOperation, @unchecked Sendable {
8+
/// Parameters for shadow styling
9+
public struct Parameters {
10+
/// The shadow size
11+
public let size: ShadowSize?
12+
13+
/// The shadow color
14+
public let color: Color?
15+
16+
/// Creates parameters for shadow styling
17+
///
18+
/// - Parameters:
19+
/// - size: The shadow size
20+
/// - color: The shadow color
21+
public init(
22+
size: ShadowSize? = nil,
23+
color: Color? = nil
24+
) {
25+
self.size = size
26+
self.color = color
27+
}
28+
29+
/// Creates parameters from a StyleParameters container
30+
///
31+
/// - Parameter params: The style parameters container
32+
/// - Returns: ShadowStyleOperation.Parameters
33+
public static func from(_ params: StyleParameters) -> Parameters {
34+
Parameters(
35+
size: params.get("size"),
36+
color: params.get("color")
37+
)
38+
}
39+
}
40+
41+
/// Applies the shadow style and returns the appropriate CSS classes
42+
///
43+
/// - Parameter params: The parameters for shadow styling
44+
/// - Returns: An array of CSS class names to be applied to elements
45+
public func applyClasses(params: Parameters) -> [String] {
46+
var classes: [String] = []
47+
let size = params.size ?? ShadowSize.md
48+
let color = params.color
49+
50+
classes.append("shadow-\(size.rawValue)")
51+
52+
if let color = color {
53+
classes.append("shadow-\(color.rawValue)")
54+
}
55+
56+
return classes
57+
}
58+
59+
/// Shared instance for use across the framework
60+
public static let shared = ShadowStyleOperation()
61+
62+
/// Private initializer to enforce singleton usage
63+
private init() {}
64+
}
65+
66+
// Extension for Element to provide shadow styling
67+
extension Element {
68+
/// Applies shadow styling to the element with specified attributes.
69+
///
70+
/// Adds shadows with custom size and color to an element.
71+
///
72+
/// - Parameters:
73+
/// - size: The shadow size (sm, md, lg).
74+
/// - color: The shadow color.
75+
/// - modifiers: Zero or more modifiers (e.g., `.hover`, `.md`) to scope the styles.
76+
/// - Returns: A new element with updated shadow classes.
77+
///
78+
/// ## Example
79+
/// ```swift
80+
/// Stack()
81+
/// .shadow(size: .lg, color: .blue(._500))
82+
/// .shadow(size: .sm, color: .gray(._200), on: .hover)
83+
/// ```
84+
public func shadow(
85+
size: ShadowSize,
86+
color: Color? = nil,
87+
on modifiers: Modifier...
88+
) -> Element {
89+
let params = ShadowStyleOperation.Parameters(
90+
size: size,
91+
color: color
92+
)
93+
94+
return ShadowStyleOperation.shared.applyToElement(
95+
self,
96+
params: params,
97+
modifiers: modifiers
98+
)
99+
}
100+
}
101+
102+
// Extension for ResponsiveBuilder to provide shadow styling
103+
extension ResponsiveBuilder {
104+
/// Applies shadow styling in a responsive context.
105+
///
106+
/// - Parameters:
107+
/// - size: The shadow size.
108+
/// - color: The shadow color.
109+
/// - Returns: The builder for method chaining.
110+
@discardableResult
111+
public func shadow(
112+
size: ShadowSize? = .md,
113+
color: Color? = nil,
114+
) -> ResponsiveBuilder {
115+
let params = ShadowStyleOperation.Parameters(
116+
size: size,
117+
color: color
118+
)
119+
120+
return ShadowStyleOperation.shared.applyToBuilder(self, params: params)
121+
}
122+
123+
/// Helper method to apply just a shadow color.
124+
///
125+
/// - Parameter color: The shadow color to apply.
126+
/// - Returns: The builder for method chaining.
127+
@discardableResult
128+
public func shadow(color: Color) -> ResponsiveBuilder {
129+
let params = ShadowStyleOperation.Parameters(
130+
size: .md,
131+
color: color
132+
)
133+
134+
return ShadowStyleOperation.shared.applyToBuilder(self, params: params)
135+
}
136+
}
137+
138+
// Global function for Declaritive DSL
139+
/// Applies shadow styling in the responsive context.
140+
///
141+
/// - Parameters:
142+
/// - size: The shadow size.
143+
/// - color: The shadow color.
144+
/// - Returns: A responsive modification for shadows.
145+
public func shadow(
146+
of size: ShadowSize? = .md,
147+
color: Color? = nil
148+
) -> ResponsiveModification {
149+
let params = ShadowStyleOperation.Parameters(
150+
size: size,
151+
color: color
152+
)
153+
154+
return ShadowStyleOperation.shared.asModification(params: params)
155+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// Specifies sizes for box shadows.
2+
///
3+
/// Defines shadow sizes from none to extra-large.
4+
///
5+
/// ## Example
6+
/// ```swift
7+
/// Stack(classes: ["card"])
8+
/// .shadow(size: .lg, color: .gray(._300, opacity: 0.5))
9+
/// ```
10+
public enum ShadowSize: String {
11+
/// No shadow
12+
case none = "none"
13+
/// Extra small shadow (2xs)
14+
case xs2 = "2xs"
15+
/// Extra small shadow (xs)
16+
case xs = "xs"
17+
/// Small shadow (sm)
18+
case sm = "sm"
19+
/// Medium shadow (default)
20+
case md = "md"
21+
/// Large shadow (lg)
22+
case lg = "lg"
23+
/// Extra large shadow (xl)
24+
case xl = "xl"
25+
/// 2x large shadow (2xl)
26+
case xl2 = "2xl"
27+
}

0 commit comments

Comments
 (0)