diff --git a/Apps/Examples/Examples.xcodeproj/project.pbxproj b/Apps/Examples/Examples.xcodeproj/project.pbxproj index 9e6046183..1c8e61c0b 100644 --- a/Apps/Examples/Examples.xcodeproj/project.pbxproj +++ b/Apps/Examples/Examples.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 6D6E866F2C539CDE00EDB6F4 /* InPlaceLoadingFlexibleButtonExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6E866E2C539CDE00EDB6F4 /* InPlaceLoadingFlexibleButtonExample.swift */; }; 6D6E86712C53A0D500EDB6F4 /* CardViewWithTwoButtonsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D6E86702C53A0D500EDB6F4 /* CardViewWithTwoButtonsExample.swift */; }; 6DE3F6A82D0FB9C600A4DAB6 /* ActionItemsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DE3F6A62D0FB9C600A4DAB6 /* ActionItemsExample.swift */; }; + 6DE3F6AC2D0FFEF100A4DAB6 /* ActivityItemsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DE3F6AB2D0FFEF100A4DAB6 /* ActivityItemsExample.swift */; }; 6DEC31F42C463ED50084DD20 /* FioriButtonTestsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEC31F32C463ED50084DD20 /* FioriButtonTestsExample.swift */; }; 6DEC31F82C47B7850084DD20 /* FioriButtonStyleToggleExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEC31F72C47B7850084DD20 /* FioriButtonStyleToggleExample.swift */; }; 6DEC31FA2C48B35D0084DD20 /* FioriButtonCustomButtonExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DEC31F92C48B35D0084DD20 /* FioriButtonCustomButtonExample.swift */; }; @@ -273,6 +274,7 @@ 6D6E866E2C539CDE00EDB6F4 /* InPlaceLoadingFlexibleButtonExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPlaceLoadingFlexibleButtonExample.swift; sourceTree = ""; }; 6D6E86702C53A0D500EDB6F4 /* CardViewWithTwoButtonsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardViewWithTwoButtonsExample.swift; sourceTree = ""; }; 6DE3F6A62D0FB9C600A4DAB6 /* ActionItemsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionItemsExample.swift; sourceTree = ""; }; + 6DE3F6AB2D0FFEF100A4DAB6 /* ActivityItemsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityItemsExample.swift; sourceTree = ""; }; 6DEC31F32C463ED50084DD20 /* FioriButtonTestsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonTestsExample.swift; sourceTree = ""; }; 6DEC31F72C47B7850084DD20 /* FioriButtonStyleToggleExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonStyleToggleExample.swift; sourceTree = ""; }; 6DEC31F92C48B35D0084DD20 /* FioriButtonCustomButtonExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FioriButtonCustomButtonExample.swift; sourceTree = ""; }; @@ -580,6 +582,7 @@ 6D66D7F02D02FC7B00F7A97D /* ActivityItem */ = { isa = PBXGroup; children = ( + 6DE3F6AB2D0FFEF100A4DAB6 /* ActivityItemsExample.swift */, 6D66D7EF2D02FC7B00F7A97D /* ActivityItemExample.swift */, ); path = ActivityItem; @@ -1292,6 +1295,7 @@ B84D24EF2652F343007F2373 /* ObjectHeaderTestApp.swift in Sources */, B84D24EC2652F343007F2373 /* ObjectHeaderSpecCompact.swift in Sources */, 8A5579CD24C1293C0098003A /* SettingsLabel.swift in Sources */, + 6DE3F6AC2D0FFEF100A4DAB6 /* ActivityItemsExample.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Apps/Examples/Examples/FioriSwiftUICore/ActivityItem/ActivityItemsExample.swift b/Apps/Examples/Examples/FioriSwiftUICore/ActivityItem/ActivityItemsExample.swift new file mode 100644 index 000000000..dc36b4609 --- /dev/null +++ b/Apps/Examples/Examples/FioriSwiftUICore/ActivityItem/ActivityItemsExample.swift @@ -0,0 +1,147 @@ +import FioriSwiftUICore +import SwiftUI + +struct ActivityItemsExample: View { + var body: some View { + List { + Section { + ActivityItems(actionItems: [ + .init(type: .phone, didSelectActivityItem: { + print("click phone") + }) + ]) + ActivityItems(actionItems: [ + .init(type: .phone, didSelectActivityItem: { + print("click phone") + }), + .init(type: .email, didSelectActivityItem: { + print("click email") + }) + ]) + ActivityItems(actionItems: [ + .init(type: .phone, didSelectActivityItem: { + print("click phone") + }), + .init(type: .email, didSelectActivityItem: { + print("click email") + }), + .init(type: .message, didSelectActivityItem: { + print("click message") + }) + ]) + ActivityItems(actionItems: [ + .init(type: .phone, didSelectActivityItem: { + print("click phone") + }), + .init(type: .email, didSelectActivityItem: { + print("click email") + }), + .init(type: .message, didSelectActivityItem: { + print("click message") + }), + .init(type: .videoCall, didSelectActivityItem: { + print("click videoCall") + }) + ]) + ActivityItems(actionItems: [ + .init(type: .phone, didSelectActivityItem: { + print("click phone") + }), + .init(type: .email, didSelectActivityItem: { + print("click email") + }), + .init(type: .message, didSelectActivityItem: { + print("click message") + }), + .init(type: .videoCall, didSelectActivityItem: { + print("click videoCall") + }), + .init(type: .detail, didSelectActivityItem: { + print("click detail") + }) + ]) + .actionItemsStyle { conf in + conf.actionItems + .font(.fiori(forTextStyle: .headline).weight(.bold)) + .foregroundColor(.red) + } + } header: { + Text("Usual Type") + .textCase(.none) + } + + Section { + ActivityItems(actionItems: [ + .init(type: .custom(Image(systemName: "person")), didSelectActivityItem: { + print("custom person") + }), + .init(type: .custom(Image(systemName: "heart")), didSelectActivityItem: { + print("custom heart") + }), + .init(type: .custom(Image(systemName: "clock")), didSelectActivityItem: { + print("custom clock") + }) + ]) + } header: { + Text("Custom Type") + .textCase(.none) + } + + Section { + ActivityItems { + Button { + print("click person") + } label: { + Image(systemName: "person") + .font(.fiori(forTextStyle: .headline).weight(.heavy)) + .imageScale(.large) + .foregroundColor(.red) + .frame(width: 44, height: 44) + } + .buttonStyle(BorderlessButtonStyle()) + + Button { + print("click heart") + } label: { + Image(systemName: "heart") + .font(.fiori(forTextStyle: .headline).weight(.heavy)) + .imageScale(.large) + .foregroundColor(.yellow) + .frame(width: 44, height: 44) + } + .buttonStyle(BorderlessButtonStyle()) + + Button { + print("click info.circle") + } label: { + Image(systemName: "info.circle") + .font(.fiori(forTextStyle: .headline).weight(.heavy)) + .imageScale(.large) + .foregroundColor(.blue) + .frame(width: 44, height: 44) + } + .buttonStyle(BorderlessButtonStyle()) + + Button { + print("click book") + } label: { + Image(systemName: "book") + .font(.fiori(forTextStyle: .headline).weight(.heavy)) + .imageScale(.large) + .foregroundColor(.green) + .frame(width: 44, height: 44) + } + .buttonStyle(BorderlessButtonStyle()) + } + } header: { + Text("Custom items") + .textCase(.none) + } + } + .navigationTitle("ActivityItemsExample") + } +} + +#Preview { + ActivityItemsExample() +} diff --git a/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemCompactExamples.swift b/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemCompactExamples.swift index cb0de3e9a..97bd6da45 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemCompactExamples.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemCompactExamples.swift @@ -29,35 +29,35 @@ struct ContactItemCompactExamples: ListDataProtocol { func cellForRow(_ indexPath: IndexPath) -> AnyView { switch (indexPath.section, indexPath.row) { case (0, 0): - let ci = ContactItem(title: "Seann Longname", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Seann Longname", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) return AnyView(ci) case (0, 1): - let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", actionItems: ActivityItems(actionItems: [.init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", actionItems: _ActivityItems(actionItems: [.init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) return AnyView(ci) case (0, 2): - let ci = ContactItem(title: "Sean Long has a name that wraps two lines", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long has a name that wraps two lines", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) return AnyView(ci) case (0, 3): - let ci = ContactItem(title: "Headline example when it wraps two lines", subtitle: "Team Lead", actionItems: ActivityItems(actionItems: [.init(type: .email), .init(type: .phone)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example when it wraps two lines", subtitle: "Team Lead", actionItems: _ActivityItems(actionItems: [.init(type: .email), .init(type: .phone)], didSelectActivityItem: { dataType in print("\(dataType)") })) return AnyView(ci) case (0, 4): - let ci = ContactItem(title: "Seann Longname", subtitle: "Team Lead", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Seann Longname", subtitle: "Team Lead", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -65,7 +65,7 @@ struct ContactItemCompactExamples: ListDataProtocol { return AnyView(ci) case (0, 5): - let ci = ContactItem(title: "Headline when\n wraps 2 lines", subtitle: "Team Lead", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline when\n wraps 2 lines", subtitle: "Team Lead", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) diff --git a/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemRegularExamples.swift b/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemRegularExamples.swift index 79d8b05f4..1c1124a38 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemRegularExamples.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/ContactItem/ContactItemRegularExamples.swift @@ -31,7 +31,7 @@ struct ContactItemRegularExamples: ListDataProtocol { func cellForRow(_ indexPath: IndexPath) -> AnyView { switch (indexPath.section, indexPath.row) { case (0, 0): - let ci = ContactItem(title: "Headline only example", descriptionText: "One line of text description is baseline aligned.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline only example", descriptionText: "One line of text description is baseline aligned.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.355) @@ -39,7 +39,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 1): - let ci = ContactItem(title: "Sean Long", descriptionText: "Single line of text is baseline aligned and expands.", detailImage: Image("person_square4"), actionItems: ActivityItems(actionItems: [.init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", descriptionText: "Single line of text is baseline aligned and expands.", detailImage: Image("person_square4"), actionItems: _ActivityItems(actionItems: [.init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -47,7 +47,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 2): - let ci = ContactItem(title: "Headline only example", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline only example", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.355) @@ -55,7 +55,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 3): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered as this example here", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered as this example here", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -85,7 +85,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 5): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should. Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should. Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -93,7 +93,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 6): - let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.4) @@ -101,7 +101,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 7): - let ci = ContactItem(title: "Sean Long name that wraps two lines", descriptionText: "Text is centered like this example and expands here.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long name that wraps two lines", descriptionText: "Text is centered like this example and expands here.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.34) @@ -109,7 +109,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 8): - let ci = ContactItem(title: "Headline example when text wraps two lines", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example when text wraps two lines", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.36) @@ -117,7 +117,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 9): - let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Description is always centered and this example shows the text that is set to truncate at two lines", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Description is always centered and this example shows the text that is set to truncate at two lines", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -125,7 +125,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 10): - let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(0.3) @@ -133,14 +133,14 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (0, 11): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message), .init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message), .init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in print("\(dataType)") })) return AnyView(ci) case (1, 0): - let ci = ContactItem(title: "Headline only example", descriptionText: "One line of text description is baseline aligned.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline only example", descriptionText: "One line of text description is baseline aligned.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -148,7 +148,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 1): - let ci = ContactItem(title: "Sean Long", descriptionText: "Single line of text is baseline aligned and expands.", detailImage: Image("person_square4"), actionItems: ActivityItems(actionItems: [.init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", descriptionText: "Single line of text is baseline aligned and expands.", detailImage: Image("person_square4"), actionItems: _ActivityItems(actionItems: [.init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -156,7 +156,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 2): - let ci = ContactItem(title: "Headline only example", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline only example", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -164,7 +164,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 3): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered as this example here", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered as this example here", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -172,7 +172,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 4): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered and this example shows the text that is set to truncate after two lines", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Description is always centered and this example shows the text that is set to truncate after two lines", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -180,7 +180,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 5): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should. Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should. Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -188,7 +188,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 6): - let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example is allowed to wrap two lines ok", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -196,7 +196,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 7): - let ci = ContactItem(title: "Sean Long name that wraps two lines", descriptionText: "Text is centered like this example and expands here.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long name that wraps two lines", descriptionText: "Text is centered like this example and expands here.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -204,7 +204,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 8): - let ci = ContactItem(title: "Headline example when text wraps two lines", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example when text wraps two lines", subtitle: "Team Lead", descriptionText: "One line of text in description is centered here.", actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -234,7 +234,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 10): - let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Headline example wraps two lines", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message)], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) @@ -242,7 +242,7 @@ struct ContactItemRegularExamples: ListDataProtocol { return AnyView(ci) case (1, 11): - let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message), .init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in + let ci = ContactItem(title: "Sean Long", subtitle: "Team Lead", descriptionText: "Example showing three lines of text at maximum lipsum ortam at al and the description is always still centered here and should.", detailImage: Image("person_square4").resizable(), actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .videoCall), .init(type: .message), .init(type: .email), .init(type: .detail), .init(type: .custom(Image(systemName: "power")))], didSelectActivityItem: { dataType in print("\(dataType)") })) .splitPercent(nil) diff --git a/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift b/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift index 558eb3143..9eaf70f16 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift @@ -13,6 +13,12 @@ struct CoreContentView: View { Text("ActivityItem") } + NavigationLink { + ActivityItemsExample() + } label: { + Text("ActivityItems") + } + NavigationLink { ActionItemsExample() } label: { diff --git a/Apps/Examples/Examples/FioriSwiftUICore/Experimental/Examples/ContactItemActionItemsExample.swift b/Apps/Examples/Examples/FioriSwiftUICore/Experimental/Examples/ContactItemActionItemsExample.swift index 858c8fdfe..dd0804af0 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/Experimental/Examples/ContactItemActionItemsExample.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/Experimental/Examples/ContactItemActionItemsExample.swift @@ -33,7 +33,7 @@ struct ContactItemActionItemsExample: View { } actionItems: { if self.useCompositeControl { // equivalent to `ActivityItems(model: viewModel)` - ActivityItems(actionItems: self.viewModel.actionItems?.actionItems) { selectedActivity in + _ActivityItems(actionItems: self.viewModel.actionItems?.actionItems) { selectedActivity in self.viewModel.selectedActivity = selectedActivity } } else { @@ -49,7 +49,7 @@ struct ContactItemActionItemsExample: View { ExpHeaderView(nil, subtitle: "Option: Type-based init", desc: "SDK will internally choose and initialize the control handling action items") ContactItem(title: self.viewModel.title, subtitle: self.viewModel.subtitle, descriptionText: self.viewModel.descriptionText, - detailImage: self.viewModel.detailImage, actionItems: self.viewModel.actionItems != nil ? ActivityItems(model: self.viewModel.actionItems!) : nil) + detailImage: self.viewModel.detailImage, actionItems: self.viewModel.actionItems != nil ? _ActivityItems(model: self.viewModel.actionItems!) : nil) .exampleHighlighting() ExpHeaderView(nil, subtitle: "Option: Protocol/Model-based init", desc: "conform your model to protocol `ContactItemModel`") @@ -69,7 +69,7 @@ struct ContactItemActionItemsExample: View { class ContactItemActionItemsExampleViewModel: ObservableObject { var model = LibraryPreviewData.Person.laurelosborn - lazy var actionItems: ActivityItemsModel? = { + lazy var actionItems: _ActivityItemsModel? = { let items: [ActivityItemDataType] = [ .init(type: .email, data: "Laurel@example.com"), .init(type: .email, data: "Laurel@contoso.com") @@ -100,7 +100,7 @@ extension ContactItemActionItemsExampleViewModel: ContactItemModel, ActionItemsC var descriptionText: String? { self.model.descriptionText } var detailImage: Image? { self.model.detailImage } - struct ActivityItemsDataModel: ActivityItemsModel { + struct ActivityItemsDataModel: _ActivityItemsModel { let actionItems: [ActivityItemDataType]? let didSelectActivityItem: ((ActivityItemDataType) -> Void)? } diff --git a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift index 26a40302b..28d487e53 100644 --- a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift +++ b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift @@ -104,7 +104,11 @@ public protocol _ActivityItemModel: IconComponent, SubtitleComponent {} public protocol ActivityItemModel {} // sourcery: generated_component_not_configurable -public protocol ActivityItemsModel: ActionItemsComponent {} +public protocol _ActivityItemsModel: ActionItemsComponent {} + +/// Deprecated ActivityItems +@available(*, unavailable, renamed: "_ActivityItemsModel", message: "Will be removed in the future release. Please create ActivityItems with other initializers instead.") +public protocol ActivityItemsModel {} // sourcery: generated_component // sourcery: add_env_props = "listBackground" @@ -156,7 +160,7 @@ public protocol SideBarModel {} // sourcery: virtualPropMainViewSize = "@State var mainViewSize: CGSize = .zero" // sourcery: generated_component_composite public protocol ContactItemModel: TitleComponent, SubtitleComponent, DescriptionTextComponent, DetailImageComponent { - var actionItems: ActivityItemsModel? { get } + var actionItems: _ActivityItemsModel? { get } } // sourcery: add_env_props = ["horizontalSizeClass"] diff --git a/Sources/FioriSwiftUICore/Views/ActivityItems+View.swift b/Sources/FioriSwiftUICore/Views/ActivityItems+View.swift index 7d18bf1db..5d12379b6 100644 --- a/Sources/FioriSwiftUICore/Views/ActivityItems+View.swift +++ b/Sources/FioriSwiftUICore/Views/ActivityItems+View.swift @@ -24,7 +24,7 @@ extension Fiori { // FIXME: - Implement ActivityItems View body -extension ActivityItems: View { +extension _ActivityItems: View { public var body: some View { ActivityControlLayoutContainer(_actionItems ?? []) { activity in ActivityButtonView(image: activity.icon) { diff --git a/Sources/FioriSwiftUICore/_ComponentProtocols/BaseComponentProtocols.swift b/Sources/FioriSwiftUICore/_ComponentProtocols/BaseComponentProtocols.swift index 25880422b..d1b5ab75e 100755 --- a/Sources/FioriSwiftUICore/_ComponentProtocols/BaseComponentProtocols.swift +++ b/Sources/FioriSwiftUICore/_ComponentProtocols/BaseComponentProtocols.swift @@ -472,9 +472,11 @@ protocol _ProgressComponent { /// /// ## Usage /// ```swift -/// ActionItems(actionItems: [.init(type: .phone), .init(type: .email), .init(type: .message), .init(type: .videoCall), .init(type: .detail)]) { dataType in -/// print("\(dataType)") -/// } +/// ActionItems(actionItems: [ +/// .init(type: .phone, didSelectActivityItem: { +/// print("click phone") +/// }) +/// ]) /// ``` // sourcery: BaseComponent protocol _ActionItemsComponent { diff --git a/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift b/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift index 54c4a851f..2e0fede9a 100755 --- a/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift +++ b/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift @@ -742,6 +742,19 @@ protocol _ActivityItemComponent: _IconComponent, _SubtitleComponent { var layout: ActivityItemLayout { get } } +/// `ActivityItems` provides a view that shows several items with action. +/// +/// ## Usage +/// ```swift +/// ActivityItems(actionItems: [ +/// .init(type: .phone, didSelectActivityItem: { +/// print("click phone") +/// }) +/// ]) +/// ``` +// sourcery: CompositeComponent +protocol _ActivityItemsComponent: _ActionItemsComponent {} + // sourcery: CompositeComponent protocol _RangeSliderControlComponent: _LowerThumbComponent, _UpperThumbComponent, _ActiveTrackComponent, _InactiveTrackComponent { // sourcery: @Binding diff --git a/Sources/FioriSwiftUICore/_FioriStyles/ActivityItemsStyle.fiori.swift b/Sources/FioriSwiftUICore/_FioriStyles/ActivityItemsStyle.fiori.swift new file mode 100644 index 000000000..131867f75 --- /dev/null +++ b/Sources/FioriSwiftUICore/_FioriStyles/ActivityItemsStyle.fiori.swift @@ -0,0 +1,32 @@ +import FioriThemeManager +import Foundation +import SwiftUI + +// Base Layout style +public struct ActivityItemsBaseStyle: ActivityItemsStyle { + public func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + // Add default layout here + configuration.actionItems + } +} + +// Default fiori styles +extension ActivityItemsFioriStyle { + struct ContentFioriStyle: ActivityItemsStyle { + func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + ActivityItems(configuration) + // Add default style for its content + // .background() + } + } + + struct ActionItemsFioriStyle: ActionItemsStyle { + let activityItemsConfiguration: ActivityItemsConfiguration + + func makeBody(_ configuration: ActionItemsConfiguration) -> some View { + ActionItems(configuration) + .font(.fiori(forTextStyle: .body).weight(.light)) + .foregroundColor(.preferredColor(.tintColor)) + } + } +} diff --git a/Sources/FioriSwiftUICore/_FioriStyles/CardStyle.fiori.swift b/Sources/FioriSwiftUICore/_FioriStyles/CardStyle.fiori.swift index 0f7fe400d..e7d6fbff9 100644 --- a/Sources/FioriSwiftUICore/_FioriStyles/CardStyle.fiori.swift +++ b/Sources/FioriSwiftUICore/_FioriStyles/CardStyle.fiori.swift @@ -761,7 +761,7 @@ public enum CardTests { VStack(alignment: .leading, spacing: 4) { ContactItem(title: "Title", subtitle: "Subtitle", - actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .email)], didSelectActivityItem: { dataType in + actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .email)], didSelectActivityItem: { dataType in print("\(dataType)") })) @@ -795,7 +795,7 @@ public enum CardTests { VStack(alignment: .center, spacing: 4) { ContactItem(title: "Title", subtitle: "Subtitle", - actionItems: ActivityItems(actionItems: [.init(type: .phone), .init(type: .email)], didSelectActivityItem: { dataType in + actionItems: _ActivityItems(actionItems: [.init(type: .phone), .init(type: .email)], didSelectActivityItem: { dataType in print("\(dataType)") })) diff --git a/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActionItems/ActionItems.generated.swift b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActionItems/ActionItems.generated.swift index 4f92d4e98..d5810fae0 100644 --- a/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActionItems/ActionItems.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActionItems/ActionItems.generated.swift @@ -7,9 +7,11 @@ import SwiftUI /// /// ## Usage /// ```swift -/// ActionItems(actionItems: [.init(type: .phone), .init(type: .email), .init(type: .message), .init(type: .videoCall), .init(type: .detail)]) { dataType in -/// print("\(dataType)") -/// } +/// ActionItems(actionItems: [ +/// .init(type: .phone, didSelectActivityItem: { +/// print("click phone") +/// }) +/// ]) /// ``` public struct ActionItems { let actionItems: any View diff --git a/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItems.generated.swift b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItems.generated.swift new file mode 100644 index 000000000..da33039dd --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItems.generated.swift @@ -0,0 +1,73 @@ +// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import Foundation +import SwiftUI + +/// `ActivityItems` provides a view that shows several items with action. +/// +/// ## Usage +/// ```swift +/// ActivityItems(actionItems: [ +/// .init(type: .phone, didSelectActivityItem: { +/// print("click phone") +/// }) +/// ]) +/// ``` +public struct ActivityItems { + let actionItems: any View + + @Environment(\.activityItemsStyle) var style + + fileprivate var _shouldApplyDefaultStyle = true + + public init(@ActionItemsBuilder actionItems: () -> any View = { EmptyView() }) { + self.actionItems = ActionItems(actionItems: actionItems) + } +} + +public extension ActivityItems { + init(actionItems: [ActivityItemDataType] = []) { + self.init(actionItems: { ActionItemsListStack(actionItems) }) + } +} + +public extension ActivityItems { + init(_ configuration: ActivityItemsConfiguration) { + self.init(configuration, shouldApplyDefaultStyle: false) + } + + internal init(_ configuration: ActivityItemsConfiguration, shouldApplyDefaultStyle: Bool) { + self.actionItems = configuration.actionItems + self._shouldApplyDefaultStyle = shouldApplyDefaultStyle + } +} + +extension ActivityItems: View { + public var body: some View { + if self._shouldApplyDefaultStyle { + self.defaultStyle() + } else { + self.style.resolve(configuration: .init(actionItems: .init(self.actionItems))).typeErased + .transformEnvironment(\.activityItemsStyleStack) { stack in + if !stack.isEmpty { + stack.removeLast() + } + } + } + } +} + +private extension ActivityItems { + func shouldApplyDefaultStyle(_ bool: Bool) -> some View { + var s = self + s._shouldApplyDefaultStyle = bool + return s + } + + func defaultStyle() -> some View { + ActivityItems(.init(actionItems: .init(self.actionItems))) + .shouldApplyDefaultStyle(false) + .activityItemsStyle(ActivityItemsFioriStyle.ContentFioriStyle()) + .typeErased + } +} diff --git a/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItemsStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItemsStyle.generated.swift new file mode 100644 index 000000000..a24f56cfe --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/StyleableComponents/ActivityItems/ActivityItemsStyle.generated.swift @@ -0,0 +1,35 @@ +// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import Foundation +import SwiftUI + +public protocol ActivityItemsStyle: DynamicProperty { + associatedtype Body: View + + func makeBody(_ configuration: ActivityItemsConfiguration) -> Body +} + +struct AnyActivityItemsStyle: ActivityItemsStyle { + let content: (ActivityItemsConfiguration) -> any View + + init(@ViewBuilder _ content: @escaping (ActivityItemsConfiguration) -> any View) { + self.content = content + } + + public func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + self.content(configuration).typeErased + } +} + +public struct ActivityItemsConfiguration { + public let actionItems: ActionItems + + public typealias ActionItems = ConfigurationViewWrapper +} + +public struct ActivityItemsFioriStyle: ActivityItemsStyle { + public func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + ActivityItems(configuration) + .actionItemsStyle(ActionItemsFioriStyle(activityItemsConfiguration: configuration)) + } +} diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift index 86dff0b7d..0668fd90e 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift @@ -115,6 +115,41 @@ public extension ActivityItemStyle where Self == ActivityItemSubtitleStyle { } } +// MARK: ActivityItemsStyle + +public extension ActivityItemsStyle where Self == ActivityItemsBaseStyle { + static var base: ActivityItemsBaseStyle { + ActivityItemsBaseStyle() + } +} + +public extension ActivityItemsStyle where Self == ActivityItemsFioriStyle { + static var fiori: ActivityItemsFioriStyle { + ActivityItemsFioriStyle() + } +} + +public struct ActivityItemsActionItemsStyle: ActivityItemsStyle { + let style: any ActionItemsStyle + + public func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + ActivityItems(configuration) + .actionItemsStyle(self.style) + .typeErased + } +} + +public extension ActivityItemsStyle where Self == ActivityItemsActionItemsStyle { + static func actionItemsStyle(_ style: some ActionItemsStyle) -> ActivityItemsActionItemsStyle { + ActivityItemsActionItemsStyle(style: style) + } + + static func actionItemsStyle(@ViewBuilder content: @escaping (ActionItemsConfiguration) -> some View) -> ActivityItemsActionItemsStyle { + let style = AnyActionItemsStyle(content) + return ActivityItemsActionItemsStyle(style: style) + } +} + // MARK: AllEntriesSectionTitleStyle public extension AllEntriesSectionTitleStyle where Self == AllEntriesSectionTitleBaseStyle { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift index 57433252a..191f29d52 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift @@ -108,6 +108,27 @@ extension EnvironmentValues { } } +// MARK: ActivityItemsStyle + +struct ActivityItemsStyleStackKey: EnvironmentKey { + static let defaultValue: [any ActivityItemsStyle] = [] +} + +extension EnvironmentValues { + var activityItemsStyle: any ActivityItemsStyle { + self.activityItemsStyleStack.last ?? .base.concat(.fiori) + } + + var activityItemsStyleStack: [any ActivityItemsStyle] { + get { + self[ActivityItemsStyleStackKey.self] + } + set { + self[ActivityItemsStyleStackKey.self] = newValue + } + } +} + // MARK: AllEntriesSectionTitleStyle struct AllEntriesSectionTitleStyleStackKey: EnvironmentKey { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift index efec6ecc3..18356a3d4 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift @@ -148,6 +148,34 @@ public extension ActivityItemStyle { } } +// MARK: ActivityItemsStyle + +extension ModifiedStyle: ActivityItemsStyle where Style: ActivityItemsStyle { + public func makeBody(_ configuration: ActivityItemsConfiguration) -> some View { + ActivityItems(configuration) + .activityItemsStyle(self.style) + .modifier(self.modifier) + } +} + +public struct ActivityItemsStyleModifier: ViewModifier { + let style: Style + + public func body(content: Content) -> some View { + content.activityItemsStyle(self.style) + } +} + +public extension ActivityItemsStyle { + func modifier(_ modifier: some ViewModifier) -> some ActivityItemsStyle { + ModifiedStyle(style: self, modifier: modifier) + } + + func concat(_ style: some ActivityItemsStyle) -> some ActivityItemsStyle { + style.modifier(ActivityItemsStyleModifier(style: self)) + } +} + // MARK: AllEntriesSectionTitleStyle extension ModifiedStyle: AllEntriesSectionTitleStyle where Style: AllEntriesSectionTitleStyle { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift index 8641adcd2..c025b0369 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift @@ -83,6 +83,22 @@ extension ActivityItemStyle { } } +// MARK: ActivityItemsStyle + +struct ResolvedActivityItemsStyle: View { + let style: Style + let configuration: ActivityItemsConfiguration + var body: some View { + self.style.makeBody(self.configuration) + } +} + +extension ActivityItemsStyle { + func resolve(configuration: ActivityItemsConfiguration) -> some View { + ResolvedActivityItemsStyle(style: self, configuration: configuration) + } +} + // MARK: AllEntriesSectionTitleStyle struct ResolvedAllEntriesSectionTitleStyle: View { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift index fa6bbe327..7350f25ca 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift @@ -88,6 +88,23 @@ public extension View { } } +// MARK: ActivityItemsStyle + +public extension View { + func activityItemsStyle(_ style: some ActivityItemsStyle) -> some View { + self.transformEnvironment(\.activityItemsStyleStack) { stack in + stack.append(style) + } + } + + func activityItemsStyle(@ViewBuilder content: @escaping (ActivityItemsConfiguration) -> some View) -> some View { + self.transformEnvironment(\.activityItemsStyleStack) { stack in + let style = AnyActivityItemsStyle(content) + stack.append(style) + } + } +} + // MARK: AllEntriesSectionTitleStyle public extension View { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift index 14caff301..47eba286e 100755 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift @@ -34,6 +34,12 @@ extension ActivityItem: _ViewEmptyChecking { } } +extension ActivityItems: _ViewEmptyChecking { + public var isEmpty: Bool { + actionItems.isEmpty + } +} + extension AllEntriesSectionTitle: _ViewEmptyChecking { public var isEmpty: Bool { allEntriesSectionTitle.isEmpty diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift index 6a0679362..208a2e3ea 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift @@ -96,13 +96,13 @@ extension ContactItem where Title == Text, Subtitle == _ConditionalContent, DescriptionText == _ConditionalContent, DetailImage == _ConditionalContent, - ActionItems == _ConditionalContent { + ActionItems == _ConditionalContent<_ActivityItems, EmptyView> { public init(model: ContactItemModel) { - self.init(title: model.title, subtitle: model.subtitle, descriptionText: model.descriptionText, detailImage: model.detailImage, actionItems: model.actionItems != nil ? ActivityItems(model: model.actionItems!) : nil) + self.init(title: model.title, subtitle: model.subtitle, descriptionText: model.descriptionText, detailImage: model.detailImage, actionItems: model.actionItems != nil ? _ActivityItems(model: model.actionItems!) : nil) } - public init(title: String, subtitle: String? = nil, descriptionText: String? = nil, detailImage: Image? = nil, actionItems: ActivityItems? = nil) { + public init(title: String, subtitle: String? = nil, descriptionText: String? = nil, detailImage: Image? = nil, actionItems: _ActivityItems? = nil) { self._title = Text(title) self._subtitle = subtitle != nil ? ViewBuilder.buildEither(first: Text(subtitle!)) : ViewBuilder.buildEither(second: EmptyView()) self._descriptionText = descriptionText != nil ? ViewBuilder.buildEither(first: Text(descriptionText!)) : ViewBuilder.buildEither(second: EmptyView()) diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift index c629f96c7..c683f6061 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift @@ -25,12 +25,12 @@ public struct ObjectHeader Void)? = nil - var allowsEmptySelection: Bool = false - @State var _searchText: String = "" - var updateSearchListPickerHeight: ((CGFloat) -> ())? = nil - var allowsDisplaySelectionCount: Bool = true + var isSearchBarHidden: Bool = false @State var _height: CGFloat = 44 - @State var _searchViewCornerRadius: CGFloat = 18 - var allowsMultipleSelection: Bool = false + @State var _keyboardHeight: CGFloat = 0.0 var disableListEntriesSection: Bool = false var barItemFrame: CGRect = .zero + var updateSearchListPickerHeight: ((CGFloat) -> ())? = nil var selectAll: ((Bool) -> ())? = nil - var isSearchBarHidden: Bool = false - @State var _keyboardHeight: CGFloat = 0.0 + @State var _searchViewCornerRadius: CGFloat = 18 + var allowsDisplaySelectionCount: Bool = true + var allowsMultipleSelection: Bool = false + var allowsEmptySelection: Bool = false + @State var _searchText: String = "" let popoverWidth = 393.0 public init(model: SearchListPickerItemModel) { self.init(value: Binding<[Int]>(get: { model.value }, set: { model.value = $0 }), valueOptions: model.valueOptions, hint: model.hint, onTap: model.onTap) diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift index 3bd73cd1c..daa840df6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift @@ -20,35 +20,35 @@ public struct SignatureCaptureView Void)? let _onDelete: (() -> Void)? - var indicatorColor = Color.preferredColor(.primaryLabel) - @State var isSaved = false - var appliesTintColorToImage = true - var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) - var indicatorFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) - @State var currentDrawing = Drawing() + var addsTimestampInImage: Bool = false + @State var isReenterTapped = false + var strokeWidth: CGFloat = 3.0 let _drawingViewMinHeight: CGFloat = 256 - var signatureLineColor = Color.preferredColor(.quaternaryLabel) - @State var drawings = [Drawing]() - var timestampFormatter: DateFormatter? - var watermarkTextColor: Color = .preferredColor(.tertiaryLabel) - var titleFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) - var hidesXmark = false - var hidesSignatureLine = false + var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) + var titleColor = Color.preferredColor(.primaryLabel) + var _drawingViewMaxHeight: CGFloat? var cropsImage = false - @State var isReenterTapped = false + var titleFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) var isRequired = false + var strokeColor = Color.preferredColor(.primaryLabel) var xmarkColor = Color.preferredColor(.quaternaryLabel) + var watermarkTextColor: Color = .preferredColor(.tertiaryLabel) + var signatureLineColor = Color.preferredColor(.quaternaryLabel) @State var fullSignatureImage: UIImage? - var strokeWidth: CGFloat = 3.0 - var addsTimestampInImage: Bool = false - var watermarkText: String? + @State var isEditing = false + var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) + @State var drawings = [Drawing]() var watermarkTextAlignment: NSTextAlignment = .natural - var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) - var titleColor = Color.preferredColor(.primaryLabel) - var _drawingViewMaxHeight: CGFloat? + var indicatorFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) public private(set) var _heightDidChangePublisher = CurrentValueSubject(0) - @State var isEditing = false - var strokeColor = Color.preferredColor(.primaryLabel) + var hidesXmark = false + @State var currentDrawing = Drawing() + var hidesSignatureLine = false + var appliesTintColorToImage = true + var indicatorColor = Color.preferredColor(.primaryLabel) + @State var isSaved = false + var timestampFormatter: DateFormatter? + var watermarkText: String? private var isModelInit: Bool = false private var isTitleNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift index f6c4a594b..f38dd531e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift @@ -16,9 +16,9 @@ public struct SortFilterView Void)? + @StateObject var context: SortFilterContext = SortFilterContext() let popoverWidth = 393.0 @State var size: CGSize = .zero - @StateObject var context: SortFilterContext = SortFilterContext() private var isModelInit: Bool = false private var isCancelActionNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ActivityItems+API.generated.swift similarity index 89% rename from Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift rename to Sources/FioriSwiftUICore/_generated/ViewModels/API/_ActivityItems+API.generated.swift index 01a2374e2..669a401fd 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ActivityItems+API.generated.swift @@ -2,13 +2,13 @@ // DO NOT EDIT import SwiftUI -public struct ActivityItems { +public struct _ActivityItems { @Environment(\.actionItemsModifier) private var actionItemsModifier var _actionItems: [ActivityItemDataType]? = nil var _didSelectActivityItem: ((ActivityItemDataType) -> Void)? = nil - public init(model: ActivityItemsModel) { + public init(model: _ActivityItemsModel) { self.init(actionItems: model.actionItems, didSelectActivityItem: model.didSelectActivityItem) } diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift index 63bdfd7b2..79bb7ae41 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift @@ -14,15 +14,15 @@ public struct _SingleStep + } +} + +// FIXME: - Implement _ActivityItems specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct _ActivityItemsLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(_ActivityItems(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift index dbea04dc7..d1ad2b3f0 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift @@ -3,7 +3,7 @@ import SwiftUI public extension ContactItemModel { - var actionItems: ActivityItemsModel? { + var actionItems: _ActivityItemsModel? { return nil } } diff --git a/sourcery/.lib/Sources/utils/Type+Extensions.swift b/sourcery/.lib/Sources/utils/Type+Extensions.swift index 2ea7c67f0..e6a0dce06 100644 --- a/sourcery/.lib/Sources/utils/Type+Extensions.swift +++ b/sourcery/.lib/Sources/utils/Type+Extensions.swift @@ -74,6 +74,7 @@ public extension Type { "_SideBarModel", "_SideBarListItemModel", "_ActivityItemModel", + "_ActivityItemsModel", "_ProgressIndicatorModel", "_SingleStepModel", "_StepProgressIndicatorModel"]