diff --git a/Apps/Examples/Examples.xcodeproj/project.pbxproj b/Apps/Examples/Examples.xcodeproj/project.pbxproj index 2df31c478..22fae1363 100644 --- a/Apps/Examples/Examples.xcodeproj/project.pbxproj +++ b/Apps/Examples/Examples.xcodeproj/project.pbxproj @@ -100,6 +100,8 @@ B8D4376F25F980340024EE7D /* ObjectCell_Spec_Jan2018.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D4376E25F980340024EE7D /* ObjectCell_Spec_Jan2018.swift */; }; B8D4377125F983730024EE7D /* ObjectCell_Rules_Alignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D4377025F983730024EE7D /* ObjectCell_Rules_Alignment.swift */; }; B8D437732609479E0024EE7D /* SingleActionFollowButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D437722609479E0024EE7D /* SingleActionFollowButton.swift */; }; + C1A0FDB32AD893FA0001738E /* SortFilterView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1A0FDB22AD893FA0001738E /* SortFilterView+Extensions.swift */; }; + C1C764882A818BEC00BCB0F7 /* SortFilterExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1C764872A818BEC00BCB0F7 /* SortFilterExample.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -240,6 +242,8 @@ B8D4376E25F980340024EE7D /* ObjectCell_Spec_Jan2018.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectCell_Spec_Jan2018.swift; sourceTree = ""; }; B8D4377025F983730024EE7D /* ObjectCell_Rules_Alignment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObjectCell_Rules_Alignment.swift; sourceTree = ""; }; B8D437722609479E0024EE7D /* SingleActionFollowButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleActionFollowButton.swift; sourceTree = ""; }; + C1A0FDB22AD893FA0001738E /* SortFilterView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SortFilterView+Extensions.swift"; sourceTree = ""; }; + C1C764872A818BEC00BCB0F7 /* SortFilterExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortFilterExample.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -423,6 +427,7 @@ 8A5579C824C1293C0098003A /* FioriSwiftUICore */ = { isa = PBXGroup; children = ( + C1C764862A818BD600BCB0F7 /* SortFilter */, B100639129C0623300AF0CA2 /* StepProgressIndicator */, 108E43D3292DAB3E006532F3 /* EmptyStateView */, B1D41B1E291A2D2E004E64A5 /* Picker */, @@ -575,6 +580,15 @@ path = ObjectItem; sourceTree = ""; }; + C1C764862A818BD600BCB0F7 /* SortFilter */ = { + isa = PBXGroup; + children = ( + C1C764872A818BEC00BCB0F7 /* SortFilterExample.swift */, + C1A0FDB22AD893FA0001738E /* SortFilterView+Extensions.swift */, + ); + path = SortFilter; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -728,6 +742,7 @@ 8A557A2424C12F380098003A /* ChartDetailView.swift in Sources */, 8A5579D024C1293C0098003A /* SettingsLine.swift in Sources */, 1FC30412270540FB004BEE00 /* 72-Fonts.swift in Sources */, + C1A0FDB32AD893FA0001738E /* SortFilterView+Extensions.swift in Sources */, B84D24ED2652F343007F2373 /* HeaderChartExample.swift in Sources */, B100639329C0624D00AF0CA2 /* StepProgressIndicatorExample.swift in Sources */, B846F94626815CC90085044B /* ContactItemExample.swift in Sources */, @@ -777,6 +792,7 @@ 8A5579D524C1293C0098003A /* SettingsSeries.swift in Sources */, 8A557A2224C12C9B0098003A /* CoreContentView.swift in Sources */, 8A5579D224C1293C0098003A /* Color+Extensions.swift in Sources */, + C1C764882A818BEC00BCB0F7 /* SortFilterExample.swift in Sources */, B84D24EF2652F343007F2373 /* ObjectHeaderTestApp.swift in Sources */, B84D24EC2652F343007F2373 /* ObjectHeaderSpecCompact.swift in Sources */, 8A5579CD24C1293C0098003A /* SettingsLabel.swift in Sources */, @@ -920,7 +936,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -975,7 +991,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -995,7 +1011,7 @@ DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Examples/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1017,7 +1033,7 @@ DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; INFOPLIST_FILE = Examples/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 16.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift b/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift index fcf70c39e..91545232c 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/CoreContentView.swift @@ -107,6 +107,10 @@ struct CoreContentView: View { destination: EmptyStateViewExample()) { Text("EmptyStateViewExample") } + + NavigationLink(destination: SortFilterExample()) { + Text("SortFilterExample") + } } }.navigationBarTitle("FioriSwiftUICore") } diff --git a/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterExample.swift b/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterExample.swift new file mode 100644 index 000000000..bbd4f5835 --- /dev/null +++ b/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterExample.swift @@ -0,0 +1,110 @@ +import FioriSwiftUICore +import SwiftUI + +struct SortFilterExample: View { + @State private var items: [[SortFilterItem]] = [ + [ + .switch(item: .init(name: "Favorite", value: true, icon: "heart.fill"), showsOnFilterFeedbackBar: true), + .switch(item: .init(name: "Tagged", value: nil, icon: "tag"), showsOnFilterFeedbackBar: false), + .picker(item: .init(name: "JIRA Status", value: [0], valueOptions: ["Received", "Started", "Hold", "Transfer", "Completed", "Pending Review", "Accepted", "Rejected"], allowsMultipleSelection: true, allowsEmptySelection: true, icon: "clock"), showsOnFilterFeedbackBar: true) + ], + [ + .picker(item: .init(name: "Priority", value: [0], valueOptions: ["High", "Medium", "Low"], allowsMultipleSelection: true, allowsEmptySelection: true, icon: "filemenu.and.cursorarrow"), showsOnFilterFeedbackBar: true), + .filterfeedback(item: .init(name: "Sort Order", value: [0], valueOptions: ["Ascending", "Descending"], allowsMultipleSelection: false, allowsEmptySelection: false, icon: "checkmark")) + ], + [ + .slider(item: .init(name: "User Stories", value: 10, minimumValue: 0, maximumValue: 100, formatter: "%2d Stories", icon: "number"), showsOnFilterFeedbackBar: true), + .slider(item: .init(name: "Number of Tasks", value: nil, minimumValue: 0, maximumValue: 100), showsOnFilterFeedbackBar: true), + .datetime(item: .init(name: "Start Date", value: Date(), formatter: "yyyy-MM-dd HH:mm",icon: "calendar"), showsOnFilterFeedbackBar: true) + ], + [ + .datetime(item: .init(name: "Completion Date", value: nil), showsOnFilterFeedbackBar: true) + ] + ] + + @State private var isShowingFullCFG: Bool = false + @State private var isCustomStyle: Bool = false + @State private var sortFilterList: [String] = [] + @State private var sortFilterButtonLabel: String = "Sort & Filter" + + var body: some View { + VStack { + if isCustomStyle { + FilterFeedbackBar(items: $items, onUpdate: performSortAndFilter) + .filterFeedbackBarStyle(font: .subheadline, foregroundColorSelected: .red, strokeColorSelected: .red, cornerRadius: 25) + .optionListPickerStyle(font: .footnote, foregroundColorUnselected: .green, strokeColorSelected: .black) +// .trailingFullConfigurationMenuItem(icon: "command") +// .leadingFullConfigurationMenuItem(icon: "command") +// .leadingFullConfigurationMenuItem(name: "All") + } else { + FilterFeedbackBar(items: $items, onUpdate: performSortAndFilter) + } + + List { + ForEach(sortFilterList, id: \.self) { line in + Text(line) + } + } + .listStyle(PlainListStyle()) + + HStack { + Toggle("Custom Style", isOn: $isCustomStyle) + .fixedSize() + .toggleStyle(FioriToggleStyle()) + + Button("Print") { + for line in sortFilterList { + print(line) + } + } + } + } + .navigationTitle("Sort & Filter") + .toolbar { + Button(sortFilterButtonLabel) { + isShowingFullCFG.toggle() + } + .popover(isPresented: $isShowingFullCFG, arrowEdge: .leading) { + if isCustomStyle { + SortFilterView( + title: "Configuration", + items: $items, + onUpdate: performSortAndFilter + ) + .optionListPickerStyle(font: .footnote, foregroundColorUnselected: .green, strokeColorSelected: .black) + } else { + SortFilterView( + title: "Configuration", + items: $items, + onUpdate: performSortAndFilter + ) + } + } + } + .onAppear { + performSortAndFilter() + } + } + + func numberOfItems() -> Int { + // randomly padding result to mimic impact of filterring + for i in 0 ... Int.random(in: 0 ... 5) { + self.sortFilterList.append("padding element \(i + 1)") + } + return self.sortFilterList.count + } + + func performSortAndFilter() { + self.sortFilterList = self.items.joined().map { value(of: $0) } + self.sortFilterButtonLabel = "CFG (\(self.numberOfItems()))" + } +} + +#if DEBUG + @available(iOS 16.0, *) + struct SortFilterExample_Previews: PreviewProvider { + static var previews: some View { + SortFilterExample() + } + } +#endif diff --git a/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterView+Extensions.swift b/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterView+Extensions.swift new file mode 100644 index 000000000..42b7dd3c4 --- /dev/null +++ b/Apps/Examples/Examples/FioriSwiftUICore/SortFilter/SortFilterView+Extensions.swift @@ -0,0 +1,35 @@ +import FioriSwiftUICore +import SwiftUI + +extension View { + func value(of item: SortFilterItem) -> String { + switch item { + case .picker(let v, _): + return self.json(item: v) + case .filterfeedback(let v): + return self.json(item: v) + case .slider(let v, _): + return self.json(item: v) + case .datetime(let v, _): + return self.json(item: v) + case .switch(let v, _): + return self.json(item: v) + } + } + + func json(item: SortFilterItem.PickerItem) -> String { + "{name: \(item.name), value: \(item.value)}" + } + + func json(item: SortFilterItem.SliderItem) -> String { + "{name: \(item.name), value: \(String(describing: item.value))}" + } + + func json(item: SortFilterItem.DateTimeItem) -> String { + "{name: \(item.name), value: \(String(describing: item.value))}" + } + + func json(item: SortFilterItem.SwitchItem) -> String { + "{name: \(item.name), value: \(String(describing: item.value))}" + } +} diff --git a/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/Contents.json b/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/Contents.json new file mode 100644 index 000000000..2945b36b9 --- /dev/null +++ b/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/icon.png b/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/icon.png new file mode 100644 index 000000000..d91dd8e60 Binary files /dev/null and b/Apps/Examples/Examples/Preview Content/Preview Assets.xcassets/iconfromapp.imageset/icon.png differ diff --git a/Package.swift b/Package.swift index 0b4374da2..48162e04b 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "FioriSwiftUI", defaultLocalization: "en", - platforms: [.iOS(.v15), .watchOS(.v7)], + platforms: [.iOS(.v16), .watchOS(.v7)], products: [ .library( name: "FioriSwiftUI", diff --git a/Sources/FioriSwiftUICore/Components/CancellableResettableForm.swift b/Sources/FioriSwiftUICore/Components/CancellableResettableForm.swift new file mode 100644 index 000000000..f79dd2adb --- /dev/null +++ b/Sources/FioriSwiftUICore/Components/CancellableResettableForm.swift @@ -0,0 +1,130 @@ +import Foundation +import SwiftUI + +struct CancellableResettableDialogForm: View { + let title: Title + + let components: Components + + var cancelAction: CancelAction + var resetAction: ResetAction + var applyAction: ApplyAction + + public init(@ViewBuilder title: () -> Title, + @ViewBuilder cancelAction: () -> CancelAction, + @ViewBuilder resetAction: () -> ResetAction, + @ViewBuilder applyAction: () -> ApplyAction, + @ViewBuilder components: () -> Components) + { + self.title = title() + self.cancelAction = cancelAction() + self.resetAction = resetAction() + self.applyAction = applyAction() + self.components = components() + } + + var body: some View { + VStack(spacing: UIDevice.current.userInterfaceIdiom == .pad ? 8 : 16) { + HStack { + cancelAction + Spacer() + title + Spacer() + resetAction + } + .padding([.leading, .trailing], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16) + + components + applyAction + } + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375: UIScreen.main.bounds.size.width) + .padding([.top, .bottom], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16) + } +} + +struct ApplyButtonStyle: PrimitiveButtonStyle { + @Environment(\.isEnabled) private var isEnabled: Bool + + func makeBody(configuration: Configuration) -> some View { + if isEnabled { + configuration.label + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 : + UIScreen.main.bounds.size.width - 16 * 2) + .padding([.top, .bottom], 8) + .font(.body) + .fontWeight(.bold) + .foregroundStyle(Color.preferredColor(.base2)) + .background(RoundedRectangle(cornerRadius: 8).fill(Color.preferredColor(.tintColor))) + .onTapGesture { + configuration.trigger() + } + .padding([.top], UIDevice.current.userInterfaceIdiom == .pad ? 16 : 8) + } else { + configuration.label + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 : + UIScreen.main.bounds.size.width - 16 * 2) + .padding([.top, .bottom], 8) + .font(.body) + .fontWeight(.bold) + .foregroundStyle(Color.preferredColor(.grey1)) + .background(RoundedRectangle(cornerRadius: 8).fill(Color.preferredColor(.grey5))) + .padding([.top], UIDevice.current.userInterfaceIdiom == .pad ? 16 : 8) + } + } +} + +struct CancelButtonStyle: PrimitiveButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .font(.body) + .fontWeight(.bold) + .foregroundStyle(Color.preferredColor(.tintColor)) + .onTapGesture { + configuration.trigger() + } + } +} + +struct ResetButtonStyle: PrimitiveButtonStyle { + @Environment(\.isEnabled) private var isEnabled: Bool + + func makeBody(configuration: Configuration) -> some View { + if isEnabled { + configuration.label + .font(.body) + .fontWeight(.bold) + .foregroundStyle(Color.preferredColor(.tintColor)) + .onTapGesture { + configuration.trigger() + } + } else { + configuration.label + .font(.body) + .fontWeight(.bold) + .foregroundStyle(Color.preferredColor(.separator)) + } + } +} + +#Preview { + VStack { + Spacer() + CancellableResettableDialogForm { + Text("Date of Completion") + } cancelAction: { + Action(actionText: "Cancel", didSelectAction: nil) + } resetAction: { + Action(actionText: "Reset", didSelectAction: nil) + } applyAction: { + Action(actionText: "Apply", didSelectAction: nil) + .buttonStyle(ApplyButtonStyle()) + } components: { + DatePicker( + "date", + selection: Binding(get: { Date() }, set: { print($0) }), + displayedComponents: [.date] + ) + .datePickerStyle(.graphical) + } + } +} diff --git a/Sources/FioriSwiftUICore/Components/MultiPropertyComponents.swift b/Sources/FioriSwiftUICore/Components/MultiPropertyComponents.swift index 14215991d..a2d135c86 100644 --- a/Sources/FioriSwiftUICore/Components/MultiPropertyComponents.swift +++ b/Sources/FioriSwiftUICore/Components/MultiPropertyComponents.swift @@ -53,3 +53,52 @@ internal protocol _DurationPicker: _ComponentMultiPropGenerating, AnyObject { // sourcery: default.value = MeasurementFormatter() var measurementFormatter: MeasurementFormatter { get set } } + +internal protocol _SliderPicker: _ComponentMultiPropGenerating, AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: Int? { get set } + + // sourcery: no_view + // sourcery: default.value = nil + var formatter: String? { get } + + // sourcery: no_view + // sourcery: default.value = 0.0 + var minimumValue: Int { get } + + // sourcery: no_view + // sourcery: default.value = 100.0 + var maximumValue: Int { get } + + // sourcery: no_view + // sourcery: default.value = nil + var hint: String? { get } +} + +internal protocol _SwitchPicker: _ComponentMultiPropGenerating, AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: Bool? { get set } + + // sourcery: no_view + // sourcery: default.value = nil + var name: String? { get } + + // sourcery: no_view + // sourcery: default.value = nil + var hint: String? { get } +} + +internal protocol _OptionListPicker: _ComponentMultiPropGenerating, AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: [Int] { get set } + + // sourcery: no_view + var valueOptions: [String] { get } + + // sourcery: no_view + // sourcery: default.value = nil + var hint: String? { get } +} diff --git a/Sources/FioriSwiftUICore/Components/SinglePropertyComponents.swift b/Sources/FioriSwiftUICore/Components/SinglePropertyComponents.swift index e9731f208..2020a4b4b 100644 --- a/Sources/FioriSwiftUICore/Components/SinglePropertyComponents.swift +++ b/Sources/FioriSwiftUICore/Components/SinglePropertyComponents.swift @@ -51,4 +51,6 @@ internal struct _Component: _ComponentGenerating { // sourcery: backingComponent=FootnoteIconStack // sourcery: customFunctionBuilder=FootnoteIconsBuilder let footnoteIcons_: [TextOrIcon]? + let leftIcon_: Image? + let rightIcon_: Image? } diff --git a/Sources/FioriSwiftUICore/DataTypes/SortFilter+DataType.swift b/Sources/FioriSwiftUICore/DataTypes/SortFilter+DataType.swift new file mode 100644 index 000000000..a20c126e1 --- /dev/null +++ b/Sources/FioriSwiftUICore/DataTypes/SortFilter+DataType.swift @@ -0,0 +1,581 @@ +import SwiftUI +import UIKit + +/// UI control types supporeted by Sort and Filter configuraiton +public enum SortFilterItem: Identifiable, Hashable { + /// :nodoc: + public var id: String { + switch self { + case .picker(let item, _): + return item.id + case .filterfeedback(let item): + return item.id + case .switch(let item, _): + return item.id + case .slider(let item, _): + return item.id + case .datetime(let item, _): + return item.id + } + } + + /// The type of UI control is used to buid: + /// + /// 1. Sort & Filter's menu item associating with sub-menu items when the number of selectable options is less than 8, + /// or a popover containing a collection of selectable buttons when the number of selectable options is greater than 7. + /// + /// 2. A section of view containing a collection of selectable buttons + case picker(item: PickerItem, showsOnFilterFeedbackBar: Bool) + + /// The type of UI control is used to buid: + /// + /// 1. Sort & Filter's menu items associated with one and another; the number of selectable items, mutual exclusion, and + /// empty selection can be controlled + /// + /// 2. A section of view containing a collection of selectable buttons + /// + /// Note: `filterfeedback` is alwasy to be shown on menu bar + case filterfeedback(item: PickerItem) + + /// The type of UI control is used to buid: + /// + /// 1. Sort & Filter's menu item to be toggled between selected and unselected states + /// + /// 2. A section of view containing a SwiftUI Toggle with Fiori style + case `switch`(item: SwitchItem, showsOnFilterFeedbackBar: Bool) + + /// The type of UI control is used to buid: + /// + /// 1. Sort & Filter's menu item associated with a popover containing a SwiftUI Toggle with Fiori style + /// + /// 2. A section of view containing a SwiftUI Toggle with Fiori style + case slider(item: SliderItem, showsOnFilterFeedbackBar: Bool) + + /// The type of UI control is used to buid: + /// + /// 1. Sort & Filter's menu item associated with a popover containing a SwiftUI Canlendar + /// + /// 2. A section of view containing a SwiftUI Canlendar + case datetime(item: DateTimeItem, showsOnFilterFeedbackBar: Bool) + + public var showsOnFilterFeedbackBar: Bool { + switch self { + case .picker(_, let showsOnFilterFeedbackBar): + return showsOnFilterFeedbackBar + case .filterfeedback: + return true + case .switch(_, let showsOnFilterFeedbackBar): + return showsOnFilterFeedbackBar + case .slider(_, let showsOnFilterFeedbackBar): + return showsOnFilterFeedbackBar + case .datetime(_, let showsOnFilterFeedbackBar): + return showsOnFilterFeedbackBar + } + } + + /// :nodoc: + public func hash(into hasher: inout Hasher) { + switch self { + case .picker(let item, _): + hasher.combine(item.id) + hasher.combine(item.originalValue) + hasher.combine(item.workingValue) + hasher.combine(item.value) + case .filterfeedback(let item): + hasher.combine(item.id) + hasher.combine(item.originalValue) + hasher.combine(item.workingValue) + hasher.combine(item.value) + case .switch(let item, _): + hasher.combine(item.id) + hasher.combine(item.originalValue) + hasher.combine(item.workingValue) + hasher.combine(item.value) + case .slider(let item, _): + hasher.combine(item.id) + hasher.combine(item.originalValue) + hasher.combine(item.workingValue) + hasher.combine(item.value) + case .datetime(let item, _): + hasher.combine(item.id) + hasher.combine(item.originalValue) + hasher.combine(item.workingValue) + hasher.combine(item.value) + } + } +} + +extension SortFilterItem { + var picker: PickerItem { + get { + switch self { + case .picker(let item, _): + return item + default: + fatalError("Unexpected value \(self)") + } + } + + set { + switch self { + case .picker(_, let showsOnFilterFeedbackBar): + self = .picker(item: newValue, showsOnFilterFeedbackBar: showsOnFilterFeedbackBar) + default: + fatalError("Unexpected value \(self)") + } + } + } + + var filterfeedback: PickerItem { + get { + switch self { + case .filterfeedback(let item): + return item + default: + fatalError("Unexpected value \(self)") + } + } + + set { + switch self { + case .filterfeedback: + self = .filterfeedback(item: newValue) + default: + fatalError("Unexpected value \(self)") + } + } + } + + var slider: SliderItem { + get { + switch self { + case .slider(let item, _): + return item + default: + fatalError("Unexpected value \(self)") + } + } + + set { + switch self { + case .slider(_, let showsOnFilterFeedbackBar): + self = .slider(item: newValue, showsOnFilterFeedbackBar: showsOnFilterFeedbackBar) + default: + fatalError("Unexpected value \(self)") + } + } + } + + var datetime: DateTimeItem { + get { + switch self { + case .datetime(let item, _): + return item + default: + fatalError("Unexpected value \(self)") + } + } + + set { + switch self { + case .datetime(_, let showsOnFilterFeedbackBar): + self = .datetime(item: newValue, showsOnFilterFeedbackBar: showsOnFilterFeedbackBar) + default: + fatalError("Unexpected value \(self)") + } + } + } + + var `switch`: SwitchItem { + get { + switch self { + case .switch(let item, _): + return item + default: + fatalError("Unexpected value \(self)") + } + } + + set { + switch self { + case .switch(_, let showsOnFilterFeedbackBar): + self = .switch(item: newValue, showsOnFilterFeedbackBar: showsOnFilterFeedbackBar) + default: + fatalError("Unexpected value \(self)") + } + } + } + + var isChanged: Bool { + switch self { + case .picker(let item, _): + return item.isChanged + case .filterfeedback(let item): + return item.isChanged + case .switch(let item, _): + return item.isChanged + case .datetime(let item, _): + return item.isChanged + case .slider(let item, _): + return item.isChanged + } + } + + var isOriginal: Bool { + switch self { + case .picker(let item, _): + return item.isOriginal + case .filterfeedback(let item): + return item.isOriginal + case .switch(let item, _): + return item.isOriginal + case .datetime(let item, _): + return item.isOriginal + case .slider(let item, _): + return item.isOriginal + } + } + + mutating func cancel() { + switch self { + case .picker(var item, _): + item.cancel() + self.picker = item + case .filterfeedback(var item): + item.cancel() + self.filterfeedback = item + case .switch(var item, _): + item.cancel() + self.switch = item + case .datetime(var item, _): + item.cancel() + self.datetime = item + case .slider(var item, _): + item.cancel() + self.slider = item + } + } + + mutating func reset() { + switch self { + case .picker(var item, _): + item.reset() + self.picker = item + case .filterfeedback(var item): + item.reset() + self.filterfeedback = item + case .switch(var item, _): + item.reset() + self.switch = item + case .datetime(var item, _): + item.reset() + self.datetime = item + case .slider(var item, _): + item.reset() + self.slider = item + } + } + + mutating func apply() { + switch self { + case .picker(var item, _): + item.apply() + self.picker = item + case .filterfeedback(var item): + item.apply() + self.filterfeedback = item + case .switch(var item, _): + item.apply() + self.switch = item + case .datetime(var item, _): + item.apply() + self.datetime = item + case .slider(var item, _): + item.apply() + self.slider = item + } + } +} + +extension SortFilterItem { + /// Data structure for filter feedback, option list picker, + public struct PickerItem: Identifiable, Equatable { + public let id: String + public var name: String + public var value: [Int] + public var workingValue: [Int] + let originalValue: [Int] + + var valueOptions: [String] + public let allowsMultipleSelection: Bool + public let allowsEmptySelection: Bool + public let icon: String? + + public init(id: String = UUID().uuidString, name: String, value: [Int], valueOptions: [String], allowsMultipleSelection: Bool, allowsEmptySelection: Bool, icon: String? = nil) { + self.id = id + self.name = name + self.value = value + self.workingValue = value + self.originalValue = value + self.valueOptions = valueOptions + self.allowsMultipleSelection = allowsMultipleSelection + self.allowsEmptySelection = allowsEmptySelection + self.icon = icon + } + + mutating func onTap(option: String) { + guard let index = valueOptions.firstIndex(of: option) else { return } + if self.workingValue.contains(index) { + if self.workingValue.count > 1 { + self.workingValue = self.workingValue.filter { $0 != index } + } else { + if self.allowsEmptySelection { + self.workingValue = [] + } else { + self.workingValue = index == 1 ? [0] : [1] + } + } + } else { + if self.allowsMultipleSelection { + self.workingValue.append(index) + } else { + self.workingValue = [index] + } + } + } + + mutating func optionOnTap(_ index: Int) { + if self.workingValue.contains(index) { + if self.workingValue.count > 1 { + self.workingValue = self.workingValue.filter { $0 != index } + } else { + if self.allowsEmptySelection { + self.workingValue = [] + } else { + self.workingValue = index == 1 ? [0] : [1] + } + } + } else { + if self.allowsMultipleSelection { + self.workingValue.append(index) + } else { + self.workingValue = [index] + } + } + } + + mutating func cancel() { + self.workingValue = self.value.map { $0 } + } + + mutating func reset() { + self.workingValue = self.originalValue.map { $0 } + } + + mutating func apply() { + self.value = self.workingValue.map { $0 } + } + + func isOptionSelected(_ option: String) -> Bool { + guard let idx = valueOptions.firstIndex(of: option) else { return false } + return self.workingValue.contains(idx) + } + + func isOptionSelected(index: Int) -> Bool { + self.workingValue.contains(index) + } + + var isChecked: Bool { + !self.value.isEmpty + } + + var label: String { + if allowsMultipleSelection && self.value.count >= 1 { + if self.value.count == 1 { + return valueOptions[value[0]] + } else { + return "\(self.name) (\(self.value.count))" + } + } else { + return self.name + } + } + + var isChanged: Bool { + self.value != self.workingValue + } + + var isOriginal: Bool { + self.workingValue == self.originalValue + } + } + + /// Data structure for boolean type + public struct SwitchItem: Identifiable, Equatable { + public var id: String + public var name: String + public var value: Bool? + var workingValue: Bool? + let originalValue: Bool? + public let icon: String? + public let hint: String? + + public init(id: String = UUID().uuidString, name: String, value: Bool?, icon: String? = nil, hint: String? = nil) { + self.id = id + self.name = name + self.value = value + self.workingValue = value + self.originalValue = value + self.icon = icon + self.hint = hint + } + + mutating func reset() { + self.workingValue = self.originalValue + } + + mutating func cancel() { + self.workingValue = self.value + } + + mutating func apply() { + self.value = self.workingValue + } + + var isChecked: Bool { + self.value ?? false + } + + var isChanged: Bool { + self.value != self.workingValue + } + + var isOriginal: Bool { + self.workingValue == self.originalValue + } + } + + /// Data structure for integer type slider + public struct SliderItem: Identifiable, Equatable { + public let id: String + public var name: String + public var value: Int? + var workingValue: Int? + let originalValue: Int? + public let minimumValue: Int + public let maximumValue: Int + let formatter: String? + public let icon: String? + public let hint: String? + + public init(id: String = UUID().uuidString, name: String, value: Int? = nil, minimumValue: Int, maximumValue: Int, formatter: String? = nil, icon: String? = nil, hint: String? = nil) { + self.id = id + self.name = name + self.value = value + self.workingValue = value + self.originalValue = value + self.minimumValue = minimumValue + self.maximumValue = maximumValue + self.formatter = formatter + self.icon = icon + self.hint = hint + } + + mutating func reset() { + self.workingValue = self.originalValue + } + + mutating func cancel() { + self.workingValue = self.value + } + + mutating func apply() { + self.value = self.workingValue + } + + var isChecked: Bool { + self.value != nil + } + + var label: String { + if let value = self.value { + return "\(name): \(value)" + } + return name + } + + mutating func setValue(newValue: SliderItem) { + self.value = newValue.value + } + + var isChanged: Bool { + self.value != self.workingValue + } + + var isOriginal: Bool { + self.workingValue == self.originalValue + } + } + + /// Data structure for datetime data + public struct DateTimeItem: Equatable, Hashable { + public let id: String + public var name: String + public var value: Date? + var workingValue: Date? + let originalValue: Date? + public var icon: String? + public let formatter: String? + + public init(id: String = UUID().uuidString, name: String, value: Date?, formatter: String? = nil, icon: String? = nil) { + self.id = id + self.name = name + self.value = value + self.workingValue = value + self.originalValue = value + self.formatter = formatter + self.icon = icon + } + + mutating func reset() { + self.workingValue = self.originalValue + } + + mutating func apply() { + self.value = self.workingValue + } + + mutating func cancel() { + self.workingValue = self.value + } + + var isChecked: Bool { + self.value != nil + } + + var label: String { + if let value = self.value { + if let format = self.formatter { + let formatter = DateFormatter() + formatter.dateFormat = format + return formatter.string(from: value) + } else { + let dateFormatter: DateFormatter = DateFormatter() + dateFormatter.dateStyle = .long + dateFormatter.timeStyle = .short + return dateFormatter.string(from: value) + } + } else { + return self.name + } + } + + var isChanged: Bool { + self.value != self.workingValue + } + + var isOriginal: Bool { + self.workingValue == self.originalValue + } + } +} diff --git a/Sources/FioriSwiftUICore/Models/DefaultViewModels.swift b/Sources/FioriSwiftUICore/Models/DefaultViewModels.swift index 420d1ad11..7c615eecb 100644 --- a/Sources/FioriSwiftUICore/Models/DefaultViewModels.swift +++ b/Sources/FioriSwiftUICore/Models/DefaultViewModels.swift @@ -24,6 +24,22 @@ public struct _CancelActionDefault: ActionModel { public init() {} } +public struct _ResetActionDefault: ActionModel { + public var actionText: String? { + NSLocalizedString("Reset", tableName: "FioriSwiftUICore", bundle: fioriSwiftUICoreBundle, comment: "") + } + + public init() {} +} + +public struct _ApplyActionDefault: ActionModel { + public var actionText: String? { + NSLocalizedString("Apply", tableName: "FioriSwiftUICore", bundle: fioriSwiftUICoreBundle, comment: "") + } + + public init() {} +} + public struct _AgreeActionDefault: ActionModel { public var actionText: String? { NSLocalizedString("Agree", tableName: "FioriSwiftUICore", bundle: fioriSwiftUICoreBundle, comment: "") diff --git a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift index 41941e396..ad863eb5f 100644 --- a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift +++ b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift @@ -433,3 +433,71 @@ public protocol StepProgressIndicatorModel: AnyObject { // sourcery: default.value = _CancelActionDefault() var cancelAction: ActionModel? { get } } + +// sourcery: generated_component_composite +public protocol FilterFeedbackBarModel: AnyObject { + // sourcery: bindingProperty + // sourcery: backingComponent=_SortFilterMenuItemContainer + var items: [[SortFilterItem]] { get set } + + // sourcery: default.value = nil + // sourcery: no_view + var onUpdate: (() -> Void)? { get set } +} + +// sourcery: virtualPropActionHelper = "@StateObject var context: SortFilterContext = SortFilterContext()" +// sourcery: add_env_props = "dismiss" +// sourcery: generated_component_composite +public protocol SortFilterViewModel: AnyObject, TitleComponent { + // sourcery: bindingProperty + // sourcery: backingComponent=_SortFilterCFGItemContainer + var items: [[SortFilterItem]] { get set } + + // sourcery: genericParameter.name = CancelActionView + // sourcery: default.value = _CancelActionDefault() + var cancelAction: ActionModel? { get } + + // sourcery: genericParameter.name = ResetActionView + // sourcery: default.value = _ResetActionDefault() + var resetAction: ActionModel? { get } + + // sourcery: genericParameter.name = ApplyActionView + // sourcery: default.value = _ApplyActionDefault() + var applyAction: ActionModel? { get } + + // sourcery: default.value = nil + // sourcery: no_view + var onUpdate: (() -> Void)? { get } +} + +// sourcery: add_env_props = "filterFeedbackBarStyle" +// sourcery: virtualPropActionHelper = "@StateObject var context: SortFilterContext = SortFilterContext()" +// sourcery: generated_component_composite +public protocol FilterFeedbackBarItemModel: LeftIconComponent, TitleComponent, RightIconComponent { + // sourcery: no_view + var isSelected: Bool { get } +} + +// sourcery: add_env_props = "optionListPickerStyle" +// sourcery: generated_component_composite +public protocol FilterFeedbackBarButtonModel: LeftIconComponent, TitleComponent { + // sourcery: no_view + var isSelected: Bool { get } +} + +// sourcery: add_env_props = "filterFeedbackBarStyle" +// sourcery: generated_component_not_configurable +public protocol OptionListPickerItemModel: OptionListPickerComponent { + // sourcery: default.value = nil + // sourcery: no_view + var onTap: ((_ index: Int) -> Void)? { get } +} + +// sourcery: add_env_props = "filterFeedbackBarStyle" +// sourcery: generated_component_not_configurable +// sourcery: add_env_props = "fioriToggleStyle" +public protocol SwitchPickerItemModel: SwitchPickerComponent {} + +// sourcery: add_env_props = "filterFeedbackBarStyle" +// sourcery: generated_component_not_configurable +public protocol SliderPickerItemModel: SliderPickerComponent {} diff --git a/Sources/FioriSwiftUICore/Views/FilterFeedbackBarButton+View.swift b/Sources/FioriSwiftUICore/Views/FilterFeedbackBarButton+View.swift new file mode 100644 index 000000000..2c2e5c94b --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/FilterFeedbackBarButton+View.swift @@ -0,0 +1,168 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery + +import SwiftUI + +extension Fiori { + enum FilterFeedbackBarButton { + typealias LeftIcon = EmptyModifier + typealias LeftIconCumulative = EmptyModifier + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + + static let leftIcon = LeftIcon() + static let title = Title() + static let leftIconCumulative = LeftIconCumulative() + static let titleCumulative = TitleCumulative() + } +} + +extension FilterFeedbackBarButton: View { + public var body: some View { + optionListPickerStyle.makeBody(configuration: OptionListPickerButtonConfiguration(leftIcon: AnyView(leftIcon), title: AnyView(title), isSelected: _isSelected)) + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct OptionChipLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(OptionChip(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ + +/// Option list picker configuration for styling +public struct OptionListPickerButtonConfiguration { + let leftIcon: AnyView + let title: AnyView + let isSelected: Bool + + /// :nodoc: + public init(leftIcon: AnyView, title: AnyView, isSelected: Bool) { + self.leftIcon = leftIcon + self.title = title + self.isSelected = isSelected + } +} + +/// Option list picker style +public protocol OptionListPickerStyle { + /// :nodoc: + func makeBody(configuration: OptionListPickerButtonConfiguration) -> AnyView +} + +/// Default option list picker style +public struct DefaultOptionListPickerStyle: OptionListPickerStyle { + let font: Font + let foregroundColorSelected: Color + let foregroundColorUnselected: Color + let fillColorSelected: Color + let fillColorUnselected: Color + let strokeColorSelected: Color + let strokeColorUnselected: Color + let cornerRadius: CGFloat + let spacing: CGFloat + let borderWidth: CGFloat + let minHeight: CGFloat + let minTouchHeight: CGFloat + + /// :nodoc: + public init(font: Font = .system(.body), foregroundColorSelected: Color = .preferredColor(.tintColor), foregroundColorUnselected: Color = .preferredColor(.tertiaryLabel), fillColorSelected: Color = .preferredColor(.primaryFill), fillColorUnselected: Color = .preferredColor(.secondaryFill), strokeColorSelected: Color = .preferredColor(.tintColor), strokeColorUnselected: Color = .preferredColor(.separator), cornerRadius: CGFloat = 16, spacing: CGFloat = 6, borderWidth: CGFloat = 1, minHeight: CGFloat = 44, minTouchHeight: CGFloat = 56) { + self.font = font + self.foregroundColorSelected = foregroundColorSelected + self.foregroundColorUnselected = foregroundColorUnselected + self.fillColorSelected = fillColorSelected + self.fillColorUnselected = fillColorUnselected + self.strokeColorSelected = strokeColorSelected + self.strokeColorUnselected = strokeColorUnselected + self.cornerRadius = cornerRadius + self.spacing = spacing + self.borderWidth = borderWidth + self.minHeight = minHeight + self.minTouchHeight = minTouchHeight + } + + /// :nodoc: + public func makeBody(configuration: OptionListPickerButtonConfiguration) -> AnyView { + AnyView( + HStack(spacing: self.spacing) { + configuration.leftIcon + configuration.title + } + .font(self.font) + .foregroundColor(configuration.isSelected ? self.foregroundColorSelected : self.foregroundColorUnselected) + .frame(maxWidth: .infinity, minHeight: minHeight) + .background( + ZStack { + RoundedRectangle(cornerRadius: cornerRadius) + .fill(configuration.isSelected ? fillColorSelected : fillColorUnselected) + RoundedRectangle(cornerRadius: cornerRadius) + .stroke(configuration.isSelected ? strokeColorSelected : strokeColorUnselected, lineWidth: borderWidth) + } + ) + .frame(minHeight: minTouchHeight) + ) + } +} + +struct OptionListPickerStyleKey: EnvironmentKey { + static var defaultValue: any OptionListPickerStyle = DefaultOptionListPickerStyle() +} + +extension EnvironmentValues { + var optionListPickerStyle: any OptionListPickerStyle { + get { + self[OptionListPickerStyleKey.self] + } + set { + self[OptionListPickerStyleKey.self] = newValue + } + } +} + +/// Experiemental option list picker styling +public extension View { + /// Experiemental option list picker styling + func optionListPickerStyle(_ style: S) -> some View where S: OptionListPickerStyle { + self.environment(\.optionListPickerStyle, style) + } + + /// Experiemental option list picker styling + func optionListPickerStyle(font: Font = .system(.body), foregroundColorSelected: Color = .preferredColor(.tintColor), foregroundColorUnselected: Color = .preferredColor(.tertiaryLabel), fillColorSelected: Color = .preferredColor(.primaryFill), fillColorUnselected: Color = .preferredColor(.secondaryFill), strokeColorSelected: Color = .preferredColor(.tintColor), strokeColorUnselected: Color = .preferredColor(.separator), cornerRadius: CGFloat = 16, spacing: CGFloat = 6, borderWidth: CGFloat = 1, minHeight: CGFloat = 44) -> some View { + self.environment(\.optionListPickerStyle, + DefaultOptionListPickerStyle(font: font, foregroundColorSelected: foregroundColorSelected, foregroundColorUnselected: foregroundColorUnselected, fillColorSelected: fillColorSelected, fillColorUnselected: fillColorUnselected, strokeColorSelected: strokeColorSelected, strokeColorUnselected: strokeColorUnselected, cornerRadius: cornerRadius, spacing: spacing, borderWidth: borderWidth, minHeight: minHeight)) + } +} + +#Preview { + VStack { + Spacer() + + FilterFeedbackBarButton(leftIcon: Image(systemName: "airplane"), title: "Airplane", isSelected: true) + FilterFeedbackBarButton(leftIcon: Image(systemName: "airplane"), title: "Airplane", isSelected: false) + FilterFeedbackBarButton(title: "Ship", isSelected: true) + FilterFeedbackBarButton(title: "Ship", isSelected: false) + FilterFeedbackBarButton(leftIcon: Image(systemName: "bus"), title: "Bus", isSelected: true) + FilterFeedbackBarButton(leftIcon: Image(systemName: "bus"), title: "Bus", isSelected: false) + + Spacer() + + FilterFeedbackBarButton(leftIcon: Image(systemName: "airplane"), title: "Air Plane", isSelected: true) + .optionListPickerStyle(font: .largeTitle, foregroundColorSelected: .red, strokeColorSelected: .red, cornerRadius: 25) + FilterFeedbackBarButton(leftIcon: Image(systemName: "airplane"), title: "Air Plane", isSelected: false) + .optionListPickerStyle(font: .footnote, foregroundColorUnselected: .green, strokeColorSelected: .black) + .optionListPickerStyle(cornerRadius: 16) + FilterFeedbackBarButton(title: "Ship", isSelected: true) + .optionListPickerStyle(fillColorSelected: .yellow) + FilterFeedbackBarButton(title: "Ship", isSelected: false) + .optionListPickerStyle(fillColorUnselected: .gray) + FilterFeedbackBarButton(leftIcon: Image(systemName: "bus"), title: "Blue Bus", isSelected: true) + .optionListPickerStyle(cornerRadius: 20) + FilterFeedbackBarButton(leftIcon: Image(systemName: "bus"), title: "Gray Bus", isSelected: false) + .optionListPickerStyle(cornerRadius: 20) + + Spacer() + } +} diff --git a/Sources/FioriSwiftUICore/Views/OptionListPickerItem+View.swift b/Sources/FioriSwiftUICore/Views/OptionListPickerItem+View.swift new file mode 100644 index 000000000..a072cfa6a --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/OptionListPickerItem+View.swift @@ -0,0 +1,56 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery + +import SwiftUI + +extension OptionListPickerItem: View { + public var body: some View { + Grid(horizontalSpacing: 16) { + ForEach(0 ..< Int(ceil(Double(_valueOptions.count) / 2.0))) { rowIndex in + GridRow { + FilterFeedbackBarButton( + leftIcon: _value.wrappedValue.contains(rowIndex * 2) ? Image(systemName: "checkmark") : nil, + title: _valueOptions[rowIndex * 2], + isSelected: _value.wrappedValue.contains(rowIndex * 2) + ) + .onTapGesture { + _onTap?(rowIndex * 2) + } + if rowIndex * 2 + 1 < _valueOptions.count { + FilterFeedbackBarButton( + leftIcon: _value.wrappedValue.contains(rowIndex * 2 + 1) ? Image(systemName: "checkmark") : nil, + title: _valueOptions[rowIndex * 2 + 1], + isSelected: _value.wrappedValue.contains(rowIndex * 2 + 1) + ) + .onTapGesture { + _onTap?(rowIndex * 2 + 1) + } + } + } + } + } + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct OptionListPickerLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(OptionListPicker(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ + +#Preview { + VStack { + Spacer() + OptionListPickerItem(value: Binding<[Int]>(get: { [0, 1, 2] }, set: { print($0) }), valueOptions: ["Received", "Started", "Hold", "Transfer", "Completed", "Pending Review", "Accepted", "Rejected"], hint: nil) + .frame(width: 375) + Spacer() + OptionListPickerItem(value: Binding<[Int]>(get: { [0, 1, 2] }, set: { print($0) }), valueOptions: ["Received", "Started", "Hold", "Transfer", "Completed", "Pending Review", "Accepted", "Rejected"], hint: nil) + .optionListPickerStyle(font: .title, foregroundColorSelected: Color.red, strokeColorSelected: Color.red, cornerRadius: 25) + .frame(width: 375) + Spacer() + } +} diff --git a/Sources/FioriSwiftUICore/Views/SliderPickerItem+View.swift b/Sources/FioriSwiftUICore/Views/SliderPickerItem+View.swift new file mode 100644 index 000000000..a50ca75ef --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SliderPickerItem+View.swift @@ -0,0 +1,199 @@ +import SwiftUI + +extension SliderPickerItem: View { + public var body: some View { + VStack { + HStack { + Text(String(format: self._formatter ?? NSLocalizedString("Value: %d", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), _value.wrappedValue ?? _minimumValue)) + .font(.fiori(forTextStyle: .subheadline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + } + .frame(minHeight: 44) + + HStack { + Slider(value: .convert(from: _value, ifNilUse: _minimumValue), in: Float(_minimumValue) ... Float(_maximumValue), step: 1.0) { + EmptyView() + } minimumValueLabel: { + Text("\(_minimumValue)") + .font(.body) + .fontWeight(.regular) + .foregroundColor(.preferredColor(.primaryLabel)) + } maximumValueLabel: { + Text("\(_maximumValue)") + .font(.body) + .fontWeight(.regular) + .foregroundColor(.preferredColor(.primaryLabel)) + } + } + .frame(minHeight: 44) + + if let hint = _hint { + HStack { + Text(hint) + .font(.fiori(forTextStyle: .subheadline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + } + } + } + } +} + +private extension SliderPickerItem { + func calcWidth(font: Font) -> CGFloat { + var width: CGFloat = 0 + for i in 0 ... 9 { + let fontAttributes = [NSAttributedString.Key.font: self.preferredFont(from: font)] + let size = String(i).size(withAttributes: fontAttributes) + width = max(size.width, width) + } + return floor(log10(CGFloat(_maximumValue)) + 1) * width + 2 * 12 + } + + func preferredFont(from font: Font) -> UIFont { + let uiFont: UIFont + + switch font { + case .largeTitle: + uiFont = UIFont.preferredFont(forTextStyle: .largeTitle) + case .title: + uiFont = UIFont.preferredFont(forTextStyle: .title1) + case .title2: + uiFont = UIFont.preferredFont(forTextStyle: .title2) + case .title3: + uiFont = UIFont.preferredFont(forTextStyle: .title3) + case .headline: + uiFont = UIFont.preferredFont(forTextStyle: .headline) + case .subheadline: + uiFont = UIFont.preferredFont(forTextStyle: .subheadline) + case .callout: + uiFont = UIFont.preferredFont(forTextStyle: .callout) + case .caption: + uiFont = UIFont.preferredFont(forTextStyle: .caption1) + case .caption2: + uiFont = UIFont.preferredFont(forTextStyle: .caption2) + case .footnote: + uiFont = UIFont.preferredFont(forTextStyle: .footnote) + case .body: + uiFont = UIFont.preferredFont(forTextStyle: .body) + default: + uiFont = UIFont.preferredFont(forTextStyle: .body) + } + + return uiFont + } +} + +struct RangeIntegerStyle: ParseableFormatStyle { + var parseStrategy: RangeIntegerStrategy = .init() + let range: ClosedRange + + func format(_ value: Int) -> String { + let constrainedValue = min(max(value, range.lowerBound), self.range.upperBound) + return "\(constrainedValue)" + } +} + +struct RangeIntegerStrategy: ParseStrategy { + func parse(_ value: String) throws -> Int { + Int(value) ?? 1 + } +} + +extension FormatStyle where Self == RangeIntegerStyle { + static func ranged(_ range: ClosedRange) -> RangeIntegerStyle { + RangeIntegerStyle(range: range) + } +} + +extension Binding { + static func convert(from intBinding: Binding, ifNilUse defaultValue: TInt) -> Binding where TInt: BinaryInteger, TFloat: BinaryFloatingPoint { + Binding( + get: { + TFloat(intBinding.wrappedValue ?? defaultValue) + }, + set: { + intBinding.wrappedValue = TInt($0) + } + ) + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct SliderPickerLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SliderPicker(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ + +private struct SliderPickeTestView: View { + @State var value1: Int? = 10 + @State var value2: Int? = 20 + @State var value3: Int? = nil + + var body: some View { + VStack { + Spacer() + HStack { + Text("Value 1: \($value1.wrappedValue ?? 0)") + .font(.largeTitle) + .foregroundColor(value1 != nil ? .blue : .gray) + Spacer() + } + SliderPickerItem(value: Binding( + get: { + value1 + }, + set: { + value1 = $0 + } + ), minimumValue: 0, maximumValue: 1000, hint: nil) + Spacer() + HStack { + Text("Value 2: \(value2 ?? 0)") + .font(.largeTitle) + .foregroundColor(value2 != nil ? .blue : .gray) + + Spacer() + } + + SliderPickerItem(value: Binding( + get: { + value2 + }, + set: { + value2 = $0 + } + ), minimumValue: 0, maximumValue: 100, hint: "Pick an integer value") + Spacer() + HStack { + Text("Value 3: \(value3 ?? 0)") + .font(.largeTitle) + .foregroundColor(value3 != nil ? .blue : .gray) + + Spacer() + } + SliderPickerItem(value: Binding( + get: { + value3 + }, + set: { + value3 = $0 + } + ), minimumValue: 0, maximumValue: 100, hint: "Pick an integer value") + Spacer() + } + .frame(width: 375) + } +} + +struct SliderPickeTestView_Previews: PreviewProvider { + static var previews: some View { + SliderPickeTestView() + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/FeedbackBar+View.swift b/Sources/FioriSwiftUICore/Views/SortFilter/FeedbackBar+View.swift new file mode 100644 index 000000000..ccef6b1f8 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/FeedbackBar+View.swift @@ -0,0 +1,29 @@ +import SwiftUI + +extension Fiori { + enum FilterFeedbackBar { + typealias Items = EmptyModifier + typealias ItemsCumulative = EmptyModifier + + static let items = Items() + static let itemsCumulative = ItemsCumulative() + } +} + +extension FilterFeedbackBar: View { + public var body: some View { + items + .onModelUpdateAppCallback(_onUpdate ?? {}) + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct SortFilterMenuLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SortFilterMenu(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+Style.swift b/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+Style.swift new file mode 100644 index 000000000..a2b9ce094 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+Style.swift @@ -0,0 +1,109 @@ +import FioriThemeManager +import SwiftUI + +/// Configuration for filter feedback bar styling +public struct FilterFeedbackBarStyleConfiguration { + let leftIcon: AnyView + let title: AnyView + let isSelected: Bool + let rightIcon: AnyView + + public init(leftIcon: AnyView, title: AnyView, isSelected: Bool, rightIcon: AnyView) { + self.leftIcon = leftIcon + self.title = title + self.isSelected = isSelected + self.rightIcon = rightIcon + } +} + +/// Protocol for sort and filer menu item styling +public protocol FilterFeedbackBarStyle { + typealias Configuration = FilterFeedbackBarStyleConfiguration + + /// Build view according to configuration and style + func makeBody(configuration: Self.Configuration) -> AnyView +} + +/// Default style for sort and filer menu item +public struct DefaultFilterFeedbackBarStyle: FilterFeedbackBarStyle { + let font: Font + let foregroundColorSelected: Color + let foregroundColorUnselected: Color + let fillColorSelected: Color + let fillColorUnselected: Color + let strokeColorSelected: Color + let strokeColorUnselected: Color + let cornerRadius: CGFloat + let spacing: CGFloat + let padding: CGFloat + let borderWidth: CGFloat + let minHeight: CGFloat + + /// :nodoc: + public init(font: Font = .system(.body), foregroundColorSelected: Color = .preferredColor(.tintColor), foregroundColorUnselected: Color = .preferredColor(.tertiaryLabel), fillColorSelected: Color = .preferredColor(.primaryFill), fillColorUnselected: Color = .preferredColor(.secondaryFill), strokeColorSelected: Color = .preferredColor(.tintColor), strokeColorUnselected: Color = .preferredColor(.separator), cornerRadius: CGFloat = 10, spacing: CGFloat = 6, padding: CGFloat = 8, borderWidth: CGFloat = 1, minHeight: CGFloat = 38) { + self.font = font + self.foregroundColorSelected = foregroundColorSelected + self.foregroundColorUnselected = foregroundColorUnselected + self.fillColorSelected = fillColorSelected + self.fillColorUnselected = fillColorUnselected + self.strokeColorSelected = strokeColorSelected + self.strokeColorUnselected = strokeColorUnselected + self.cornerRadius = cornerRadius + self.spacing = spacing + self.padding = padding + self.borderWidth = borderWidth + self.minHeight = minHeight + } + + /// Build view according to configuration and style + public func makeBody(configuration: Configuration) -> AnyView { + AnyView( + HStack(spacing: self.spacing) { + configuration.leftIcon + configuration.title + configuration.rightIcon + } + .font(self.font) + .foregroundColor(configuration.isSelected ? self.foregroundColorSelected : self.foregroundColorUnselected) + .padding(self.padding) + .frame(minHeight: self.minHeight) + .background( + ZStack { + RoundedRectangle(cornerRadius: cornerRadius) + .fill(configuration.isSelected ? fillColorSelected : fillColorUnselected) + RoundedRectangle(cornerRadius: cornerRadius) + .stroke(configuration.isSelected ? strokeColorSelected : strokeColorUnselected, lineWidth: borderWidth) + } + ) + ) + } +} + +struct FilterFeedbackBarStyleKey: EnvironmentKey { + static var defaultValue: any FilterFeedbackBarStyle = DefaultFilterFeedbackBarStyle() +} + +extension EnvironmentValues { + var filterFeedbackBarStyle: any FilterFeedbackBarStyle { + get { + self[FilterFeedbackBarStyleKey.self] + } + set { + self[FilterFeedbackBarStyleKey.self] = newValue + } + } +} + +/// Experimental filter feedback bar styling +public extension View { + /// Experimental filter feedback bar styling + func filterFeedbackBarStyle(_ style: S) -> some View where S: FilterFeedbackBarStyle { + self.environment(\.filterFeedbackBarStyle, style) + } + + /// Experimental filter feedback bar styling + func filterFeedbackBarStyle(font: Font = .system(.body), foregroundColorSelected: Color = .preferredColor(.tintColor), foregroundColorUnselected: Color = .preferredColor(.tertiaryLabel), fillColorSelected: Color = .preferredColor(.primaryFill), fillColorUnselected: Color = .preferredColor(.secondaryFill), strokeColorSelected: Color = .preferredColor(.tintColor), strokeColorUnselected: Color = .preferredColor(.separator), cornerRadius: CGFloat = 10, spacing: CGFloat = 6, padding: CGFloat = 8, borderWidth: CGFloat = 1, minHeight: CGFloat = 38) -> some View { + self.environment(\.filterFeedbackBarStyle, + DefaultFilterFeedbackBarStyle(font: font, foregroundColorSelected: foregroundColorSelected, foregroundColorUnselected: foregroundColorUnselected, fillColorSelected: fillColorSelected, fillColorUnselected: fillColorUnselected, strokeColorSelected: strokeColorSelected, strokeColorUnselected: strokeColorUnselected, cornerRadius: cornerRadius, spacing: spacing, padding: padding, borderWidth: borderWidth, minHeight: minHeight)) + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+View.swift b/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+View.swift new file mode 100644 index 000000000..3a9b747f2 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+View.swift @@ -0,0 +1,461 @@ +import SwiftUI + +extension Fiori { + enum FilterFeedbackBarItem { + typealias LeftIcon = EmptyModifier + typealias LeftIconCumulative = EmptyModifier + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + typealias RightIcon = EmptyModifier + typealias RightIconCumulative = EmptyModifier + + static let leftIcon = LeftIcon() + static let title = Title() + static let rightIcon = RightIcon() + static let leftIconCumulative = LeftIconCumulative() + static let titleCumulative = TitleCumulative() + static let rightIconCumulative = RightIconCumulative() + } +} + +extension FilterFeedbackBarItem: View { + public var body: some View { + filterFeedbackBarStyle.makeBody(configuration: FilterFeedbackBarStyleConfiguration(leftIcon: AnyView(_leftIcon), title: AnyView(_title), isSelected: _isSelected, rightIcon: AnyView(_rightIcon))).typeErased + } +} + +private extension View { + func icon(name: String?, isVisible: Bool) -> Image? { + if isVisible { + if let name = name { + return Image(systemName: name) + } + } + return nil + } +} + +struct FilterFeedbackMenuItem: View { + @Binding var item: SortFilterItem.PickerItem + var onUpdate: () -> Void + + public init(item: Binding, onUpdate: @escaping () -> Void) { + self._item = item + self.onUpdate = onUpdate + } + + var body: some View { + Group { + ForEach($item.valueOptions.wrappedValue, id: \.self) { opt in + FilterFeedbackBarItem(leftIcon: item.isOptionSelected(opt) ? icon(name: item.icon, isVisible: true) : nil, title: opt, isSelected: item.isOptionSelected(opt)) + .onTapGesture { + item.onTap(option: opt) + item.apply() + onUpdate() + } + } + } + } +} + +struct SliderMenuItem: View { + @Binding var item: SortFilterItem.SliderItem + + @State var isSheetVisible = false + + @State var detentHeight: CGFloat = 0 + + var onUpdate: () -> Void + + public init(item: Binding, onUpdate: @escaping () -> Void) { + self._item = item + self.onUpdate = onUpdate + } + + var body: some View { + FilterFeedbackBarItem(leftIcon: icon(name: item.icon, isVisible: true), title: item.label, rightIcon: Image(systemName: "chevron.down"), isSelected: item.isChecked) + .onTapGesture { + isSheetVisible.toggle() + } + .popover(isPresented: $isSheetVisible, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { + CancellableResettableDialogForm { + SortFilterItemTitle(title: item.name) + } cancelAction: { + Action(actionText: NSLocalizedString("Cancel", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.cancel() + isSheetVisible.toggle() + }) + .buttonStyle(CancelButtonStyle()) + } resetAction: { + Action(actionText: NSLocalizedString("Reset", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.reset() + }) + .buttonStyle(ResetButtonStyle()) + .disabled(self.item.isOriginal) + } applyAction: { + Action(actionText: NSLocalizedString("Apply", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.apply() + onUpdate() + isSheetVisible.toggle() + }) + .buttonStyle(ApplyButtonStyle()) + + } components: { + SliderPickerItem(value: Binding(get: { item.workingValue }, set: { item.workingValue = $0 }), formatter: item.formatter, minimumValue: item.minimumValue, maximumValue: item.maximumValue) + .padding([.leading, .trailing], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16) + } + .readHeight() + .onPreferenceChange(HeightPreferenceKey.self) { height in + if let height { + self.detentHeight = height + } + } + .presentationDetents([.height(self.detentHeight)]) + } + } +} + +struct PickerMenuItem: View { + @Binding var item: SortFilterItem.PickerItem + var onUpdate: () -> Void + + @State var isSheetVisible = false + + @State var detentHeight: CGFloat = 0 + + public init(item: Binding, onUpdate: @escaping () -> Void) { + self._item = item + self.onUpdate = onUpdate + } + + var body: some View { + if item.valueOptions.count > 4 { + button + } else { + menu + } + } + + @ViewBuilder + var button: some View { + FilterFeedbackBarItem(leftIcon: icon(name: item.icon, isVisible: true), title: item.label, rightIcon: Image(systemName: "chevron.down"), isSelected: item.isChecked) + .onTapGesture { + isSheetVisible.toggle() + } + .popover(isPresented: $isSheetVisible, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { + CancellableResettableDialogForm { + SortFilterItemTitle(title: item.name) + } cancelAction: { + Action(actionText: NSLocalizedString("Cancel", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.cancel() + isSheetVisible.toggle() + }) + .buttonStyle(CancelButtonStyle()) + } resetAction: { + Action(actionText: NSLocalizedString("Reset", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.reset() + }) + .buttonStyle(ResetButtonStyle()) + .disabled(self.item.isOriginal) + } applyAction: { + Action(actionText: NSLocalizedString("Apply", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.apply() + onUpdate() + isSheetVisible.toggle() + }) + .buttonStyle(ApplyButtonStyle()) + } components: { + OptionListPickerItem(value: $item.workingValue, valueOptions: item.valueOptions, hint: nil) { index in + item.onTap(option: item.valueOptions[index]) + } + .padding([.leading, .trailing], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16) + } + .readHeight() + .onPreferenceChange(HeightPreferenceKey.self) { height in + if let height { + self.detentHeight = height + } + } + .presentationDetents([.height(self.detentHeight)]) + } + } + + @ViewBuilder + var menu: some View { + HStack { + Menu { + ForEach(item.valueOptions.indices) { idx in + if item.isOptionSelected(index: idx) { + Button { + item.onTap(option: item.valueOptions[idx]) + item.apply() + onUpdate() + } label: { + Label { Text(item.valueOptions[idx]) } icon: { Image(fioriName: "fiori.accept") } + } + } else { + Button(item.valueOptions[idx]) { + item.onTap(option: item.valueOptions[idx]) + item.apply() + onUpdate() + } + } + } + } label: { + FilterFeedbackBarItem(leftIcon: icon(name: item.icon, isVisible: true), title: item.label, isSelected: item.isChecked) + } + } + } +} + +struct HeightPreferenceKey: PreferenceKey { + static var defaultValue: CGFloat? + + static func reduce(value: inout CGFloat?, nextValue: () -> CGFloat?) { + guard let nextValue = nextValue() else { return } + value = nextValue + } +} + +private extension View { + func readHeight() -> some View { + self.modifier(ReadHeightModifier()) + } +} + +private struct ReadHeightModifier: ViewModifier { + private var sizeView: some View { + GeometryReader { geometry in + Color.clear.preference(key: HeightPreferenceKey.self, value: geometry.size.height) + } + } + + func body(content: Content) -> some View { + content.background(self.sizeView) + } +} + +struct DateTimeMenuItem: View { + @Binding private var item: SortFilterItem.DateTimeItem + + @State private var isSheetVisible: Bool = false + + @State var detentHeight: CGFloat = 0 + + var onUpdate: () -> Void + + public init(item: Binding, onUpdate: @escaping () -> Void) { + self._item = item + self.onUpdate = onUpdate + } + + var body: some View { + FilterFeedbackBarItem(leftIcon: icon(name: item.icon, isVisible: true), title: item.label, rightIcon: Image(systemName: "chevron.down"), isSelected: item.isChecked) + .onTapGesture { + isSheetVisible.toggle() + } + .popover(isPresented: $isSheetVisible, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { + CancellableResettableDialogForm { + SortFilterItemTitle(title: item.name) + } cancelAction: { + Action(actionText: NSLocalizedString("Cancel", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.cancel() + isSheetVisible.toggle() + }) + .buttonStyle(CancelButtonStyle()) + } resetAction: { + Action(actionText: NSLocalizedString("Reset", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.reset() + }) + .buttonStyle(ResetButtonStyle()) + .disabled(self.item.isOriginal) + } applyAction: { + Action(actionText: NSLocalizedString("Apply", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + item.apply() + onUpdate() + isSheetVisible.toggle() + }) + .buttonStyle(ApplyButtonStyle()) + } components: { + VStack { + HStack { + Text(NSLocalizedString("Time", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: "")) + .font(.fiori(forTextStyle: .headline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + DatePicker( + "", + selection: Binding(get: { item.workingValue ?? Date() }, set: { item.workingValue = $0 }), + displayedComponents: [.hourAndMinute] + ) + .labelsHidden() + } + .padding([.leading, .trailing], UIDevice.current.userInterfaceIdiom == .pad ? 13 : 16) + + DatePicker( + item.label, + selection: Binding(get: { item.workingValue ?? Date() }, set: { item.workingValue = $0 }), + displayedComponents: [.date] + ) + .datePickerStyle(.graphical) + .labelsHidden() + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 : UIScreen.main.bounds.size.width - 16) + .clipped() + } + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width) + + } + .readHeight() + .onPreferenceChange(HeightPreferenceKey.self) { height in + if let height { + self.detentHeight = height + } + } + .presentationDetents([.height(self.detentHeight)]) + } + } +} + +struct SwitchMenuItem: View { + @Binding private var item: SortFilterItem.SwitchItem + +// @State var detentHeight: CGFloat = 0 + +// @State private var isSheetVisible: Bool = false + var onUpdate: () -> Void + + public init(item: Binding, onUpdate: @escaping () -> Void) { + self._item = item + self.onUpdate = onUpdate + } + + var body: some View { + FilterFeedbackBarItem(leftIcon: icon(name: item.icon, isVisible: true), title: item.name, isSelected: item.isChecked) + .onTapGesture { + if item.value != nil { + item.workingValue?.toggle() + item.apply() + onUpdate() + } else { + item.workingValue = true + item.apply() + onUpdate() + } +// isSheetVisible.toggle() + } +// .popover(isPresented: $isSheetVisible, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { +// CancellableResettableDialogForm { +// Text(item.name) +// } cancelAction: { +// Action(actionText: "Cancel", didSelectAction: { +// item.cancel() +// isSheetVisible.toggle() +// }) +// .buttonStyle(CancelResetButtonStyle()) +// } resetAction: { +// Action(actionText: "Reset", didSelectAction: { +// item.reset() +// }) +// .buttonStyle(CancelResetButtonStyle()) +// } applyAction: { +// Action(actionText: "Apply", didSelectAction: { +// item.apply() +// onUpdate() +// isSheetVisible.toggle() +// }) +// .buttonStyle(ApplyButtonStyle()) +// } components: { +// SwitchPicker(value: $item.workingValue) +// } +// } + } +} + +struct FullCFGMenuItem: View { + @Environment(\.sortFilterMenuItemFullConfigurationButton) var fullCFGButton + + @Binding var items: [[SortFilterItem]] + + @State var isSheetVisible = false + + var onUpdate: () -> Void + + public init(items: Binding<[[SortFilterItem]]>, onUpdate: @escaping () -> Void) { + self._items = items + self.onUpdate = onUpdate + } + + var body: some View { + FilterFeedbackBarItem(leftIcon: icon(name: fullCFGButton.icon, isVisible: true), title: fullCFGButton.name ?? "", isSelected: true) + .onTapGesture { + isSheetVisible.toggle() + } + .popover(isPresented: $isSheetVisible, attachmentAnchor: .point(.bottom), arrowEdge: .bottom) { + SortFilterView( + title: { + if let title = fullCFGButton.name { + Text(title) + } else { + EmptyView() + } + }, + items: { + _SortFilterCFGItemContainer(items: $items) + }, + cancelAction: { + Action(actionText: NSLocalizedString("Cancel", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + // item.apply() + onUpdate() + isSheetVisible.toggle() + }) + .buttonStyle(CancelButtonStyle()) + }, + resetAction: { + Action(actionText: NSLocalizedString("Reset", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + // item.cancel() + isSheetVisible.toggle() + }) + .buttonStyle(ResetButtonStyle()) + }, + applyAction: { + Action(actionText: NSLocalizedString("Apply", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: ""), didSelectAction: { + // item.reset() + }) + .buttonStyle(ApplyButtonStyle()) + }, + onUpdate: {} + ) + } + } +} + +#Preview { + VStack { + Spacer() + + FilterFeedbackBarItem(leftIcon: Image(systemName: "airplane"), title: "Airplane", rightIcon: Image(systemName: "chevron.down"), isSelected: true) + FilterFeedbackBarItem(leftIcon: Image(systemName: "airplane"), title: "Airplane", rightIcon: Image(systemName: "chevron.down"), isSelected: false) + FilterFeedbackBarItem(title: "Ship", rightIcon: Image(systemName: "chevron.down"), isSelected: true) + FilterFeedbackBarItem(title: "Ship", rightIcon: Image(systemName: "chevron.down"), isSelected: false) + FilterFeedbackBarItem(leftIcon: Image(systemName: "bus"), title: "Bus", isSelected: true) + FilterFeedbackBarItem(leftIcon: Image(systemName: "bus"), title: "Bus", isSelected: false) + + Spacer() + + FilterFeedbackBarItem(leftIcon: Image(systemName: "airplane"), title: "Air Plane", rightIcon: Image(systemName: "chevron.down"), isSelected: true) + .filterFeedbackBarStyle(font: .largeTitle, foregroundColorSelected: .red, strokeColorSelected: .red, cornerRadius: 25) + FilterFeedbackBarItem(leftIcon: Image(systemName: "airplane"), title: "Air Plane", rightIcon: Image(systemName: "chevron.down"), isSelected: false) + .filterFeedbackBarStyle(font: .footnote, foregroundColorUnselected: .green, strokeColorSelected: .black) + .filterFeedbackBarStyle(cornerRadius: 16) + FilterFeedbackBarItem(title: "Ship", rightIcon: Image(systemName: "chevron.down"), isSelected: true) + .filterFeedbackBarStyle(fillColorSelected: .yellow) + FilterFeedbackBarItem(title: "Ship", rightIcon: Image(systemName: "chevron.down"), isSelected: false) + .filterFeedbackBarStyle(fillColorUnselected: .gray) + FilterFeedbackBarItem(leftIcon: Image(systemName: "bus"), title: "Blue Bus", isSelected: true) + .filterFeedbackBarStyle(cornerRadius: 20) + FilterFeedbackBarItem(leftIcon: Image(systemName: "bus"), title: "Gray Bus", isSelected: false) + .filterFeedbackBarStyle(cornerRadius: 20) + + Spacer() + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/SortFilter+Environment.swift b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilter+Environment.swift new file mode 100644 index 000000000..054e54dcf --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilter+Environment.swift @@ -0,0 +1,23 @@ +import SwiftUI + +struct SortFilterOnModelUpdateAppCallbackKey: EnvironmentKey { + static let defaultValue: () -> Void = { print("default empty callback") } +} + +extension EnvironmentValues { + var onModelUpdateAppCallback: () -> Void { + get { + self[SortFilterOnModelUpdateAppCallbackKey.self] + } + + set { + self[SortFilterOnModelUpdateAppCallbackKey.self] = newValue + } + } +} + +extension View { + func onModelUpdateAppCallback(_ closure: @escaping () -> Void) -> some View { + self.environment(\.onModelUpdateAppCallback, closure) + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterContext.swift b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterContext.swift new file mode 100644 index 000000000..e5af8e86d --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterContext.swift @@ -0,0 +1,18 @@ +import SwiftUI + +class SortFilterContext: Equatable, ObservableObject { + @Published public var isResetButtonEnabled: Bool = false + @Published public var isApplyButtonEnabled: Bool = false + + @Published public var handleCancel: (() -> Void)? + @Published public var handleReset: (() -> Void)? + @Published public var handleApply: (() -> Void)? + + @Published public var handleDismiss: (() -> Void)? + + public init() {} + + static func == (lhs: SortFilterContext, rhs: SortFilterContext) -> Bool { + return lhs.isResetButtonEnabled == rhs.isResetButtonEnabled && lhs.isApplyButtonEnabled == rhs.isApplyButtonEnabled + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterItemTitle.swift b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterItemTitle.swift new file mode 100644 index 000000000..af923f808 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterItemTitle.swift @@ -0,0 +1,30 @@ +// +// SortFilterItemTitle.swift +// +// +// Created by Xu, Charles on 10/24/23. +// + +import SwiftUI +import FioriThemeManager + +/// Dialog titile component +struct SortFilterItemTitle: TitleComponent, View { + public let title: String + + public init(title: String) { + self.title = title + } + + public var body: some View { + Text(title) + .font(.body) + .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/) + .foregroundStyle(Color.preferredColor(.primaryLabel)) + .multilineTextAlignment(.center) + } +} + +#Preview { + SortFilterItemTitle(title: "My Title") +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterView+View.swift b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterView+View.swift new file mode 100644 index 000000000..7b4063483 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/SortFilterView+View.swift @@ -0,0 +1,89 @@ +import SwiftUI + +extension Fiori { + enum SortFilterView { + struct Title: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/) + .foregroundStyle(Color.preferredColor(.primaryLabel)) + .multilineTextAlignment(.center) + } + } + typealias TitleCumulative = EmptyModifier + typealias Items = EmptyModifier + typealias ItemsCumulative = EmptyModifier + typealias CancelAction = EmptyModifier + typealias CancelActionCumulative = EmptyModifier + typealias ResetAction = EmptyModifier + typealias ResetActionCumulative = EmptyModifier + typealias ApplyAction = EmptyModifier + typealias ApplyActionCumulative = EmptyModifier + + static let title = Title() + static let items = Items() + static let cancelAction = CancelAction() + static let resetAction = ResetAction() + static let applyAction = ApplyAction() + static let titleCumulative = TitleCumulative() + static let itemsCumulative = ItemsCumulative() + static let cancelActionCumulative = CancelActionCumulative() + static let resetActionCumulative = ResetActionCumulative() + static let applyActionCumulative = ApplyActionCumulative() + } +} + +extension SortFilterView: View { + public var body: some View { + CancellableResettableDialogForm { + title + } cancelAction: { + cancelAction + .simultaneousGesture( + TapGesture() + .onEnded { _ in + context.handleCancel?() + dismiss() + } + ) + .buttonStyle(CancelButtonStyle()) + } resetAction: { + resetAction + .simultaneousGesture( + TapGesture() + .onEnded { _ in + context.handleReset?() + } + ) + .buttonStyle(ResetButtonStyle()) + .environment(\.isEnabled, context.isResetButtonEnabled) + } applyAction: { + applyAction + .simultaneousGesture( + TapGesture() + .onEnded { _ in + context.handleApply?() + _onUpdate?() + dismiss() + } + ) + .buttonStyle(ApplyButtonStyle()) + .environment(\.isEnabled, true) + } components: { + _items + .environmentObject(context) + } + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct SortFilterFullCFGLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SortFilterFullCFG(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterCFGItemContainer.swift b/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterCFGItemContainer.swift new file mode 100644 index 000000000..a54df5196 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterCFGItemContainer.swift @@ -0,0 +1,196 @@ +// _SortFilterMenuItemContainer.swift +// +// +// Created by Xu, Charles on 9/25/23. +// +import SwiftUI +import FioriThemeManager + +/// :nodoc: +public struct _SortFilterCFGItemContainer { + @EnvironmentObject var context: SortFilterContext + + @Binding var _items: [[SortFilterItem]] + + public init(items: Binding<[[SortFilterItem]]>) { + self.__items = items + } +} + +extension _SortFilterCFGItemContainer: View { + /// :nodoc: + public var body: some View { + ScrollView(.vertical, showsIndicators: false) { + VStack(spacing: 30) { + ForEach(0 ..< _items.count) { r in + VStack { + ForEach(0 ..< _items[r].count) { c in + switch _items[r][c] { + case .picker: + picker(row: r, column: c) + case .filterfeedback: + filterfeedback(row: r, column: c) + case .switch: + switcher(row: r, column: c) + case .slider: + slider(row: r, column: c) + case .datetime: + datetimePicker(row: r, column: c) + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width) + } + } + } + .padding([.top], 12) + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2: UIScreen.main.bounds.size.width - 16 * 2) + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width) + .background(Color.preferredColor(.secondaryGroupedBackground)) + } + } + .background(Color.preferredColor(.secondaryBackground)) + } + .onChange(of: _items) { _ in + checkUpdateButtonState() + } + .onAppear { + context.handleCancel = { + for r in 0 ..< _items.count { + for c in 0 ..< _items[r].count { + _items[r][c].cancel() + } + } + } + + context.handleReset = { + for r in 0 ..< _items.count { + for c in 0 ..< _items[r].count { + _items[r][c].reset() + } + } + } + + context.handleApply = { + for r in 0 ..< _items.count { + for c in 0 ..< _items[r].count { + _items[r][c].apply() + } + } + } + + checkUpdateButtonState() + } + } + + func checkUpdateButtonState() { + var isApplyButtonEnabled = false + var isResetButtonEnabled = false + + for item in _items.joined() { + if !isApplyButtonEnabled && item.isChanged { + isApplyButtonEnabled = true + print("Enable apply button.") + } + if !isResetButtonEnabled && !item.isOriginal { + isResetButtonEnabled = true + print("Enable reset button.") + } + } + context.isApplyButtonEnabled = isApplyButtonEnabled + context.isResetButtonEnabled = isResetButtonEnabled + } + + func picker(row r: Int, column c: Int) -> some View { + VStack { + HStack { + Text(_items[r][c].picker.name) + .font(.fiori(forTextStyle: .subheadline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + } + OptionListPickerItem( + value: Binding<[Int]>(get: { _items[r][c].picker.workingValue }, set: { _items[r][c].picker.workingValue = $0 }), + valueOptions: _items[r][c].picker.valueOptions, + onTap: { index in + _items[r][c].picker.onTap(option: _items[r][c].picker.valueOptions[index]) + } + ) + } + } + + func filterfeedback(row r: Int, column c: Int) -> some View { + VStack { + HStack { + Text(_items[r][c].filterfeedback.name) + .font(.fiori(forTextStyle: .subheadline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + } + OptionListPickerItem( + value: Binding<[Int]>(get: { _items[r][c].filterfeedback.workingValue }, set: { _items[r][c].filterfeedback.workingValue = $0 }), + valueOptions: _items[r][c].filterfeedback.valueOptions, + onTap: { index in + _items[r][c].filterfeedback.onTap(option: _items[r][c].filterfeedback.valueOptions[index]) + } + ) + } + } + + func switcher(row r: Int, column c: Int) -> some View { + VStack { + SwitchPickerItem(value: Binding(get: { _items[r][c].switch.workingValue }, set: { _items[r][c].switch.workingValue = $0 }), name: _items[r][c].switch.name, hint: nil) + } + } + + func slider(row r: Int, column c: Int) -> some View { + VStack { + HStack { + Text(_items[r][c].slider.name) + .font(.headline) + Spacer() + } + SliderPickerItem( + value: Binding(get: { _items[r][c].slider.workingValue }, set: { _items[r][c].slider.workingValue = $0 }), + formatter: _items[r][c].slider.formatter, + minimumValue: _items[r][c].slider.minimumValue, + maximumValue: _items[r][c].slider.maximumValue + ) + } + } + + func datetimePicker(row r: Int, column c: Int) -> some View { + VStack { + HStack { + Text(_items[r][c].datetime.name) + .font(.fiori(forTextStyle: .headline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + } + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 : UIScreen.main.bounds.size.width - 16 * 2) + + HStack { + Text(NSLocalizedString("Time", tableName: "FioriSwiftUICore", bundle: Bundle.accessor, comment: "")) + .font(.fiori(forTextStyle: .headline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(Color.preferredColor(.primaryLabel)) + Spacer() + DatePicker( + "", + selection: Binding(get: { _items[r][c].datetime.workingValue ?? Date() }, set: { _items[r][c].datetime.workingValue = $0 }), + displayedComponents: [.hourAndMinute] + ) + .labelsHidden() + } + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2 : UIScreen.main.bounds.size.width - 16 * 2) + + DatePicker( + "", + selection: Binding(get: { _items[r][c].datetime.workingValue ?? Date() }, set: { _items[r][c].datetime.workingValue = $0 }), + displayedComponents: [.date] + ) + .datePickerStyle(.graphical) + .labelsHidden() + .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 : UIScreen.main.bounds.size.width - 16) +// .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 : UIScreen.main.bounds.size.width) + .clipped() +// .frame(width: UIDevice.current.userInterfaceIdiom == .pad ? 375 - 13 * 2: UIScreen.main.bounds.size.width) + } + } +} diff --git a/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterMenuItemContainer.swift b/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterMenuItemContainer.swift new file mode 100644 index 000000000..f36e0a0c8 --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SortFilter/_SortFilterMenuItemContainer.swift @@ -0,0 +1,161 @@ +// +// _SortFilterMenuItemContainer.swift +// +// +// Created by Xu, Charles on 9/25/23. +// +import SwiftUI + +/// :nodoc: +public struct _SortFilterMenuItemContainer { + @Environment(\.onModelUpdateAppCallback) var onUpdate: () -> Void +// @Environment(\.cancelActionView) var _cancelAction + @Environment(\.sortFilterMenuItemFullConfigurationButton) var fullCFGButton + @Binding var _items: [[SortFilterItem]] + + public init(items: Binding<[[SortFilterItem]]>) { + self.__items = items + } +} + +extension _SortFilterMenuItemContainer: View { + public var body: some View { + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 10) { + if fullCFGButton.positon == .leading { + FullCFGMenuItem(items: $_items, onUpdate: onUpdate) + } + ForEach(0 ..< _items.count) { r in + ForEach(0 ..< _items[r].count) { c in + if _items[r][c].showsOnFilterFeedbackBar { + switch _items[r][c] { + case .picker: + PickerMenuItem(item: Binding(get: { _items[r][c].picker }, set: { _items[r][c].picker = $0 }), onUpdate: onUpdate) + case .filterfeedback: + FilterFeedbackMenuItem(item: Binding(get: { _items[r][c].filterfeedback }, set: { _items[r][c].filterfeedback = $0 }), onUpdate: onUpdate) + case .switch: + SwitchMenuItem(item: Binding(get: { _items[r][c].switch }, set: { _items[r][c].switch = $0 }), onUpdate: onUpdate) + case .slider: + SliderMenuItem(item: Binding(get: { _items[r][c].slider }, set: { _items[r][c].slider = $0 }), onUpdate: onUpdate) + case .datetime: + DateTimeMenuItem(item: Binding(get: { _items[r][c].datetime }, set: { _items[r][c].datetime = $0 }), onUpdate: onUpdate) + } + } + } + } + if fullCFGButton.positon == .trailing { + FullCFGMenuItem(items: $_items, onUpdate: onUpdate) + } + } + } + .frame(minHeight: 44) + .padding(.leading, 5) + } +} + +struct SortFilterMenuItemFullConfigurationButtonKey: EnvironmentKey { + public static var defaultValue: SortFilterMenuItemFullConfigurationButton = .none +} + +/// Filter feedback bar item for displaying full configuration list +public struct SortFilterMenuItemFullConfigurationButton { + /// Name/title of the button + public let name: String? + /// SF icon name of the button + public let icon: String? + /// Position of the button + public let positon: Position + + /// Location of the button + public enum Position { + /// Disaplay the button as the first one + case leading + /// Display the button as the last one + case trailing + /// No button displayed + case none + } + + private init(name: String? = nil, icon: String? = nil, positon: Position) { + self.name = name + self.icon = icon + self.positon = positon + } + + /// Place the button at the beginning + public static func leading(name: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(name: name, positon: .leading) + } + + /// Place the button at the beginning + public static func leading(icon: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(icon: icon, positon: .leading) + } + + /// Place the button at the beginning + public static func leading(name: String, icon: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(name: name, icon: icon, positon: .leading) + } + + /// Place the button at the end + public static func trailing(name: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(name: name, positon: .trailing) + } + + /// Place the button at the end + public static func trailing(icon: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(icon: icon, positon: .trailing) + } + + /// Place the button at the end + public static func trailing(name: String, icon: String) -> SortFilterMenuItemFullConfigurationButton { + SortFilterMenuItemFullConfigurationButton(name: name, icon: icon, positon: .trailing) + } + + /// No button for full configuration + static var none = SortFilterMenuItemFullConfigurationButton(positon: Position.none) +} + +extension EnvironmentValues { + var sortFilterMenuItemFullConfigurationButton: SortFilterMenuItemFullConfigurationButton { + get { + self[SortFilterMenuItemFullConfigurationButtonKey.self] + } + set { + self[SortFilterMenuItemFullConfigurationButtonKey.self] = newValue + } + } +} + +/// Experiemental feature for adding full list of configuraiton to filter feedback bar +public extension View { + /// Place the button at the beginning + func leadingFullConfigurationMenuItem(name: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .leading(name: name)) + } + + /// Place the button at the beginning + func leadingFullConfigurationMenuItem(icon: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .leading(icon: icon)) + } + + /// Place the button at the beginning + func leadingFullConfigurationMenuItem(name: String, icon: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .leading(name: name, icon: icon)) + } + + /// Place the button at the end + func trailingFullConfigurationMenuItem(name: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .trailing(name: name)) + } + + /// Place the button at the end + func trailingFullConfigurationMenuItem(icon: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .trailing(icon: icon)) + } + + /// Place the button at the end + func trailingFullConfigurationMenuItem(name: String, icon: String) -> some View { + self.environment(\.sortFilterMenuItemFullConfigurationButton, .trailing(name: name, icon: icon)) + } +} diff --git a/Sources/FioriSwiftUICore/Views/SwitchPickerItem+View.swift b/Sources/FioriSwiftUICore/Views/SwitchPickerItem+View.swift new file mode 100644 index 000000000..8051abe0b --- /dev/null +++ b/Sources/FioriSwiftUICore/Views/SwitchPickerItem+View.swift @@ -0,0 +1,135 @@ +import FioriThemeManager +import SwiftUI + +extension SwitchPickerItem: View { + public var body: some View { + AnyView( + Toggle(_name ?? "", isOn: .convert(from: _value, ifNilUse: false)) + .toggleStyle(fioriToggleStyle) + ).typeErased + } +} + +private extension Binding { + static func convert(from value: Binding, ifNilUse defaultValue: Bool) -> Binding { + Binding( + get: { + value.wrappedValue ?? defaultValue + }, + set: { + value.wrappedValue = $0 + } + ) + } +} + +/// Experiemental Fiori switch/toggle style +public struct FioriToggleStyle: ToggleStyle { + @ScaledMetric var scale: CGFloat = 1 + + let labelColor: Color + + let onColor: Color + let offColor: Color + + let onThumbColor: Color + let offThumbColor: Color + + let onBorderColor: Color + let offBorderColor: Color + + public init( + labelColor: Color = Color.preferredColor(.primaryLabel), + onColor: Color = Color.preferredColor(.tintColor), + offColor: Color = Color.preferredColor(.secondaryFill), + onThumbColor: Color = Color.preferredColor(.baseWhite), + offThumbColor: Color = Color.preferredColor(.baseWhite), + onBorderColor: Color = Color.preferredColor(.separator), + offBorderColor: Color = Color.preferredColor(.separator) + ) { + self.labelColor = labelColor + + self.onColor = onColor + self.offColor = offColor + + self.onThumbColor = onThumbColor + self.offThumbColor = offThumbColor + + self.onBorderColor = onBorderColor + self.offBorderColor = offBorderColor + } + + public func makeBody(configuration: Self.Configuration) -> some View { + HStack { + configuration.label + .font(.fiori(forTextStyle: .subheadline, weight: .bold, isItalic: false, isCondensed: false)) + .foregroundColor(labelColor) + + Spacer() + ZStack { + RoundedRectangle(cornerRadius: 16 * scale, style: .circular) + .stroke(configuration.isOn ? onBorderColor : offBorderColor, lineWidth: 0.5 * scale) + .frame(width: 51 * scale, height: 30 * scale) + + RoundedRectangle(cornerRadius: 16 * scale, style: .circular) + .fill(configuration.isOn ? onColor : offColor) + .frame(width: 51 * scale, height: 30 * scale) + .overlay( + Circle() + .fill(configuration.isOn ? onThumbColor : offThumbColor) + .shadow(radius: 1 * scale, x: 0, y: 1 * scale) + .padding(1.5 * scale) + .offset(x: configuration.isOn ? 10 * scale : -10 * scale)) + .animation(Animation.easeInOut(duration: 0.2), value: configuration.isOn) + .frame(minHeight: 44) + .onTapGesture { configuration.isOn.toggle() } + } + } + .frame(minHeight: 44) + } +} + +struct FioriToggleStyleKey: EnvironmentKey { + public static var defaultValue: any ToggleStyle = FioriToggleStyle() +} + +extension EnvironmentValues { + var fioriToggleStyle: any ToggleStyle { + get { + self[FioriToggleStyleKey.self] + } + set { + self[FioriToggleStyleKey.self] = newValue + } + } +} + +/* + @available(iOS 14.0, macOS 11.0, *) + struct SwitchPickerLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SwitchPicker(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } + } + */ + +private struct TestSwitchPicker: View { + @State var v1: Bool? = true + @State var v2: Bool? = false + @State var v3: Bool? = nil + + var body: some View { + VStack { + SwitchPickerItem(value: $v1, hint: nil) + SwitchPickerItem(value: $v2, hint: nil) + SwitchPickerItem(value: $v3, hint: nil) + } + } +} + +#Preview { + TestSwitchPicker() + .frame(width: 375) +} diff --git a/Sources/FioriSwiftUICore/_generated/Components/Component+Protocols.generated.swift b/Sources/FioriSwiftUICore/_generated/Components/Component+Protocols.generated.swift index 9ffbfc4de..ba02aa975 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/Component+Protocols.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/Component+Protocols.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -158,6 +158,14 @@ public protocol FootnoteIconsComponent { var footnoteIcons: [TextOrIcon]? { get } } +public protocol LeftIconComponent { + var leftIcon: Image? { get } +} + +public protocol RightIconComponent { + var rightIcon: Image? { get } +} + public protocol ActionComponent { var actionText: String? { get } @@ -194,10 +202,51 @@ public protocol KpiProgressComponent : KpiComponent { var fraction: Double? { get } } +public protocol OptionListPickerComponent : AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: [Int] { get set } + // sourcery: no_view + var valueOptions: [String] { get } + // sourcery: default.value=nil + // sourcery: no_view + var hint: String? { get } +} + public protocol ProgressIndicatorComponent { var progressIndicatorText: String? { get } } +public protocol SliderPickerComponent : AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: Int? { get set } + // sourcery: default.value=nil + // sourcery: no_view + var formatter: String? { get } + // sourcery: default.value=0 + // sourcery: no_view + var minimumValue: Int { get } + // sourcery: default.value=100 + // sourcery: no_view + var maximumValue: Int { get } + // sourcery: default.value=nil + // sourcery: no_view + var hint: String? { get } +} + +public protocol SwitchPickerComponent : AnyObject { + // sourcery: bindingProperty + // sourcery: no_view + var value: Bool? { get set } + // sourcery: default.value=nil + // sourcery: no_view + var name: String? { get } + // sourcery: default.value=nil + // sourcery: no_view + var hint: String? { get } +} + public protocol TextInputComponent : AnyObject { // sourcery: bindingPropertyOptional=.constant("") var textInputValue: String { get set } diff --git a/Sources/FioriSwiftUICore/_generated/Components/ComponentProtocols+Extension.generated.swift b/Sources/FioriSwiftUICore/_generated/Components/ComponentProtocols+Extension.generated.swift index 97eae186c..013e39d75 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/ComponentProtocols+Extension.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/ComponentProtocols+Extension.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -142,12 +142,24 @@ public extension KpiProgressComponent { } } +public extension LeftIconComponent { + var leftIcon: Image? { + return nil + } +} + public extension LowerBoundTitleComponent { var lowerBoundTitle: String? { return nil } } +public extension OptionListPickerComponent { + var hint: String? { + return nil + } +} + public extension PlaceholderComponent { var placeholder: String? { return nil @@ -160,6 +172,12 @@ public extension ProgressIndicatorComponent { } } +public extension RightIconComponent { + var rightIcon: Image? { + return nil + } +} + public extension SecondActionTitleComponent { var secondActionTitle: String? { return nil @@ -184,6 +202,28 @@ public extension SecondaryValuesAxisTitleComponent { } } +public extension SliderPickerComponent { + var formatter: String? { + return nil + } + + var minimumValue: Int { + return 0 + } + + var maximumValue: Int { + return 100 + } + + var hint: String? { + return nil + } + + var value: Int? { + return nil + } +} + public extension StatusComponent { var status: TextOrIcon? { return nil @@ -202,6 +242,20 @@ public extension SubtitleComponent { } } +public extension SwitchPickerComponent { + var name: String? { + return nil + } + + var hint: String? { + return nil + } + + var value: Bool? { + return nil + } +} + public extension TagsComponent { var tags: [String]? { return nil diff --git a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift index 43459f573..09eb4a960 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -146,19 +146,23 @@ struct FootnoteIconsModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct ActionTextModifierKey: EnvironmentKey { +struct LeftIconModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct ActionItemsModifierKey: EnvironmentKey { +struct RightIconModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct ProgressIndicatorTextModifierKey: EnvironmentKey { +struct ActionTextModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct NodeModifierKey: EnvironmentKey { +struct ActionItemsModifierKey: EnvironmentKey { + public static let defaultValue = AnyViewModifier { $0 } +} + +struct ProgressIndicatorTextModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } @@ -182,6 +186,10 @@ struct CancelActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } +struct ItemsModifierKey: EnvironmentKey { + public static let defaultValue = AnyViewModifier { $0 } +} + struct ProgressIndicatorModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } @@ -206,6 +214,18 @@ struct SaveActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } +struct NodeModifierKey: EnvironmentKey { + public static let defaultValue = AnyViewModifier { $0 } +} + +struct ResetActionModifierKey: EnvironmentKey { + public static let defaultValue = AnyViewModifier { $0 } +} + +struct ApplyActionModifierKey: EnvironmentKey { + public static let defaultValue = AnyViewModifier { $0 } +} + struct NextActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } diff --git a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift index 016d1dda8..63d866699 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -184,6 +184,16 @@ extension EnvironmentValues { set { self[FootnoteIconsModifierKey.self] = newValue } } + public var leftIconModifier: AnyViewModifier { + get { return self[LeftIconModifierKey.self] } + set { self[LeftIconModifierKey.self] = newValue } + } + + public var rightIconModifier: AnyViewModifier { + get { return self[RightIconModifierKey.self] } + set { self[RightIconModifierKey.self] = newValue } + } + public var actionTextModifier: AnyViewModifier { get { return self[ActionTextModifierKey.self] } set { self[ActionTextModifierKey.self] = newValue } @@ -199,11 +209,6 @@ extension EnvironmentValues { set { self[ProgressIndicatorTextModifierKey.self] = newValue } } - public var nodeModifier: AnyViewModifier { - get { return self[NodeModifierKey.self] } - set { self[NodeModifierKey.self] = newValue } - } - public var textInputValueModifier: AnyViewModifier { get { return self[TextInputValueModifierKey.self] } set { self[TextInputValueModifierKey.self] = newValue } @@ -229,6 +234,11 @@ extension EnvironmentValues { set { self[CancelActionModifierKey.self] = newValue } } + public var itemsModifier: AnyViewModifier { + get { return self[ItemsModifierKey.self] } + set { self[ItemsModifierKey.self] = newValue } + } + public var progressIndicatorModifier: AnyViewModifier { get { return self[ProgressIndicatorModifierKey.self] } set { self[ProgressIndicatorModifierKey.self] = newValue } @@ -259,6 +269,21 @@ extension EnvironmentValues { set { self[SaveActionModifierKey.self] = newValue } } + public var nodeModifier: AnyViewModifier { + get { return self[NodeModifierKey.self] } + set { self[NodeModifierKey.self] = newValue } + } + + public var resetActionModifier: AnyViewModifier { + get { return self[ResetActionModifierKey.self] } + set { self[ResetActionModifierKey.self] = newValue } + } + + public var applyActionModifier: AnyViewModifier { + get { return self[ApplyActionModifierKey.self] } + set { self[ApplyActionModifierKey.self] = newValue } + } + public var nextActionModifier: AnyViewModifier { get { return self[NextActionModifierKey.self] } set { self[NextActionModifierKey.self] = newValue } @@ -463,6 +488,16 @@ public extension View { self.environment(\.footnoteIconsModifier, AnyViewModifier(transform)) } + @ViewBuilder + func leftIconModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.leftIconModifier, AnyViewModifier(transform)) + } + + @ViewBuilder + func rightIconModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.rightIconModifier, AnyViewModifier(transform)) + } + @ViewBuilder func actionTextModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { self.environment(\.actionTextModifier, AnyViewModifier(transform)) @@ -478,11 +513,6 @@ public extension View { self.environment(\.progressIndicatorTextModifier, AnyViewModifier(transform)) } - @ViewBuilder - func nodeModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { - self.environment(\.nodeModifier, AnyViewModifier(transform)) - } - @ViewBuilder func textInputValueModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { self.environment(\.textInputValueModifier, AnyViewModifier(transform)) @@ -508,6 +538,11 @@ public extension View { self.environment(\.cancelActionModifier, AnyViewModifier(transform)) } + @ViewBuilder + func itemsModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.itemsModifier, AnyViewModifier(transform)) + } + @ViewBuilder func progressIndicatorModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { self.environment(\.progressIndicatorModifier, AnyViewModifier(transform)) @@ -538,6 +573,21 @@ public extension View { self.environment(\.saveActionModifier, AnyViewModifier(transform)) } + @ViewBuilder + func nodeModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.nodeModifier, AnyViewModifier(transform)) + } + + @ViewBuilder + func resetActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.resetActionModifier, AnyViewModifier(transform)) + } + + @ViewBuilder + func applyActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.applyActionModifier, AnyViewModifier(transform)) + } + @ViewBuilder func nextActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { self.environment(\.nextActionModifier, AnyViewModifier(transform)) diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/Action+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/Action+API.generated.swift index a36f5da8a..0aeec1c2e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/Action+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/Action+API.generated.swift @@ -1,10 +1,10 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI public struct Action { @Environment(\.actionTextModifier) private var actionTextModifier - @Environment(\.sharedAction) var sharedAction + @Environment(\.sharedAction) var sharedAction var _actionText: String? = nil var _didSelectAction: (() -> Void)? = nil diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivationScreen+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivationScreen+API.generated.swift index c0eb23804..5a6f63971 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivationScreen+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivationScreen+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItem+API.generated.swift index ef252474e..b24da74d6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift index 889906674..ad1be3a39 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ActivityItems+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/AvatarStack+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/AvatarStack+API.generated.swift index 41064f0e0..d47083cb8 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/AvatarStack+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/AvatarStack+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift index aafed23a8..3567b7ba4 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ContactItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/DurationPicker+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/DurationPicker+API.generated.swift index b2aaccf9d..aeabd3523 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/DurationPicker+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/DurationPicker+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/EULAView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/EULAView+API.generated.swift index 65ac59e5a..450035e07 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/EULAView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/EULAView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/EmptyStateView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/EmptyStateView+API.generated.swift index e7c4e9566..bdf6e695d 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/EmptyStateView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/EmptyStateView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBar+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBar+API.generated.swift new file mode 100644 index 000000000..9b92d59b7 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBar+API.generated.swift @@ -0,0 +1,47 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public struct FilterFeedbackBar { + @Environment(\.itemsModifier) private var itemsModifier + + var _items: Items + var _onUpdate: (() -> Void)? + + + private var isModelInit: Bool = false + private var isOnUpdateNil: Bool = false + + public init( + @ViewBuilder items: () -> Items, + onUpdate: (() -> Void)? = nil + ) { + self._items = items() + self._onUpdate = onUpdate + } + + @ViewBuilder var items: some View { + if isModelInit { + _items.modifier(itemsModifier.concat(Fiori.FilterFeedbackBar.items).concat(Fiori.FilterFeedbackBar.itemsCumulative)) + } else { + _items.modifier(itemsModifier.concat(Fiori.FilterFeedbackBar.items)) + } + } + + +} + +extension FilterFeedbackBar where Items == _SortFilterMenuItemContainer { + + public init(model: FilterFeedbackBarModel) { + self.init(items: Binding<[[SortFilterItem]]>(get: { model.items }, set: { model.items = $0 }), onUpdate: model.onUpdate) + } + + public init(items: Binding<[[SortFilterItem]]>, onUpdate: (() -> Void)? = nil) { + self._items = _SortFilterMenuItemContainer(items: items) + self._onUpdate = onUpdate + + isModelInit = true + isOnUpdateNil = onUpdate == nil ? true : false + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarButton+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarButton+API.generated.swift new file mode 100644 index 000000000..c4ecff09a --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarButton+API.generated.swift @@ -0,0 +1,63 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public struct FilterFeedbackBarButton { + @Environment(\.leftIconModifier) private var leftIconModifier + @Environment(\.titleModifier) private var titleModifier + @Environment(\.optionListPickerStyle) var optionListPickerStyle + + let _leftIcon: LeftIcon + let _title: Title + let _isSelected: Bool + + + private var isModelInit: Bool = false + private var isLeftIconNil: Bool = false + + public init( + @ViewBuilder leftIcon: () -> LeftIcon, + @ViewBuilder title: () -> Title, + isSelected: Bool + ) { + self._leftIcon = leftIcon() + self._title = title() + self._isSelected = isSelected + } + + @ViewBuilder var leftIcon: some View { + if isModelInit { + _leftIcon.modifier(leftIconModifier.concat(Fiori.FilterFeedbackBarButton.leftIcon).concat(Fiori.FilterFeedbackBarButton.leftIconCumulative)) + } else { + _leftIcon.modifier(leftIconModifier.concat(Fiori.FilterFeedbackBarButton.leftIcon)) + } + } + @ViewBuilder var title: some View { + if isModelInit { + _title.modifier(titleModifier.concat(Fiori.FilterFeedbackBarButton.title).concat(Fiori.FilterFeedbackBarButton.titleCumulative)) + } else { + _title.modifier(titleModifier.concat(Fiori.FilterFeedbackBarButton.title)) + } + } + + var isLeftIconEmptyView: Bool { + ((isModelInit && isLeftIconNil) || LeftIcon.self == EmptyView.self) ? true : false + } +} + +extension FilterFeedbackBarButton where LeftIcon == _ConditionalContent, + Title == Text { + + public init(model: FilterFeedbackBarButtonModel) { + self.init(leftIcon: model.leftIcon, title: model.title, isSelected: model.isSelected) + } + + public init(leftIcon: Image? = nil, title: String, isSelected: Bool) { + self._leftIcon = leftIcon != nil ? ViewBuilder.buildEither(first: leftIcon!) : ViewBuilder.buildEither(second: EmptyView()) + self._title = Text(title) + self._isSelected = isSelected + + isModelInit = true + isLeftIconNil = leftIcon == nil ? true : false + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarItem+API.generated.swift new file mode 100644 index 000000000..0991e3c85 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FilterFeedbackBarItem+API.generated.swift @@ -0,0 +1,82 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public struct FilterFeedbackBarItem { + @Environment(\.leftIconModifier) private var leftIconModifier + @Environment(\.titleModifier) private var titleModifier + @Environment(\.rightIconModifier) private var rightIconModifier + @Environment(\.filterFeedbackBarStyle) var filterFeedbackBarStyle + + let _leftIcon: LeftIcon + let _title: Title + let _rightIcon: RightIcon + let _isSelected: Bool + @StateObject var context: SortFilterContext = SortFilterContext() + + private var isModelInit: Bool = false + private var isLeftIconNil: Bool = false + private var isRightIconNil: Bool = false + + public init( + @ViewBuilder leftIcon: () -> LeftIcon, + @ViewBuilder title: () -> Title, + @ViewBuilder rightIcon: () -> RightIcon, + isSelected: Bool + ) { + self._leftIcon = leftIcon() + self._title = title() + self._rightIcon = rightIcon() + self._isSelected = isSelected + } + + @ViewBuilder var leftIcon: some View { + if isModelInit { + _leftIcon.modifier(leftIconModifier.concat(Fiori.FilterFeedbackBarItem.leftIcon).concat(Fiori.FilterFeedbackBarItem.leftIconCumulative)) + } else { + _leftIcon.modifier(leftIconModifier.concat(Fiori.FilterFeedbackBarItem.leftIcon)) + } + } + @ViewBuilder var title: some View { + if isModelInit { + _title.modifier(titleModifier.concat(Fiori.FilterFeedbackBarItem.title).concat(Fiori.FilterFeedbackBarItem.titleCumulative)) + } else { + _title.modifier(titleModifier.concat(Fiori.FilterFeedbackBarItem.title)) + } + } + @ViewBuilder var rightIcon: some View { + if isModelInit { + _rightIcon.modifier(rightIconModifier.concat(Fiori.FilterFeedbackBarItem.rightIcon).concat(Fiori.FilterFeedbackBarItem.rightIconCumulative)) + } else { + _rightIcon.modifier(rightIconModifier.concat(Fiori.FilterFeedbackBarItem.rightIcon)) + } + } + + var isLeftIconEmptyView: Bool { + ((isModelInit && isLeftIconNil) || LeftIcon.self == EmptyView.self) ? true : false + } + + var isRightIconEmptyView: Bool { + ((isModelInit && isRightIconNil) || RightIcon.self == EmptyView.self) ? true : false + } +} + +extension FilterFeedbackBarItem where LeftIcon == _ConditionalContent, + Title == Text, + RightIcon == _ConditionalContent { + + public init(model: FilterFeedbackBarItemModel) { + self.init(leftIcon: model.leftIcon, title: model.title, rightIcon: model.rightIcon, isSelected: model.isSelected) + } + + public init(leftIcon: Image? = nil, title: String, rightIcon: Image? = nil, isSelected: Bool) { + self._leftIcon = leftIcon != nil ? ViewBuilder.buildEither(first: leftIcon!) : ViewBuilder.buildEither(second: EmptyView()) + self._title = Text(title) + self._rightIcon = rightIcon != nil ? ViewBuilder.buildEither(first: rightIcon!) : ViewBuilder.buildEither(second: EmptyView()) + self._isSelected = isSelected + + isModelInit = true + isLeftIconNil = leftIcon == nil ? true : false + isRightIconNil = rightIcon == nil ? true : false + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/FootnoteIconStack+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FootnoteIconStack+API.generated.swift index b57a76399..b7a3ce8a1 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/FootnoteIconStack+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/FootnoteIconStack+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/HeaderChart+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/HeaderChart+API.generated.swift index 674f14769..4431f8f5a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/HeaderChart+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/HeaderChart+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/IconStack+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/IconStack+API.generated.swift index 3d1c29176..1c53a9bdb 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/IconStack+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/IconStack+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift index 4a6a731e2..dce169502 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIItem+API.generated.swift index 5aea7091b..6502d4295 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIProgressItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIProgressItem+API.generated.swift index 6f25339b5..65ed06049 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIProgressItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KPIProgressItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KeyValueItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KeyValueItem+API.generated.swift index bce427d71..4437850b6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/KeyValueItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/KeyValueItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ListPickerItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ListPickerItem+API.generated.swift index 645f8168c..9c8759c81 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ListPickerItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ListPickerItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift index 3a683a90f..e52f7115a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ObjectHeader+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -26,11 +26,11 @@ public struct ObjectHeader + var _valueOptions: [String] + var _hint: String? = nil + var _onTap: ((_ index: Int) -> Void)? = nil + + public init(model: OptionListPickerItemModel) { + self.init(value: Binding<[Int]>(get: { model.value }, set: { model.value = $0 }), valueOptions: model.valueOptions, hint: model.hint, onTap: model.onTap) + } + + public init(value: Binding<[Int]>, valueOptions: [String] = [], hint: String? = nil, onTap: ((_ index: Int) -> Void)? = nil) { + self._value = value + self._valueOptions = valueOptions + self._hint = hint + self._onTap = onTap + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ProgressIndicator+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ProgressIndicator+API.generated.swift index c131b7808..cb79f0f12 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/ProgressIndicator+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/ProgressIndicator+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchableListView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchableListView+API.generated.swift index de2854950..3a1d89ba0 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchableListView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchableListView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -11,9 +11,9 @@ public struct SearchableListView { let _cancelAction: CancelActionView let _doneAction: DoneActionView - var dataHandler: (() -> ())? = nil var isTopLevel: Bool = true var contentView: AnyView? = nil + var dataHandler: (() -> ())? = nil private var isModelInit: Bool = false private var isCancelActionNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SectionHeader+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SectionHeader+API.generated.swift index 31b0d35dc..d81d562f6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SectionHeader+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SectionHeader+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBar+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBar+API.generated.swift index 43a5d8462..505b467ba 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBar+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBar+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBarListItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBarListItem+API.generated.swift index 96e3e2abe..5b8b6512a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBarListItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SideBarListItem+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift index 0b9ce9aca..c88c2e8a9 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SignatureCaptureView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI import Combine @@ -19,32 +19,32 @@ public struct SignatureCaptureView Void)? let _onDelete: (() -> Void)? - var timestampFormatter: DateFormatter? - @State var currentDrawing = Drawing() - var titleColor = Color.preferredColor(.primaryLabel) - var hidesXmark = false - @State var fullSignatureImage: UIImage? var strokeWidth: CGFloat = 3.0 - public private(set) var _heightDidChangePublisher = CurrentValueSubject(0) - var addsTimestampInImage: Bool = false - var strokeColor = Color.preferredColor(.primaryLabel) - var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) - var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) var cropsImage = false - var _drawingViewMaxHeight: CGFloat? + public private(set) var _heightDidChangePublisher = CurrentValueSubject(0) + @State var isSaved = false + var timestampFormatter: DateFormatter? + var xmarkColor = Color.preferredColor(.quarternaryLabel) + @State var isEditing = false + var watermarkText: String? var watermarkTextColor: Color = .preferredColor(.tertiaryLabel) + @State var fullSignatureImage: UIImage? + @State var drawings = [Drawing]() + @State var currentDrawing = Drawing() + var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) var signatureLineColor = Color.preferredColor(.quarternaryLabel) - var appliesTintColorToImage = true - @State var isSaved = false + var hidesXmark = false + var watermarkTextAlignment: NSTextAlignment = .natural let _drawingViewMinHeight: CGFloat = 256 + var titleColor = Color.preferredColor(.primaryLabel) + var strokeColor = Color.preferredColor(.primaryLabel) @State var isReenterTapped = false - var watermarkTextAlignment: NSTextAlignment = .natural - var watermarkText: String? + var _drawingViewMaxHeight: CGFloat? var titleFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) - @State var isEditing = false + var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) + var addsTimestampInImage: Bool = false var hidesSignatureLine = false - var xmarkColor = Color.preferredColor(.quarternaryLabel) - @State var drawings = [Drawing]() + var appliesTintColorToImage = true private var isModelInit: Bool = false private var isTitleNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SingleStep+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SingleStep+API.generated.swift index 2ff29626d..7be62a842 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SingleStep+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SingleStep+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -14,15 +14,15 @@ public struct SingleStep + var _formatter: String? = nil + var _minimumValue: Int + var _maximumValue: Int + var _hint: String? = nil + + public init(model: SliderPickerItemModel) { + self.init(value: Binding(get: { model.value }, set: { model.value = $0 }), formatter: model.formatter, minimumValue: model.minimumValue, maximumValue: model.maximumValue, hint: model.hint) + } + + public init(value: Binding, formatter: String? = nil, minimumValue: Int = 0, maximumValue: Int = 100, hint: String? = nil) { + self._value = value + self._formatter = formatter + self._minimumValue = minimumValue + self._maximumValue = maximumValue + self._hint = hint + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift new file mode 100644 index 000000000..f4e7a8207 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SortFilterView+API.generated.swift @@ -0,0 +1,116 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public struct SortFilterView { + @Environment(\.titleModifier) private var titleModifier + @Environment(\.itemsModifier) private var itemsModifier + @Environment(\.cancelActionModifier) private var cancelActionModifier + @Environment(\.resetActionModifier) private var resetActionModifier + @Environment(\.applyActionModifier) private var applyActionModifier + @Environment(\.dismiss) var dismiss + + let _title: Title + var _items: Items + let _cancelAction: CancelActionView + let _resetAction: ResetActionView + let _applyAction: ApplyActionView + let _onUpdate: (() -> Void)? + @StateObject var context: SortFilterContext = SortFilterContext() + + private var isModelInit: Bool = false + private var isCancelActionNil: Bool = false + private var isResetActionNil: Bool = false + private var isApplyActionNil: Bool = false + private var isOnUpdateNil: Bool = false + + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder cancelAction: () -> CancelActionView, + @ViewBuilder resetAction: () -> ResetActionView, + @ViewBuilder applyAction: () -> ApplyActionView, + onUpdate: (() -> Void)? = nil + ) { + self._title = title() + self._items = items() + self._cancelAction = cancelAction() + self._resetAction = resetAction() + self._applyAction = applyAction() + self._onUpdate = onUpdate + } + + @ViewBuilder var title: some View { + if isModelInit { + _title.modifier(titleModifier.concat(Fiori.SortFilterView.title).concat(Fiori.SortFilterView.titleCumulative)) + } else { + _title.modifier(titleModifier.concat(Fiori.SortFilterView.title)) + } + } + @ViewBuilder var items: some View { + if isModelInit { + _items.modifier(itemsModifier.concat(Fiori.SortFilterView.items).concat(Fiori.SortFilterView.itemsCumulative)) + } else { + _items.modifier(itemsModifier.concat(Fiori.SortFilterView.items)) + } + } + @ViewBuilder var cancelAction: some View { + if isModelInit { + _cancelAction.modifier(cancelActionModifier.concat(Fiori.SortFilterView.cancelAction).concat(Fiori.SortFilterView.cancelActionCumulative)) + } else { + _cancelAction.modifier(cancelActionModifier.concat(Fiori.SortFilterView.cancelAction)) + } + } + @ViewBuilder var resetAction: some View { + if isModelInit { + _resetAction.modifier(resetActionModifier.concat(Fiori.SortFilterView.resetAction).concat(Fiori.SortFilterView.resetActionCumulative)) + } else { + _resetAction.modifier(resetActionModifier.concat(Fiori.SortFilterView.resetAction)) + } + } + @ViewBuilder var applyAction: some View { + if isModelInit { + _applyAction.modifier(applyActionModifier.concat(Fiori.SortFilterView.applyAction).concat(Fiori.SortFilterView.applyActionCumulative)) + } else { + _applyAction.modifier(applyActionModifier.concat(Fiori.SortFilterView.applyAction)) + } + } + + var isCancelActionEmptyView: Bool { + ((isModelInit && isCancelActionNil) || CancelActionView.self == EmptyView.self) ? true : false + } + + var isResetActionEmptyView: Bool { + ((isModelInit && isResetActionNil) || ResetActionView.self == EmptyView.self) ? true : false + } + + var isApplyActionEmptyView: Bool { + ((isModelInit && isApplyActionNil) || ApplyActionView.self == EmptyView.self) ? true : false + } +} + +extension SortFilterView where Title == Text, + Items == _SortFilterCFGItemContainer, + CancelActionView == _ConditionalContent, + ResetActionView == _ConditionalContent, + ApplyActionView == _ConditionalContent { + + public init(model: SortFilterViewModel) { + self.init(title: model.title, items: Binding<[[SortFilterItem]]>(get: { model.items }, set: { model.items = $0 }), cancelAction: model.cancelAction != nil ? Action(model: model.cancelAction!) : nil, resetAction: model.resetAction != nil ? Action(model: model.resetAction!) : nil, applyAction: model.applyAction != nil ? Action(model: model.applyAction!) : nil, onUpdate: model.onUpdate) + } + + public init(title: String, items: Binding<[[SortFilterItem]]>, cancelAction: Action? = Action(model: _CancelActionDefault()), resetAction: Action? = Action(model: _ResetActionDefault()), applyAction: Action? = Action(model: _ApplyActionDefault()), onUpdate: (() -> Void)? = nil) { + self._title = Text(title) + self._items = _SortFilterCFGItemContainer(items: items) + self._cancelAction = cancelAction != nil ? ViewBuilder.buildEither(first: cancelAction!) : ViewBuilder.buildEither(second: EmptyView()) + self._resetAction = resetAction != nil ? ViewBuilder.buildEither(first: resetAction!) : ViewBuilder.buildEither(second: EmptyView()) + self._applyAction = applyAction != nil ? ViewBuilder.buildEither(first: applyAction!) : ViewBuilder.buildEither(second: EmptyView()) + self._onUpdate = onUpdate + + isModelInit = true + isCancelActionNil = cancelAction == nil ? true : false + isResetActionNil = resetAction == nil ? true : false + isApplyActionNil = applyAction == nil ? true : false + isOnUpdateNil = onUpdate == nil ? true : false + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift index c8d40cf5b..7f22af7a7 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/StepProgressIndicator+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI @@ -8,16 +8,15 @@ public struct StepProgressIndicator let _title: Title let _action: ActionView let _steps: Steps let _cancelAction: CancelActionView - @State var isPresented: Bool = false var stepItems: [StepItem] = [] + @State var scrollBounds: CGRect = .zero + @State var isPresented: Bool = false + @State var stepFrames: [String: CGRect] = [:] var axis: Axis = .horizontal private var isModelInit: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SwitchPickerItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SwitchPickerItem+API.generated.swift new file mode 100644 index 000000000..041003bf9 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SwitchPickerItem+API.generated.swift @@ -0,0 +1,22 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public struct SwitchPickerItem { + @Environment(\.fioriToggleStyle) var fioriToggleStyle + @Environment(\.filterFeedbackBarStyle) var filterFeedbackBarStyle + + var _value: Binding + var _name: String? = nil + var _hint: String? = nil + + public init(model: SwitchPickerItemModel) { + self.init(value: Binding(get: { model.value }, set: { model.value = $0 }), name: model.name, hint: model.hint) + } + + public init(value: Binding, name: String? = nil, hint: String? = nil) { + self._value = value + self._name = name + self._hint = hint + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/TagStack+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/TagStack+API.generated.swift index 8f86c7938..2de639225 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/TagStack+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/TagStack+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/TextInput+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/TextInput+API.generated.swift index fd0e8fc6a..1b55e3ccf 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/TextInput+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/TextInput+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentForm+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentForm+API.generated.swift index eb6e7c529..d6ce23e78 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentForm+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentForm+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentPage+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentPage+API.generated.swift index b18fa216f..05fd52135 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentPage+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentPage+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentView+API.generated.swift index abbf69143..2870a841c 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/UserConsentView+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.3.4 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/WelcomeScreen+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/WelcomeScreen+API.generated.swift index 8960e8fd2..31096bfbd 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/WelcomeScreen+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/WelcomeScreen+API.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/Action+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/Action+View.generated.swift index 69f9ea0e4..310af2a48 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/Action+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/Action+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/Action+View.swift` //TODO: Implement Action `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivationScreen+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivationScreen+View.generated.swift index acd525ec3..3f0fec536 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivationScreen+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivationScreen+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ActivationScreen+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItem+View.generated.swift index fcfa3a694..08bb1072a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ActivityItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItems+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItems+View.generated.swift index a5e295852..0ec79e48d 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItems+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ActivityItems+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ActivityItems+View.swift` //TODO: Implement ActivityItems `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/AvatarStack+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/AvatarStack+View.generated.swift index 76f84df80..9ee25d499 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/AvatarStack+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/AvatarStack+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/AvatarStack+View.swift` //TODO: Implement AvatarStack `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ContactItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ContactItem+View.generated.swift index 2d967fa76..20f72a38e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ContactItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ContactItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ContactItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/DurationPicker+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/DurationPicker+View.generated.swift index 59a0a84f2..6c082882e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/DurationPicker+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/DurationPicker+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/DurationPicker+View.swift` //TODO: Implement DurationPicker `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EULAView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EULAView+View.generated.swift index 86e7abcb8..d7a9eec54 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EULAView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EULAView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/EULAView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EmptyStateView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EmptyStateView+View.generated.swift index 2a7d0dbb3..abbf98015 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EmptyStateView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/EmptyStateView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/EmptyStateView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBar+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBar+View.generated.swift new file mode 100644 index 000000000..15be1da22 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBar+View.generated.swift @@ -0,0 +1,58 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/FilterFeedbackBar+View.swift` +//TODO: Implement default Fiori style definitions as `ViewModifier` +//TODO: Implement FilterFeedbackBar `View` body +//TODO: Implement LibraryContentProvider + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +extension Fiori { + enum FilterFeedbackBar { + typealias Items = EmptyModifier + typealias ItemsCumulative = EmptyModifier + + // TODO: - substitute type-specific ViewModifier for EmptyModifier + /* + // replace `typealias Subtitle = EmptyModifier` with: + + struct Subtitle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .foregroundColor(.preferredColor(.primary3)) + } + } + */ + static let items = Items() + static let itemsCumulative = ItemsCumulative() + } +} + +// FIXME: - Implement FilterFeedbackBar View body + +extension FilterFeedbackBar: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement FilterFeedbackBar specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct FilterFeedbackBarLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(FilterFeedbackBar(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarButton+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarButton+View.generated.swift new file mode 100644 index 000000000..4d7d4fa2c --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarButton+View.generated.swift @@ -0,0 +1,62 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/FilterFeedbackBarButton+View.swift` +//TODO: Implement default Fiori style definitions as `ViewModifier` +//TODO: Implement FilterFeedbackBarButton `View` body +//TODO: Implement LibraryContentProvider + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +extension Fiori { + enum FilterFeedbackBarButton { + typealias LeftIcon = EmptyModifier + typealias LeftIconCumulative = EmptyModifier + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + + // TODO: - substitute type-specific ViewModifier for EmptyModifier + /* + // replace `typealias Subtitle = EmptyModifier` with: + + struct Subtitle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .foregroundColor(.preferredColor(.primary3)) + } + } + */ + static let leftIcon = LeftIcon() + static let title = Title() + static let leftIconCumulative = LeftIconCumulative() + static let titleCumulative = TitleCumulative() + } +} + +// FIXME: - Implement FilterFeedbackBarButton View body + +extension FilterFeedbackBarButton: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement FilterFeedbackBarButton specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct FilterFeedbackBarButtonLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(FilterFeedbackBarButton(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarItem+View.generated.swift new file mode 100644 index 000000000..61f4b96bd --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FilterFeedbackBarItem+View.generated.swift @@ -0,0 +1,66 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/FilterFeedbackBarItem+View.swift` +//TODO: Implement default Fiori style definitions as `ViewModifier` +//TODO: Implement FilterFeedbackBarItem `View` body +//TODO: Implement LibraryContentProvider + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +extension Fiori { + enum FilterFeedbackBarItem { + typealias LeftIcon = EmptyModifier + typealias LeftIconCumulative = EmptyModifier + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + typealias RightIcon = EmptyModifier + typealias RightIconCumulative = EmptyModifier + + // TODO: - substitute type-specific ViewModifier for EmptyModifier + /* + // replace `typealias Subtitle = EmptyModifier` with: + + struct Subtitle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .foregroundColor(.preferredColor(.primary3)) + } + } + */ + static let leftIcon = LeftIcon() + static let title = Title() + static let rightIcon = RightIcon() + static let leftIconCumulative = LeftIconCumulative() + static let titleCumulative = TitleCumulative() + static let rightIconCumulative = RightIconCumulative() + } +} + +// FIXME: - Implement FilterFeedbackBarItem View body + +extension FilterFeedbackBarItem: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement FilterFeedbackBarItem specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct FilterFeedbackBarItemLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(FilterFeedbackBarItem(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FootnoteIconStack+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FootnoteIconStack+View.generated.swift index ebcdc09a4..f2eca588b 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FootnoteIconStack+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/FootnoteIconStack+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/FootnoteIconStack+View.swift` //TODO: Implement FootnoteIconStack `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/HeaderChart+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/HeaderChart+View.generated.swift index 06b5dea5f..502a3d570 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/HeaderChart+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/HeaderChart+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/HeaderChart+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/IconStack+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/IconStack+View.generated.swift index 8f61241e8..e56b2c995 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/IconStack+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/IconStack+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/IconStack+View.swift` //TODO: Implement IconStack `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/InfoView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/InfoView+View.generated.swift index cf0554f1b..319a94e04 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/InfoView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/InfoView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/InfoView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIItem+View.generated.swift index 91d13436a..680791796 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/KPIItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIProgressItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIProgressItem+View.generated.swift index ba4e67922..4bf67eb31 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIProgressItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KPIProgressItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/KPIProgressItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KeyValueItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KeyValueItem+View.generated.swift index 859f171b3..a15d53f65 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KeyValueItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/KeyValueItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/KeyValueItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ListPickerItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ListPickerItem+View.generated.swift index 6afb225ba..aeca3b08a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ListPickerItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ListPickerItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ListPickerItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectHeader+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectHeader+View.generated.swift index a0425bcdf..98b3a880e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectHeader+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectHeader+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ObjectHeader+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectItem+View.generated.swift index 6274bdd89..690593d17 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ObjectItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ObjectItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionChip+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionChip+View.generated.swift new file mode 100644 index 000000000..237897746 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionChip+View.generated.swift @@ -0,0 +1,62 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/OptionChip+View.swift` +//TODO: Implement default Fiori style definitions as `ViewModifier` +//TODO: Implement OptionChip `View` body +//TODO: Implement LibraryContentProvider + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +extension Fiori { + enum OptionChip { + typealias LeftIcon = EmptyModifier + typealias LeftIconCumulative = EmptyModifier + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + + // TODO: - substitute type-specific ViewModifier for EmptyModifier + /* + // replace `typealias Subtitle = EmptyModifier` with: + + struct Subtitle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .foregroundColor(.preferredColor(.primary3)) + } + } + */ + static let leftIcon = LeftIcon() + static let title = Title() + static let leftIconCumulative = LeftIconCumulative() + static let titleCumulative = TitleCumulative() + } +} + +// FIXME: - Implement OptionChip View body + +extension OptionChip: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement OptionChip specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct OptionChipLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(OptionChip(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionListPickerItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionListPickerItem+View.generated.swift new file mode 100644 index 000000000..d752cf79d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/OptionListPickerItem+View.generated.swift @@ -0,0 +1,34 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/OptionListPickerItem+View.swift` +//TODO: Implement OptionListPickerItem `View` body + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +// FIXME: - Implement OptionListPickerItem View body + +extension OptionListPickerItem: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement OptionListPickerItem specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct OptionListPickerItemLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(OptionListPickerItem(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ProgressIndicator+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ProgressIndicator+View.generated.swift index 9629dd327..345f7c946 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ProgressIndicator+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/ProgressIndicator+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/ProgressIndicator+View.swift` //TODO: Implement ProgressIndicator `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SearchableListView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SearchableListView+View.generated.swift index cf9e0bb04..8cd580281 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SearchableListView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SearchableListView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SearchableListView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SectionHeader+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SectionHeader+View.generated.swift index b2352f072..881c2ffcf 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SectionHeader+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SectionHeader+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SectionHeader+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBar+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBar+View.generated.swift index a7054d593..7e9b57cd6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBar+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBar+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SideBar+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBarListItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBarListItem+View.generated.swift index c6fea5c51..e3b646b1c 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBarListItem+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SideBarListItem+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SideBarListItem+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SignatureCaptureView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SignatureCaptureView+View.generated.swift index 121c8e243..4c0f280d5 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SignatureCaptureView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SignatureCaptureView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SignatureCaptureView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SingleStep+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SingleStep+View.generated.swift index fb7eba7f5..d0df23357 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SingleStep+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SingleStep+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SingleStep+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SliderPickerItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SliderPickerItem+View.generated.swift new file mode 100644 index 000000000..b68975e38 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SliderPickerItem+View.generated.swift @@ -0,0 +1,34 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SliderPickerItem+View.swift` +//TODO: Implement SliderPickerItem `View` body + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +// FIXME: - Implement SliderPickerItem View body + +extension SliderPickerItem: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement SliderPickerItem specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct SliderPickerItemLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SliderPickerItem(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SortFilterView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SortFilterView+View.generated.swift new file mode 100644 index 000000000..f4ab8a5e6 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SortFilterView+View.generated.swift @@ -0,0 +1,74 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SortFilterView+View.swift` +//TODO: Implement default Fiori style definitions as `ViewModifier` +//TODO: Implement SortFilterView `View` body +//TODO: Implement LibraryContentProvider + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +extension Fiori { + enum SortFilterView { + typealias Title = EmptyModifier + typealias TitleCumulative = EmptyModifier + typealias Items = EmptyModifier + typealias ItemsCumulative = EmptyModifier + typealias CancelAction = EmptyModifier + typealias CancelActionCumulative = EmptyModifier + typealias ResetAction = EmptyModifier + typealias ResetActionCumulative = EmptyModifier + typealias ApplyAction = EmptyModifier + typealias ApplyActionCumulative = EmptyModifier + + // TODO: - substitute type-specific ViewModifier for EmptyModifier + /* + // replace `typealias Subtitle = EmptyModifier` with: + + struct Subtitle: ViewModifier { + func body(content: Content) -> some View { + content + .font(.body) + .foregroundColor(.preferredColor(.primary3)) + } + } + */ + static let title = Title() + static let items = Items() + static let cancelAction = CancelAction() + static let resetAction = ResetAction() + static let applyAction = ApplyAction() + static let titleCumulative = TitleCumulative() + static let itemsCumulative = ItemsCumulative() + static let cancelActionCumulative = CancelActionCumulative() + static let resetActionCumulative = ResetActionCumulative() + static let applyActionCumulative = ApplyActionCumulative() + } +} + +// FIXME: - Implement SortFilterView View body + +extension SortFilterView: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement SortFilterView specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct SortFilterViewLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SortFilterView(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/StepProgressIndicator+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/StepProgressIndicator+View.generated.swift index a9e2642a6..25f7a0d1f 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/StepProgressIndicator+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/StepProgressIndicator+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/StepProgressIndicator+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SwitchPickerItem+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SwitchPickerItem+View.generated.swift new file mode 100644 index 000000000..e37cd3f8a --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/SwitchPickerItem+View.generated.swift @@ -0,0 +1,34 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +//TODO: Copy commented code to new file: `FioriSwiftUICore/Views/SwitchPickerItem+View.swift` +//TODO: Implement SwitchPickerItem `View` body + +/// - Important: to make `@Environment` properties (e.g. `horizontalSizeClass`), internally accessible +/// to extensions, add as sourcery annotation in `FioriSwiftUICore/Models/ModelDefinitions.swift` +/// to declare a wrapped property +/// e.g.: `// sourcery: add_env_props = ["horizontalSizeClass"]` + +/* +import SwiftUI + +// FIXME: - Implement Fiori style definitions + +// FIXME: - Implement SwitchPickerItem View body + +extension SwitchPickerItem: View { + public var body: some View { + <# View body #> + } +} + +// FIXME: - Implement SwitchPickerItem specific LibraryContentProvider + +@available(iOS 14.0, macOS 11.0, *) +struct SwitchPickerItemLibraryContent: LibraryContentProvider { + @LibraryContentBuilder + var views: [LibraryItem] { + LibraryItem(SwitchPickerItem(model: LibraryPreviewData.Person.laurelosborn), + category: .control) + } +} +*/ diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TagStack+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TagStack+View.generated.swift index b3fa2c385..334605746 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TagStack+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TagStack+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/TagStack+View.swift` //TODO: Implement TagStack `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TextInput+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TextInput+View.generated.swift index f37a74ec2..c688271b3 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TextInput+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/TextInput+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/TextInput+View.swift` //TODO: Implement TextInput `View` body diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentForm+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentForm+View.generated.swift index 114cc907a..d73de8415 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentForm+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentForm+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/UserConsentForm+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentPage+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentPage+View.generated.swift index 4a9560816..f4e687a65 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentPage+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentPage+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/UserConsentPage+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentView+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentView+View.generated.swift index 6e0a28bdf..5706cdd0f 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentView+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/UserConsentView+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/UserConsentView+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/WelcomeScreen+View.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/WelcomeScreen+View.generated.swift index 1e98e76a6..9f6aa9c6f 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/WelcomeScreen+View.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Boilerplate/WelcomeScreen+View.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT //TODO: Copy commented code to new file: `FioriSwiftUICore/Views/WelcomeScreen+View.swift` //TODO: Implement default Fiori style definitions as `ViewModifier` diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivationScreen+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivationScreen+Init.generated.swift index 203df5bf3..735df792e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivationScreen+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivationScreen+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivityItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivityItem+Init.generated.swift index ba64c2504..30ef388a7 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivityItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ActivityItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ContactItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ContactItem+Init.generated.swift index dde985970..9a75be77e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ContactItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ContactItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EULAView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EULAView+Init.generated.swift index 9632561e1..7a4c7fa01 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EULAView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EULAView+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EmptyStateView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EmptyStateView+Init.generated.swift index 54ea0b8f3..c15f248e3 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EmptyStateView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/EmptyStateView+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBar+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBar+Init.generated.swift new file mode 100644 index 000000000..922a0296d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBar+Init.generated.swift @@ -0,0 +1,3 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarButton+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarButton+Init.generated.swift new file mode 100644 index 000000000..fd9df8849 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarButton+Init.generated.swift @@ -0,0 +1,16 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +extension FilterFeedbackBarButton where LeftIcon == EmptyView { + public init( + @ViewBuilder title: () -> Title, + isSelected: Bool + ) { + self.init( + leftIcon: { EmptyView() }, + title: title, + isSelected: isSelected + ) + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarItem+Init.generated.swift new file mode 100644 index 000000000..80725f317 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/FilterFeedbackBarItem+Init.generated.swift @@ -0,0 +1,47 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +extension FilterFeedbackBarItem where LeftIcon == EmptyView { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder rightIcon: () -> RightIcon, + isSelected: Bool + ) { + self.init( + leftIcon: { EmptyView() }, + title: title, + rightIcon: rightIcon, + isSelected: isSelected + ) + } +} + +extension FilterFeedbackBarItem where RightIcon == EmptyView { + public init( + @ViewBuilder leftIcon: () -> LeftIcon, + @ViewBuilder title: () -> Title, + isSelected: Bool + ) { + self.init( + leftIcon: leftIcon, + title: title, + rightIcon: { EmptyView() }, + isSelected: isSelected + ) + } +} + +extension FilterFeedbackBarItem where LeftIcon == EmptyView, RightIcon == EmptyView { + public init( + @ViewBuilder title: () -> Title, + isSelected: Bool + ) { + self.init( + leftIcon: { EmptyView() }, + title: title, + rightIcon: { EmptyView() }, + isSelected: isSelected + ) + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/HeaderChart+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/HeaderChart+Init.generated.swift index eb70cc78f..03e6cd4ea 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/HeaderChart+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/HeaderChart+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift index b44821db9..857080768 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIItem+Init.generated.swift index c2a853422..832ed61ed 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIProgressItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIProgressItem+Init.generated.swift index 7d3b8294e..cadf57c84 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIProgressItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KPIProgressItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KeyValueItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KeyValueItem+Init.generated.swift index 445fc48b0..c5ed698bd 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KeyValueItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/KeyValueItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ListPickerItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ListPickerItem+Init.generated.swift index e696ed295..8d7723e85 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ListPickerItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ListPickerItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectHeader+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectHeader+Init.generated.swift index be8e7bd6e..dd286f770 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectHeader+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectHeader+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectItem+Init.generated.swift index e8f8762df..3869973fe 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/ObjectItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/OptionListPicker+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/OptionListPicker+Init.generated.swift new file mode 100644 index 000000000..922a0296d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/OptionListPicker+Init.generated.swift @@ -0,0 +1,3 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SearchableListView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SearchableListView+Init.generated.swift index ddf92fd1e..ca8aad04f 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SearchableListView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SearchableListView+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SectionHeader+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SectionHeader+Init.generated.swift index 2b459d50b..5f36acfd2 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SectionHeader+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SectionHeader+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBar+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBar+Init.generated.swift index a06da1500..dae788a7f 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBar+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBar+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBarListItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBarListItem+Init.generated.swift index 230e7bac7..fe818f783 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBarListItem+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SideBarListItem+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SignatureCaptureView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SignatureCaptureView+Init.generated.swift index 11724973c..0a2b2342c 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SignatureCaptureView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SignatureCaptureView+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SingleStep+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SingleStep+Init.generated.swift index ed599e814..1f6123cb6 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SingleStep+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SingleStep+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SortFilterView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SortFilterView+Init.generated.swift new file mode 100644 index 000000000..65f6a658d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SortFilterView+Init.generated.swift @@ -0,0 +1,131 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +extension SortFilterView where CancelActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder resetAction: () -> ResetActionView, + @ViewBuilder applyAction: () -> ApplyActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: { Action(model: _CancelActionDefault()) }, + resetAction: resetAction, + applyAction: applyAction, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where ResetActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder cancelAction: () -> CancelActionView, + @ViewBuilder applyAction: () -> ApplyActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: cancelAction, + resetAction: { Action(model: _ResetActionDefault()) }, + applyAction: applyAction, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where ApplyActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder cancelAction: () -> CancelActionView, + @ViewBuilder resetAction: () -> ResetActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: cancelAction, + resetAction: resetAction, + applyAction: { Action(model: _ApplyActionDefault()) }, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where CancelActionView == Action, ResetActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder applyAction: () -> ApplyActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: { Action(model: _CancelActionDefault()) }, + resetAction: { Action(model: _ResetActionDefault()) }, + applyAction: applyAction, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where CancelActionView == Action, ApplyActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder resetAction: () -> ResetActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: { Action(model: _CancelActionDefault()) }, + resetAction: resetAction, + applyAction: { Action(model: _ApplyActionDefault()) }, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where ResetActionView == Action, ApplyActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + @ViewBuilder cancelAction: () -> CancelActionView, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: cancelAction, + resetAction: { Action(model: _ResetActionDefault()) }, + applyAction: { Action(model: _ApplyActionDefault()) }, + onUpdate: onUpdate + ) + } +} + +extension SortFilterView where CancelActionView == Action, ResetActionView == Action, ApplyActionView == Action { + public init( + @ViewBuilder title: () -> Title, + @ViewBuilder items: () -> Items, + onUpdate: (() -> Void)? = nil + ) { + self.init( + title: title, + items: items, + cancelAction: { Action(model: _CancelActionDefault()) }, + resetAction: { Action(model: _ResetActionDefault()) }, + applyAction: { Action(model: _ApplyActionDefault()) }, + onUpdate: onUpdate + ) + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/StepProgressIndicator+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/StepProgressIndicator+Init.generated.swift index 8b255b33e..5462bf323 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/StepProgressIndicator+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/StepProgressIndicator+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SwitchPickerItem+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SwitchPickerItem+Init.generated.swift new file mode 100644 index 000000000..922a0296d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/SwitchPickerItem+Init.generated.swift @@ -0,0 +1,3 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentForm+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentForm+Init.generated.swift index b19eb94e9..754e7f47e 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentForm+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentForm+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentPage+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentPage+Init.generated.swift index f6dcd91f2..cd28cc3d2 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentPage+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentPage+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentView+Init.generated.swift index ae11a6d16..922a0296d 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/UserConsentView+Init.generated.swift @@ -1,3 +1,3 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/WelcomeScreen+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/WelcomeScreen+Init.generated.swift index 8546c6bcb..350e65b8c 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/WelcomeScreen+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/WelcomeScreen+Init.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ActivationScreenModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ActivationScreenModel+Extensions.generated.swift index e47a97459..f80fc68a9 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ActivationScreenModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ActivationScreenModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI 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 88b6790ca..569102c2d 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ContactItemModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EULAViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EULAViewModel+Extensions.generated.swift index d9e862263..0035907bb 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EULAViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EULAViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EmptyStateViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EmptyStateViewModel+Extensions.generated.swift index 6950262ce..608dfa25b 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EmptyStateViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/EmptyStateViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/FilterFeedbackBarModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/FilterFeedbackBarModel+Extensions.generated.swift new file mode 100644 index 000000000..8ce7ea931 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/FilterFeedbackBarModel+Extensions.generated.swift @@ -0,0 +1,9 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public extension FilterFeedbackBarModel { + var onUpdate: (() -> Void)? { + return nil + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift index 979cb1d5e..afa6119fd 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ObjectItemModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ObjectItemModel+Extensions.generated.swift index 9b100ce3f..e0f1b11f8 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ObjectItemModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/ObjectItemModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/OptionListPickerItemModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/OptionListPickerItemModel+Extensions.generated.swift new file mode 100644 index 000000000..5d016c78c --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/OptionListPickerItemModel+Extensions.generated.swift @@ -0,0 +1,9 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public extension OptionListPickerItemModel { + var onTap: ((_ index: Int) -> Void)? { + return nil + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SearchableListViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SearchableListViewModel+Extensions.generated.swift index 5e512395e..61b44f3ae 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SearchableListViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SearchableListViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SignatureCaptureViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SignatureCaptureViewModel+Extensions.generated.swift index 1aee926f2..215622715 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SignatureCaptureViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SignatureCaptureViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SingleStepModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SingleStepModel+Extensions.generated.swift index f0e2aa4b8..22dc46bec 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SingleStepModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SingleStepModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SortFilterViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SortFilterViewModel+Extensions.generated.swift new file mode 100644 index 000000000..a433876de --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/SortFilterViewModel+Extensions.generated.swift @@ -0,0 +1,21 @@ +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import SwiftUI + +public extension SortFilterViewModel { + var cancelAction: ActionModel? { + return _CancelActionDefault() + } + + var resetAction: ActionModel? { + return _ResetActionDefault() + } + + var applyAction: ActionModel? { + return _ApplyActionDefault() + } + + var onUpdate: (() -> Void)? { + return nil + } +} diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/StepProgressIndicatorModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/StepProgressIndicatorModel+Extensions.generated.swift index df642597d..e7b0fddfc 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/StepProgressIndicatorModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/StepProgressIndicatorModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentFormModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentFormModel+Extensions.generated.swift index 88b53a8dc..4d1c41c9c 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentFormModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentFormModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentPageModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentPageModel+Extensions.generated.swift index 77bdde15a..90ea245ae 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentPageModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentPageModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentViewModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentViewModel+Extensions.generated.swift index 861578b36..9b984699a 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/UserConsentViewModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/WelcomeScreenModel+Extensions.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/WelcomeScreenModel+Extensions.generated.swift index 486061bba..b3ccc10ac 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/WelcomeScreenModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/WelcomeScreenModel+Extensions.generated.swift @@ -1,4 +1,4 @@ -// Generated using Sourcery 1.1.1 — https://github.com/krzysztofzablocki/Sourcery +// Generated using Sourcery 1.2.0 — https://github.com/krzysztofzablocki/Sourcery // DO NOT EDIT import SwiftUI diff --git a/Sources/FioriSwiftUICore/_localization/en.lproj/FioriSwiftUICore.strings b/Sources/FioriSwiftUICore/_localization/en.lproj/FioriSwiftUICore.strings index cbc6342ae..558aaee13 100644 --- a/Sources/FioriSwiftUICore/_localization/en.lproj/FioriSwiftUICore.strings +++ b/Sources/FioriSwiftUICore/_localization/en.lproj/FioriSwiftUICore.strings @@ -141,3 +141,9 @@ /* XBUT: voice over label for row selection status in DataTable */ "not selected" = "not selected"; + +/* XBUT: calendar time component label */ +"Time" = "Time"; + +/* XBUT: slider default value label formatter for integer */ +"Value: %d" = "Value: %d";