Skip to content

Commit e131116

Browse files
committed
feat: Separate UI product and custom views support
1 parent 63feb53 commit e131116

23 files changed

+523
-326
lines changed

Example/Example.xcodeproj/project.pbxproj

+10-10
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
E1AE5A5C2796ED6A00EA911E /* DynamicForms in Frameworks */ = {isa = PBXBuildFile; productRef = E1AE5A5B2796ED6A00EA911E /* DynamicForms */; };
11-
E1AE5A5E2796EEDD00EA911E /* DynamicForms in Frameworks */ = {isa = PBXBuildFile; productRef = E1AE5A5D2796EEDD00EA911E /* DynamicForms */; };
10+
E196B8E127A002F100E03F7F /* DynamicFormsUI in Frameworks */ = {isa = PBXBuildFile; productRef = E196B8E027A002F100E03F7F /* DynamicFormsUI */; };
1211
E1CF381C279347B400315374 /* ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CF37F4279347B300315374 /* ExampleApp.swift */; };
1312
E1CF381D279347B400315374 /* ExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CF37F4279347B300315374 /* ExampleApp.swift */; };
1413
E1CF381E279347B400315374 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CF37F5279347B300315374 /* ContentView.swift */; };
1514
E1CF381F279347B400315374 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1CF37F5279347B300315374 /* ContentView.swift */; };
1615
E1CF3820279347B400315374 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1CF37F6279347B400315374 /* Assets.xcassets */; };
1716
E1CF3821279347B400315374 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1CF37F6279347B400315374 /* Assets.xcassets */; };
17+
E1F24A5D27A006FB007C4DF3 /* DynamicFormsUI in Frameworks */ = {isa = PBXBuildFile; productRef = E1F24A5C27A006FB007C4DF3 /* DynamicFormsUI */; };
1818
/* End PBXBuildFile section */
1919

2020
/* Begin PBXContainerItemProxy section */
@@ -50,15 +50,15 @@
5050
isa = PBXFrameworksBuildPhase;
5151
buildActionMask = 2147483647;
5252
files = (
53-
E1AE5A5C2796ED6A00EA911E /* DynamicForms in Frameworks */,
53+
E1F24A5D27A006FB007C4DF3 /* DynamicFormsUI in Frameworks */,
5454
);
5555
runOnlyForDeploymentPostprocessing = 0;
5656
};
5757
E1CF37FE279347B400315374 /* Frameworks */ = {
5858
isa = PBXFrameworksBuildPhase;
5959
buildActionMask = 2147483647;
6060
files = (
61-
E1AE5A5E2796EEDD00EA911E /* DynamicForms in Frameworks */,
61+
E196B8E127A002F100E03F7F /* DynamicFormsUI in Frameworks */,
6262
);
6363
runOnlyForDeploymentPostprocessing = 0;
6464
};
@@ -142,7 +142,7 @@
142142
);
143143
name = "Example (iOS)";
144144
packageProductDependencies = (
145-
E1AE5A5B2796ED6A00EA911E /* DynamicForms */,
145+
E1F24A5C27A006FB007C4DF3 /* DynamicFormsUI */,
146146
);
147147
productName = "Example (iOS)";
148148
productReference = E1CF37FB279347B400315374 /* Example.app */;
@@ -162,7 +162,7 @@
162162
);
163163
name = "Example (macOS)";
164164
packageProductDependencies = (
165-
E1AE5A5D2796EEDD00EA911E /* DynamicForms */,
165+
E196B8E027A002F100E03F7F /* DynamicFormsUI */,
166166
);
167167
productName = "Example (macOS)";
168168
productReference = E1CF3801279347B400315374 /* Example.app */;
@@ -681,13 +681,13 @@
681681
/* End XCConfigurationList section */
682682

683683
/* Begin XCSwiftPackageProductDependency section */
684-
E1AE5A5B2796ED6A00EA911E /* DynamicForms */ = {
684+
E196B8E027A002F100E03F7F /* DynamicFormsUI */ = {
685685
isa = XCSwiftPackageProductDependency;
686-
productName = DynamicForms;
686+
productName = DynamicFormsUI;
687687
};
688-
E1AE5A5D2796EEDD00EA911E /* DynamicForms */ = {
688+
E1F24A5C27A006FB007C4DF3 /* DynamicFormsUI */ = {
689689
isa = XCSwiftPackageProductDependency;
690-
productName = DynamicForms;
690+
productName = DynamicFormsUI;
691691
};
692692
/* End XCSwiftPackageProductDependency section */
693693
};

Example/Shared/ContentView.swift

+8-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//
77

88
import SwiftUI
9-
import DynamicForms
9+
import DynamicFormsUI
1010

1111
struct ContentView: View {
1212
@State
@@ -19,14 +19,12 @@ struct ContentView: View {
1919
DynamicText("Initial")
2020
}
2121
DynamicStack(.horizontal) {
22-
DynamicButton(
23-
DynamicText("OK"),
24-
action: "content.ok"
25-
)
26-
DynamicButton(
27-
DynamicText("Cancel"),
28-
action: "content.cancel"
29-
)
22+
DynamicButton(action: "content.ok") {
23+
DynamicText("OK")
24+
}
25+
DynamicButton(action: "content.cancel") {
26+
DynamicText("Cancel")
27+
}
3028
}
3129
}
3230
}
@@ -36,7 +34,7 @@ struct ContentView: View {
3634

3735
var body: some View {
3836
ZStack {
39-
DynamicFormView($form)
37+
DynamicViews.Form($form)
4038
VStack {
4139
Spacer()
4240
ScrollView(.vertical, showsIndicators: false) {

Package.swift

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ let package = Package(
1313
name: "DynamicForms",
1414
targets: ["DynamicForms"]
1515
),
16+
.library(
17+
name: "DynamicFormsUI",
18+
targets: ["DynamicFormsUI"]
19+
),
1620
],
1721
dependencies: [
1822
.package(
@@ -58,6 +62,12 @@ let package = Package(
5862
)
5963
]
6064
),
65+
.target(
66+
name: "DynamicFormsUI",
67+
dependencies: [
68+
.target(name: "DynamicForms")
69+
]
70+
),
6171
.testTarget(
6272
name: "DynamicFormsTests",
6373
dependencies: [

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
- **To-think-about**
3030
- API improvements for state management
3131
- API improvements for action handling
32-
- API for custom views
3332
- Helper for derived (optional/collection) `Binding`s
3433
- Separate `DynamicForms` target into `DynamicForms` and `DynamicFormsUI` targets
3534

@@ -138,7 +137,7 @@ If you use SwiftPM for your project, you can add StandardClients to your package
138137
.package(
139138
name: "swiftui-dynamic-forms",
140139
url: "https://github.com/capturecontext/swiftui-dynamic-forms.git",
141-
.branch("0.0.1")
140+
.branch("0.1.0")
142141
)
143142
```
144143

Sources/DynamicForms/Components/DynamicSpacer.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Foundation
33
public struct DynamicSpacer: Equatable, DynamicElement, Identifiable {
44
public init(
55
id: DynamicElementIdentifier = .uuid(),
6-
minLength: Double?
6+
minLength: Double? = nil
77
) {
88
self.id = id
99
self.minLength = minLength

Sources/DynamicForms/Components/DynamicText.swift

+7-116
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ import SwiftUI
5656
public struct DynamicText: Equatable, Hashable, Identifiable {
5757
public var id: DynamicElementIdentifier
5858

59-
fileprivate let storage: Storage
60-
fileprivate var modifiers: [Modifier] = []
59+
public let storage: Storage
60+
public var modifiers: [Modifier] = []
6161

62-
fileprivate init(
62+
public init(
6363
storage: Storage,
6464
modifiers: [Modifier] = []
6565
) {
@@ -68,7 +68,7 @@ public struct DynamicText: Equatable, Hashable, Identifiable {
6868
self.id = .uuid()
6969
}
7070

71-
fileprivate enum Modifier: Equatable, Hashable {
71+
public enum Modifier: Equatable, Hashable {
7272
case accessibilityHeading(AccessibilityHeadingLevel)
7373
case accessibilityLabel(DynamicText)
7474
case accessibilityTextContentType(AccessibilityTextContentType)
@@ -84,12 +84,12 @@ public struct DynamicText: Equatable, Hashable, Identifiable {
8484
case underline(active: Bool, color: Color?)
8585
}
8686

87-
fileprivate enum Storage: Equatable, Hashable {
87+
public enum Storage: Equatable, Hashable {
8888
indirect case concatenated(DynamicText, DynamicText)
8989
case localized(LocalizedStringKey, tableName: String?, bundle: Bundle?, comment: StaticString?)
9090
case verbatim(String)
9191

92-
static func == (lhs: Self, rhs: Self) -> Bool {
92+
public static func == (lhs: Self, rhs: Self) -> Bool {
9393
switch (lhs, rhs) {
9494
case let (.concatenated(l1, l2), .concatenated(r1, r2)):
9595
return l1 == r1 && l2 == r2
@@ -111,7 +111,7 @@ public struct DynamicText: Equatable, Hashable, Identifiable {
111111
}
112112
}
113113

114-
func hash(into hasher: inout Hasher) {
114+
public func hash(into hasher: inout Hasher) {
115115
enum Key {
116116
case concatenated
117117
case localized
@@ -225,41 +225,10 @@ extension DynamicText {
225225
extension DynamicText {
226226
public enum AccessibilityTextContentType: String, Equatable, Hashable {
227227
case console, fileSystem, messaging, narrative, plain, sourceCode, spreadsheet, wordProcessing
228-
229-
#if compiler(>=5.5.1)
230-
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
231-
var toSwiftUI: SwiftUI.AccessibilityTextContentType {
232-
switch self {
233-
case .console: return .console
234-
case .fileSystem: return .fileSystem
235-
case .messaging: return .messaging
236-
case .narrative: return .narrative
237-
case .plain: return .plain
238-
case .sourceCode: return .sourceCode
239-
case .spreadsheet: return .spreadsheet
240-
case .wordProcessing: return .wordProcessing
241-
}
242-
}
243-
#endif
244228
}
245229

246230
public enum AccessibilityHeadingLevel: String, Equatable, Hashable {
247231
case h1, h2, h3, h4, h5, h6, unspecified
248-
249-
#if compiler(>=5.5.1)
250-
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
251-
var toSwiftUI: SwiftUI.AccessibilityHeadingLevel {
252-
switch self {
253-
case .h1: return .h1
254-
case .h2: return .h2
255-
case .h3: return .h3
256-
case .h4: return .h4
257-
case .h5: return .h5
258-
case .h6: return .h6
259-
case .unspecified: return .unspecified
260-
}
261-
}
262-
#endif
263232
}
264233
}
265234

@@ -300,84 +269,6 @@ extension DynamicText {
300269
}
301270
}
302271

303-
extension Text {
304-
public init(_ state: DynamicText) {
305-
let text: Text
306-
switch state.storage {
307-
case let .concatenated(first, second):
308-
text = Text(first) + Text(second)
309-
case let .localized(content, tableName, bundle, comment):
310-
text = .init(content, tableName: tableName, bundle: bundle, comment: comment)
311-
case let .verbatim(content):
312-
text = .init(verbatim: content)
313-
}
314-
self = state.modifiers.reduce(text) { text, modifier in
315-
switch modifier {
316-
#if compiler(>=5.5.1)
317-
case let .accessibilityHeading(level):
318-
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
319-
return text.accessibilityHeading(level.toSwiftUI)
320-
} else {
321-
return text
322-
}
323-
case let .accessibilityLabel(value):
324-
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
325-
switch value.storage {
326-
case let .verbatim(string):
327-
return text.accessibilityLabel(string)
328-
case let .localized(key, tableName, bundle, comment):
329-
return text.accessibilityLabel(
330-
Text(key, tableName: tableName, bundle: bundle, comment: comment))
331-
case .concatenated(_, _):
332-
assertionFailure("`.accessibilityLabel` does not support contcatenated `DynamicText`")
333-
return text
334-
}
335-
} else {
336-
return text
337-
}
338-
case let .accessibilityTextContentType(type):
339-
if #available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) {
340-
return text.accessibilityTextContentType(type.toSwiftUI)
341-
} else {
342-
return text
343-
}
344-
#else
345-
case .accessibilityHeading,
346-
.accessibilityLabel,
347-
.accessibilityTextContentType:
348-
return text
349-
#endif
350-
case let .baselineOffset(baselineOffset):
351-
return text.baselineOffset(baselineOffset)
352-
case .bold:
353-
return text.bold()
354-
case let .font(font):
355-
return text.font(font)
356-
case let .fontWeight(weight):
357-
return text.fontWeight(weight)
358-
case let .foregroundColor(color):
359-
return text.foregroundColor(color)
360-
case .italic:
361-
return text.italic()
362-
case let .kerning(kerning):
363-
return text.kerning(kerning)
364-
case let .strikethrough(active, color):
365-
return text.strikethrough(active, color: color)
366-
case let .tracking(tracking):
367-
return text.tracking(tracking)
368-
case let .underline(active, color):
369-
return text.underline(active, color: color)
370-
}
371-
}
372-
}
373-
}
374-
375-
extension DynamicText: View {
376-
public var body: some View {
377-
Text(self)
378-
}
379-
}
380-
381272
extension String {
382273
public init(state: DynamicText, locale: Locale? = nil) {
383274
switch state.storage {

0 commit comments

Comments
 (0)