diff --git a/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift b/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift index 800185326..29e7a8ce9 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift @@ -1,7 +1,7 @@ import FioriSwiftUICore import SwiftUI -class InfoViewDataModel: InfoViewModel { +class InfoViewDataModel: _InfoViewModel { var title: String = "SAP BTP SDK for iOS" var descriptionText: String? = "SAP BTP SDK for iOS enables you to quickly develop your own native apps, with Swift. The SDK extends the standard Swift Apple iOS frameworks with the reusable UI components from the SAP Fiori for iOS Design Language, and provides APIs which seamlessly integrate apps with SAP BTP services. " var showLoadingIndicator: Bool? = true @@ -45,12 +45,19 @@ struct InfoViewSample: View { var body: some View { VStack { - InfoView(model: self.model) + let loadingIndicator = LoadingIndicator(title: "", isPresented: .constant(true)) + + InfoView(title: AttributedString(self.model.title), descriptionText: AttributedString(self.model.descriptionText ?? ""), action: FioriButton(title: "Next", action: { _ in + print("InfoView Primary button clicked") + }), secondaryAction: FioriButton(title: "Start Tutorial", action: { _ in + print("InfoView secondary button clicked") + }), loadingIndicator: loadingIndicator) } } } struct InfoViewWithLoadingLabel: View { + @State var showLoadingView: Bool = true private var model = InfoViewDataModel() public init() { @@ -59,7 +66,16 @@ struct InfoViewWithLoadingLabel: View { var body: some View { VStack { - InfoView(model: self.model) + let loadingIndicator = LoadingIndicator(title: { + Text(AttributedString(self.model.loadingIndicatorText ?? "")) + .font(.fiori(forTextStyle: .body)) + }, progress: { ProgressView() }, isPresented: $showLoadingView) + + InfoView(title: AttributedString(self.model.title), descriptionText: AttributedString(self.model.descriptionText ?? ""), action: FioriButton(title: "Next", action: { _ in + print("InfoView Primary button clicked") + }), secondaryAction: FioriButton(title: "Start Tutorial", action: { _ in + print("InfoView secondary button clicked") + }), loadingIndicator: loadingIndicator) } } } @@ -71,7 +87,59 @@ struct InfoViewCustomized: View { var body: some View { VStack { - InfoView(model: self.model) + let loadingIndicator = LoadingIndicator(title: { Text("") }, progress: { ProgressView().progressViewStyle(CircularProgressViewStyle(tint: .red)) }, isPresented: .constant(true)) + + InfoView(title: { Text(AttributedString(self.model.title)) }, + descriptionText: { Text(AttributedString(self.model.descriptionText ?? "")).foregroundColor(.blue) }, + action: { + FioriButton(title: "Next") { _ in + print("InfoView Primary button clicked") + } + }, + secondaryAction: { + Button("Start Tutorial") { + print("InfoView secondary button clicked") + } + }, + loadingIndicator: { loadingIndicator }) + } + } +} + +struct _InfoViewSample: View { + private var model = InfoViewDataModel() + + public init() {} + + var body: some View { + VStack { + _InfoView(model: self.model) + } + } +} + +struct _InfoViewWithLoadingLabel: View { + private var model = InfoViewDataModel() + + public init() { + self.model.loadingIndicatorText = "Loading..." + } + + var body: some View { + VStack { + _InfoView(model: self.model) + } + } +} + +struct _InfoViewCustomized: View { + private var model = InfoViewDataModel() + + public init() {} + + var body: some View { + VStack { + _InfoView(model: self.model) .descriptionTextModifier { $0.font(.fiori(forTextStyle: .subheadline)).foregroundColor(.blue) } .actionModifier { $0.foregroundColor(.blue) } .loadingIndicatorStyle(CustomLoadingStyle()) diff --git a/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/OnboardingExamples.swift b/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/OnboardingExamples.swift index f260e7fea..2f63de24d 100644 --- a/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/OnboardingExamples.swift +++ b/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/OnboardingExamples.swift @@ -23,13 +23,12 @@ struct OnboardingExamples: View { Text("ActivationScreen") } - NavigationLink( - destination: InfoViewExamples(), - label: { + if self._isNewObjectItem { + NavigationLink( + destination: InfoViewExamples(isNewInfoView: true)) + { Text("InfoView Examples") } - ) - if self._isNewObjectItem { NavigationLink( destination: EULAExamples(isNewEULAView: true)) { @@ -46,6 +45,11 @@ struct OnboardingExamples: View { Text("AuthenticationScreen Examples") } } else { + NavigationLink( + destination: InfoViewExamples()) + { + Text("_InfoView Examples") + } NavigationLink( destination: EULAExamples()) { @@ -120,23 +124,35 @@ struct ActivationScreenExamples: View { } struct InfoViewExamples: View { + var isNewInfoView = false var body: some View { List { - NavigationLink( - destination: InfoViewSample(), - label: { - Text("InfoView") + NavigationLink { + if self.isNewInfoView { + InfoViewSample() + } else { + _InfoViewSample() } - ) - NavigationLink( - destination: InfoViewWithLoadingLabel()) - { + } label: { + Text("InfoView") + } + NavigationLink { + if self.isNewInfoView { + InfoViewWithLoadingLabel() + } else { + _InfoViewWithLoadingLabel() + } + } label: { Text("InfoView With Loading Label") } - NavigationLink( - destination: InfoViewCustomized()) - { + NavigationLink { + if self.isNewInfoView { + InfoViewCustomized() + } else { + _InfoViewCustomized() + } + } label: { Text("InfoView Customized") } }.navigationBarTitle("InfoView Examples", displayMode: .inline) diff --git a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift index 8d4eeb6c3..09f1a898b 100644 --- a/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift +++ b/Sources/FioriSwiftUICore/Models/ModelDefinitions.swift @@ -223,7 +223,7 @@ public protocol _ActivationScreenModel: TitleComponent, DescriptionTextComponent public protocol ActivationScreenModel {} // sourcery: generated_component_composite -public protocol InfoViewModel: TitleComponent, DescriptionTextComponent { +public protocol _InfoViewModel: TitleComponent, DescriptionTextComponent { // sourcery: default.value = nil // sourcery: no_view var showLoadingIndicator: Bool? { get } @@ -239,6 +239,10 @@ public protocol InfoViewModel: TitleComponent, DescriptionTextComponent { var secondaryAction: _ActionModel? { get } } +/// Deprecated InfoViewModel +@available(*, deprecated, renamed: "_InfoViewModel", message: "Will be removed in the future release. Please create InfoViewModel with other initializers instead.") +public protocol InfoViewModel {} + // sourcery: generated_component_composite // sourcery: virtualPropContentHeight = "@State var contentHeight: CGFloat = .zero" // sourcery: add_env_props = ["presentationMode"] diff --git a/Sources/FioriSwiftUICore/Views/InfoView+View.swift b/Sources/FioriSwiftUICore/Views/_InfoView+View.swift similarity index 84% rename from Sources/FioriSwiftUICore/Views/InfoView+View.swift rename to Sources/FioriSwiftUICore/Views/_InfoView+View.swift index b986f6129..534d490f3 100644 --- a/Sources/FioriSwiftUICore/Views/InfoView+View.swift +++ b/Sources/FioriSwiftUICore/Views/_InfoView+View.swift @@ -6,7 +6,7 @@ import SwiftUI extension Fiori { - enum InfoView { + enum _InfoView { struct Title: ViewModifier { func body(content: Content) -> some View { content @@ -60,7 +60,7 @@ extension Fiori { } } -extension InfoView: View { +extension _InfoView: View { public var body: some View { @State var isPresented: Bool = _showLoadingIndicator ?? false return VStack { @@ -86,6 +86,6 @@ extension InfoView: View { struct InfoViewLibraryContent: LibraryContentProvider { @LibraryContentBuilder var views: [LibraryItem] { - LibraryItem(InfoView(title: "SAP BTP SDK for iOS", descriptionText: "SAP BTP SDK for iOS enables you to quickly develop your own native apps, with Swift. The SDK extends the standard Swift Apple iOS frameworks with the reusable UI components from the SAP Fiori for iOS Design Language, and provides APIs which seamlessly integrate apps with SAP BTP services.", showLoadingIndicator: false, loadingIndicatorText: "", action: _Action(actionText: "Primary Button"), secondaryAction: _Action(actionText: "Secondary Button"))) + LibraryItem(_InfoView(title: "SAP BTP SDK for iOS", descriptionText: "SAP BTP SDK for iOS enables you to quickly develop your own native apps, with Swift. The SDK extends the standard Swift Apple iOS frameworks with the reusable UI components from the SAP Fiori for iOS Design Language, and provides APIs which seamlessly integrate apps with SAP BTP services.", showLoadingIndicator: false, loadingIndicatorText: "", action: _Action(actionText: "Primary Button"), secondaryAction: _Action(actionText: "Secondary Button"))) } } diff --git a/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift b/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift index 0daad19ee..0af26e738 100755 --- a/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift +++ b/Sources/FioriSwiftUICore/_ComponentProtocols/CompositeComponentProtocols.swift @@ -2015,6 +2015,77 @@ protocol _AuthenticationComponent: _DetailImageComponent, _TitleComponent, _Subt var didSignIn: (() -> Void)? { get } } +/// `InfoView` is a multifunctional view for displaying Information or Splash screen. +/// The UI elements can be displayed or hidden depending on functionality. +/// The text properties must be set before displaying the view. +/// +/// ## Initialization Parameters +/// - Required: +/// - title: The primary heading text (AttributedString or ViewBuilder) +/// - Optional: +/// - descriptionText: Supplemental information text +/// - action: Primary action control +/// - secondaryAction: Secondary action control +/// - loadingIndicator: Loading state visualization +/// +/// ## Usage +/// ## AttributedString Shortcut (Quick Setup) +/// ``` +/// InfoView( +/// title: AttributedString("Title"), +/// descriptionText: AttributedString("Description Text"), +/// action: FioriButton(title: "Update Now") { +/// startUpdate() +/// }, +/// secondaryAction: FioriButton(title: "Remind Later") { +/// scheduleReminder() +/// } +/// ) +/// ``` +/// +/// ## ViewBuilder Approach (Fully Customizable) +/// ``` +/// // Custom loading indicator with red circular style +/// let loadingIndicator = LoadingIndicator( +/// title: { Text("") }, +/// progress: { +/// ProgressView() +/// .progressViewStyle(CircularProgressViewStyle(tint: .red)) +/// }, +/// isPresented: .constant(true) +/// ) +/// +/// InfoView( +/// title: { +/// HStack(spacing: 8) { +/// Image(systemName: "exclamationmark.triangle.fill") +/// .foregroundColor(.yellow) +/// Text("Title") +/// .font(.headline) +/// } +/// }, +/// descriptionText: { +/// Text(AttributedString(self.model.descriptionText ?? "")) // Dynamic title from model +/// .foregroundColor(.blue) // Custom text color +/// }, +/// action: { +/// Toggle("Trust Device", isOn: $trustDevice) +/// .toggleStyle(.switch) +/// }, +/// secondaryAction: { +/// Button("Start Tutorial") { +/// print("InfoView secondary button clicked") +/// } +/// }, +/// loadingIndicator: { loadingIndicator } +/// ) +/// ``` +// sourcery: CompositeComponent +protocol _InfoViewComponent: _TitleComponent, _DescriptionTextComponent, _ActionComponent, _SecondaryActionComponent { + // sourcery: @ViewBuilder + var loadingIndicator: LoadingIndicator? { get set } +} + /// The Activation Screen is displayed after the Welcome Screen with title, description text, email input text field, action button and secondary action. // sourcery: CompositeComponent protocol _ActivationScreenComponent: _TitleComponent, _DescriptionTextComponent, _FootnoteComponent, _ActionComponent, _SecondaryActionComponent { diff --git a/Sources/FioriSwiftUICore/_FioriStyles/InfoViewStyle.fiori.swift b/Sources/FioriSwiftUICore/_FioriStyles/InfoViewStyle.fiori.swift new file mode 100644 index 000000000..ead335d21 --- /dev/null +++ b/Sources/FioriSwiftUICore/_FioriStyles/InfoViewStyle.fiori.swift @@ -0,0 +1,138 @@ +import FioriThemeManager +import Foundation +import SwiftUI + +// Base Layout style +public struct InfoViewBaseStyle: InfoViewStyle { + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + ZStack { + VStack { + ScrollView(.vertical) { + VStack { + configuration.title + #if os(visionOS) + .padding(.bottom, -16) + #endif + configuration.descriptionText + .padding(.top, 16) + #if !os(visionOS) + .padding(.bottom, 250) + #else + .padding(.bottom, 16) + #endif + configuration.action + #if os(visionOS) + .padding(.bottom, 16) + #endif + configuration.secondaryAction + } + } + .padding(.top, 2) + .padding(.bottom, 2) + .padding(.leading, getInfoViewLeftPadding()) + .padding(.trailing, getInfoViewLeftPadding()) + .scrollIndicators(.hidden) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + + configuration.loadingIndicator + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + } +} + +// Default fiori styles +extension InfoViewFioriStyle { + struct ContentFioriStyle: InfoViewStyle { + func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + } + } + + struct TitleFioriStyle: TitleStyle { + let infoViewConfiguration: InfoViewConfiguration + + func makeBody(_ configuration: TitleConfiguration) -> some View { + #if !os(visionOS) + Title(configuration) + .font(.fiori(forTextStyle: .title1).weight(.bold)) + .foregroundColor(.preferredColor(.primaryLabel)) + .multilineTextAlignment(.center) + #else + Title(configuration) + .font(.fiori(forTextStyle: .extraLargeTitle2)) + .multilineTextAlignment(.center) + #endif + } + } + + struct DescriptionTextFioriStyle: DescriptionTextStyle { + let infoViewConfiguration: InfoViewConfiguration + + func makeBody(_ configuration: DescriptionTextConfiguration) -> some View { + #if !os(visionOS) + DescriptionText(configuration) + .font(.fiori(forTextStyle: .body)) + .foregroundColor(.preferredColor(.primaryLabel)) + .multilineTextAlignment(.center) + #else + DescriptionText(configuration) + .font(.fiori(forTextStyle: .body)) + .multilineTextAlignment(.center) + #endif + } + } + + struct ActionFioriStyle: ActionStyle { + let infoViewConfiguration: InfoViewConfiguration + + func makeBody(_ configuration: ActionConfiguration) -> some View { + #if !os(visionOS) + Action(configuration) + .frame(minWidth: 201, minHeight: 44) + .padding(EdgeInsets(top: 9, leading: 16, bottom: 9, trailing: 16)) + .font(.fiori(forTextStyle: .body)) + #else + Action(configuration) + .frame(minWidth: 280, minHeight: 52) + .clipShape(Capsule()) + #endif + } + } + + struct SecondaryActionFioriStyle: SecondaryActionStyle { + let infoViewConfiguration: InfoViewConfiguration + + func makeBody(_ configuration: SecondaryActionConfiguration) -> some View { + #if !os(visionOS) + SecondaryAction(configuration) + .fioriButtonStyle(FioriPlainButtonStyle()) + .frame(minWidth: 201, minHeight: 44) + .padding(EdgeInsets(top: 9, leading: 16, bottom: 9, trailing: 16)) + .font(.fiori(forTextStyle: .body)) + #else + SecondaryAction(configuration) + .fioriButtonStyle(FioriPlainButtonStyle()) + .frame(minWidth: 280, minHeight: 52) + .clipShape(Capsule()) + #endif + } + } +} + +func getInfoViewLeftPadding() -> CGFloat { + var margin: CGFloat = 35 + #if !os(visionOS) + if UIDevice.current.userInterfaceIdiom == .pad { + if UIDevice.current.orientation.isPortrait { + margin = 157 + } else { + margin = 296 + } + } + #else + margin = 40 + return margin + #endif + return margin +} diff --git a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift index 1a97dbc77..11101e318 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentKey+Styles.generated.swift @@ -170,19 +170,19 @@ struct TextInputValueModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct ActionModifierKey: EnvironmentKey { +struct CancelActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct SecondaryActionModifierKey: EnvironmentKey { +struct DoneActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct CancelActionModifierKey: EnvironmentKey { +struct ActionModifierKey: EnvironmentKey { public static let defaultValue = AnyViewModifier { $0 } } -struct DoneActionModifierKey: EnvironmentKey { +struct SecondaryActionModifierKey: 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 16fe266ed..ad9c8c3f1 100644 --- a/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/Components/EnvironmentValue+Styles.generated.swift @@ -214,16 +214,6 @@ extension EnvironmentValues { set { self[TextInputValueModifierKey.self] = newValue } } - public var actionModifier: AnyViewModifier { - get { return self[ActionModifierKey.self] } - set { self[ActionModifierKey.self] = newValue } - } - - public var secondaryActionModifier: AnyViewModifier { - get { return self[SecondaryActionModifierKey.self] } - set { self[SecondaryActionModifierKey.self] = newValue } - } - public var cancelActionModifier: AnyViewModifier { get { return self[CancelActionModifierKey.self] } set { self[CancelActionModifierKey.self] = newValue } @@ -234,6 +224,16 @@ extension EnvironmentValues { set { self[DoneActionModifierKey.self] = newValue } } + public var actionModifier: AnyViewModifier { + get { return self[ActionModifierKey.self] } + set { self[ActionModifierKey.self] = newValue } + } + + public var secondaryActionModifier: AnyViewModifier { + get { return self[SecondaryActionModifierKey.self] } + set { self[SecondaryActionModifierKey.self] = newValue } + } + public var textInputModifier: AnyViewModifier { get { return self[TextInputModifierKey.self] } set { self[TextInputModifierKey.self] = newValue } @@ -514,23 +514,23 @@ public extension View { } @ViewBuilder - func actionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { - self.environment(\.actionModifier, AnyViewModifier(transform)) + func cancelActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.cancelActionModifier, AnyViewModifier(transform)) } @ViewBuilder - func secondaryActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { - self.environment(\.secondaryActionModifier, AnyViewModifier(transform)) + func doneActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.doneActionModifier, AnyViewModifier(transform)) } @ViewBuilder - func cancelActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { - self.environment(\.cancelActionModifier, AnyViewModifier(transform)) + func actionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.actionModifier, AnyViewModifier(transform)) } @ViewBuilder - func doneActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { - self.environment(\.doneActionModifier, AnyViewModifier(transform)) + func secondaryActionModifier(_ transform: @escaping (AnyViewModifier.Content) -> V) -> some View { + self.environment(\.secondaryActionModifier, AnyViewModifier(transform)) } @ViewBuilder diff --git a/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoView.generated.swift b/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoView.generated.swift new file mode 100644 index 000000000..bef17715d --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoView.generated.swift @@ -0,0 +1,159 @@ +// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import Foundation +import SwiftUI + +/// `InfoView` is a multifunctional view for displaying Information or Splash screen. +/// The UI elements can be displayed or hidden depending on functionality. +/// The text properties must be set before displaying the view. +/// +/// ## Initialization Parameters +/// - Required: +/// - title: The primary heading text (AttributedString or ViewBuilder) +/// - Optional: +/// - descriptionText: Supplemental information text +/// - action: Primary action control +/// - secondaryAction: Secondary action control +/// - loadingIndicator: Loading state visualization +/// +/// ## Usage +/// ## AttributedString Shortcut (Quick Setup) +/// ``` +/// InfoView( +/// title: AttributedString("Title"), +/// descriptionText: AttributedString("Description Text"), +/// action: FioriButton(title: "Update Now") { +/// startUpdate() +/// }, +/// secondaryAction: FioriButton(title: "Remind Later") { +/// scheduleReminder() +/// } +/// ) +/// ``` +/// +/// ## ViewBuilder Approach (Fully Customizable) +/// ``` +/// // Custom loading indicator with red circular style +/// let loadingIndicator = LoadingIndicator( +/// title: { Text("") }, +/// progress: { +/// ProgressView() +/// .progressViewStyle(CircularProgressViewStyle(tint: .red)) +/// }, +/// isPresented: .constant(true) +/// ) +/// +/// InfoView( +/// title: { +/// HStack(spacing: 8) { +/// Image(systemName: "exclamationmark.triangle.fill") +/// .foregroundColor(.yellow) +/// Text("Title") +/// .font(.headline) +/// } +/// }, +/// descriptionText: { +/// Text(AttributedString(self.model.descriptionText ?? "")) // Dynamic title from model +/// .foregroundColor(.blue) // Custom text color +/// }, +/// action: { +/// Toggle("Trust Device", isOn: $trustDevice) +/// .toggleStyle(.switch) +/// }, +/// secondaryAction: { +/// Button("Start Tutorial") { +/// print("InfoView secondary button clicked") +/// } +/// }, +/// loadingIndicator: { loadingIndicator } +/// ) +/// ``` +public struct InfoView { + let title: any View + let descriptionText: any View + let action: any View + let secondaryAction: any View + let loadingIndicator: any View + + @Environment(\.infoViewStyle) var style + + var componentIdentifier: String = InfoView.identifier + + fileprivate var _shouldApplyDefaultStyle = true + + public init(@ViewBuilder title: () -> any View, + @ViewBuilder descriptionText: () -> any View = { EmptyView() }, + @ViewBuilder action: () -> any View = { EmptyView() }, + @ViewBuilder secondaryAction: () -> any View = { EmptyView() }, + @ViewBuilder loadingIndicator: () -> any View = { EmptyView() }, + componentIdentifier: String? = InfoView.identifier) + { + self.title = Title(title: title, componentIdentifier: componentIdentifier) + self.descriptionText = DescriptionText(descriptionText: descriptionText, componentIdentifier: componentIdentifier) + self.action = Action(action: action, componentIdentifier: componentIdentifier) + self.secondaryAction = SecondaryAction(secondaryAction: secondaryAction, componentIdentifier: componentIdentifier) + self.loadingIndicator = loadingIndicator() + self.componentIdentifier = componentIdentifier ?? InfoView.identifier + } +} + +public extension InfoView { + static let identifier = "fiori_infoview_component" +} + +public extension InfoView { + init(title: AttributedString, + descriptionText: AttributedString? = nil, + action: FioriButton? = nil, + secondaryAction: FioriButton? = nil, + loadingIndicator: LoadingIndicator? = nil) + { + self.init(title: { Text(title) }, descriptionText: { OptionalText(descriptionText) }, action: { action }, secondaryAction: { secondaryAction }, loadingIndicator: { loadingIndicator }) + } +} + +public extension InfoView { + init(_ configuration: InfoViewConfiguration) { + self.init(configuration, shouldApplyDefaultStyle: false) + } + + internal init(_ configuration: InfoViewConfiguration, shouldApplyDefaultStyle: Bool) { + self.title = configuration.title + self.descriptionText = configuration.descriptionText + self.action = configuration.action + self.secondaryAction = configuration.secondaryAction + self.loadingIndicator = configuration.loadingIndicator + self._shouldApplyDefaultStyle = shouldApplyDefaultStyle + self.componentIdentifier = configuration.componentIdentifier + } +} + +extension InfoView: View { + public var body: some View { + if self._shouldApplyDefaultStyle { + self.defaultStyle() + } else { + self.style.resolve(configuration: .init(componentIdentifier: self.componentIdentifier, title: .init(self.title), descriptionText: .init(self.descriptionText), action: .init(self.action), secondaryAction: .init(self.secondaryAction), loadingIndicator: .init(self.loadingIndicator))).typeErased + .transformEnvironment(\.infoViewStyleStack) { stack in + if !stack.isEmpty { + stack.removeLast() + } + } + } + } +} + +private extension InfoView { + func shouldApplyDefaultStyle(_ bool: Bool) -> some View { + var s = self + s._shouldApplyDefaultStyle = bool + return s + } + + func defaultStyle() -> some View { + InfoView(.init(componentIdentifier: self.componentIdentifier, title: .init(self.title), descriptionText: .init(self.descriptionText), action: .init(self.action), secondaryAction: .init(self.secondaryAction), loadingIndicator: .init(self.loadingIndicator))) + .shouldApplyDefaultStyle(false) + .infoViewStyle(InfoViewFioriStyle.ContentFioriStyle()) + .typeErased + } +} diff --git a/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoViewStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoViewStyle.generated.swift new file mode 100644 index 000000000..32b979dc7 --- /dev/null +++ b/Sources/FioriSwiftUICore/_generated/StyleableComponents/InfoView/InfoViewStyle.generated.swift @@ -0,0 +1,53 @@ +// Generated using Sourcery 2.1.7 — https://github.com/krzysztofzablocki/Sourcery +// DO NOT EDIT +import Foundation +import SwiftUI + +public protocol InfoViewStyle: DynamicProperty { + associatedtype Body: View + + func makeBody(_ configuration: InfoViewConfiguration) -> Body +} + +struct AnyInfoViewStyle: InfoViewStyle { + let content: (InfoViewConfiguration) -> any View + + init(@ViewBuilder _ content: @escaping (InfoViewConfiguration) -> any View) { + self.content = content + } + + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + self.content(configuration).typeErased + } +} + +public struct InfoViewConfiguration { + public var componentIdentifier: String = "fiori_infoview_component" + public let title: Title + public let descriptionText: DescriptionText + public let action: Action + public let secondaryAction: SecondaryAction + public let loadingIndicator: LoadingIndicator + + public typealias Title = ConfigurationViewWrapper + public typealias DescriptionText = ConfigurationViewWrapper + public typealias Action = ConfigurationViewWrapper + public typealias SecondaryAction = ConfigurationViewWrapper + public typealias LoadingIndicator = ConfigurationViewWrapper +} + +extension InfoViewConfiguration { + func isDirectChild(_ componentIdentifier: String) -> Bool { + componentIdentifier == self.componentIdentifier + } +} + +public struct InfoViewFioriStyle: InfoViewStyle { + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .titleStyle(TitleFioriStyle(infoViewConfiguration: configuration)) + .descriptionTextStyle(DescriptionTextFioriStyle(infoViewConfiguration: configuration)) + .actionStyle(ActionFioriStyle(infoViewConfiguration: configuration)) + .secondaryActionStyle(SecondaryActionFioriStyle(infoViewConfiguration: configuration)) + } +} diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift index 52d7c4fc4..25357e268 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ComponentStyleProtocol+Extension.generated.swift @@ -3748,6 +3748,104 @@ public extension IncrementActionStyle where Self == IncrementActionFioriStyle { } } +// MARK: InfoViewStyle + +public extension InfoViewStyle where Self == InfoViewBaseStyle { + static var base: InfoViewBaseStyle { + InfoViewBaseStyle() + } +} + +public extension InfoViewStyle where Self == InfoViewFioriStyle { + static var fiori: InfoViewFioriStyle { + InfoViewFioriStyle() + } +} + +public struct InfoViewTitleStyle: InfoViewStyle { + let style: any TitleStyle + + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .titleStyle(self.style) + .typeErased + } +} + +public extension InfoViewStyle where Self == InfoViewTitleStyle { + static func titleStyle(_ style: some TitleStyle) -> InfoViewTitleStyle { + InfoViewTitleStyle(style: style) + } + + static func titleStyle(@ViewBuilder content: @escaping (TitleConfiguration) -> some View) -> InfoViewTitleStyle { + let style = AnyTitleStyle(content) + return InfoViewTitleStyle(style: style) + } +} + +public struct InfoViewDescriptionTextStyle: InfoViewStyle { + let style: any DescriptionTextStyle + + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .descriptionTextStyle(self.style) + .typeErased + } +} + +public extension InfoViewStyle where Self == InfoViewDescriptionTextStyle { + static func descriptionTextStyle(_ style: some DescriptionTextStyle) -> InfoViewDescriptionTextStyle { + InfoViewDescriptionTextStyle(style: style) + } + + static func descriptionTextStyle(@ViewBuilder content: @escaping (DescriptionTextConfiguration) -> some View) -> InfoViewDescriptionTextStyle { + let style = AnyDescriptionTextStyle(content) + return InfoViewDescriptionTextStyle(style: style) + } +} + +public struct InfoViewActionStyle: InfoViewStyle { + let style: any ActionStyle + + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .actionStyle(self.style) + .typeErased + } +} + +public extension InfoViewStyle where Self == InfoViewActionStyle { + static func actionStyle(_ style: some ActionStyle) -> InfoViewActionStyle { + InfoViewActionStyle(style: style) + } + + static func actionStyle(@ViewBuilder content: @escaping (ActionConfiguration) -> some View) -> InfoViewActionStyle { + let style = AnyActionStyle(content) + return InfoViewActionStyle(style: style) + } +} + +public struct InfoViewSecondaryActionStyle: InfoViewStyle { + let style: any SecondaryActionStyle + + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .secondaryActionStyle(self.style) + .typeErased + } +} + +public extension InfoViewStyle where Self == InfoViewSecondaryActionStyle { + static func secondaryActionStyle(_ style: some SecondaryActionStyle) -> InfoViewSecondaryActionStyle { + InfoViewSecondaryActionStyle(style: style) + } + + static func secondaryActionStyle(@ViewBuilder content: @escaping (SecondaryActionConfiguration) -> some View) -> InfoViewSecondaryActionStyle { + let style = AnySecondaryActionStyle(content) + return InfoViewSecondaryActionStyle(style: style) + } +} + // MARK: InformationViewStyle public extension InformationViewStyle where Self == InformationViewBaseStyle { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift index 3ce3c4419..4f9bec7a8 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/EnvironmentVariables.generated.swift @@ -1557,6 +1557,27 @@ extension EnvironmentValues { } } +// MARK: InfoViewStyle + +struct InfoViewStyleStackKey: EnvironmentKey { + static let defaultValue: [any InfoViewStyle] = [] +} + +extension EnvironmentValues { + var infoViewStyle: any InfoViewStyle { + self.infoViewStyleStack.last ?? .base.concat(.fiori) + } + + var infoViewStyleStack: [any InfoViewStyle] { + get { + self[InfoViewStyleStackKey.self] + } + set { + self[InfoViewStyleStackKey.self] = newValue + } + } +} + // MARK: InformationViewStyle struct InformationViewStyleStackKey: EnvironmentKey { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift index d5893837b..f0a528ca6 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ModifiedStyle.generated.swift @@ -2080,6 +2080,34 @@ public extension IncrementActionStyle { } } +// MARK: InfoViewStyle + +extension ModifiedStyle: InfoViewStyle where Style: InfoViewStyle { + public func makeBody(_ configuration: InfoViewConfiguration) -> some View { + InfoView(configuration) + .infoViewStyle(self.style) + .modifier(self.modifier) + } +} + +public struct InfoViewStyleModifier: ViewModifier { + let style: Style + + public func body(content: Content) -> some View { + content.infoViewStyle(self.style) + } +} + +public extension InfoViewStyle { + func modifier(_ modifier: some ViewModifier) -> some InfoViewStyle { + ModifiedStyle(style: self, modifier: modifier) + } + + func concat(_ style: some InfoViewStyle) -> some InfoViewStyle { + style.modifier(InfoViewStyleModifier(style: self)) + } +} + // MARK: InformationViewStyle extension ModifiedStyle: InformationViewStyle where Style: InformationViewStyle { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift index 759f786aa..0c6dd8c4c 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ResolvedStyle.generated.swift @@ -1187,6 +1187,22 @@ extension IncrementActionStyle { } } +// MARK: InfoViewStyle + +struct ResolvedInfoViewStyle: View { + let style: Style + let configuration: InfoViewConfiguration + var body: some View { + self.style.makeBody(self.configuration) + } +} + +extension InfoViewStyle { + func resolve(configuration: InfoViewConfiguration) -> some View { + ResolvedInfoViewStyle(style: self, configuration: configuration) + } +} + // MARK: InformationViewStyle struct ResolvedInformationViewStyle: View { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift index 8a68a16b2..6a21b5d61 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/View+Extension_.generated.swift @@ -1261,6 +1261,23 @@ public extension View { } } +// MARK: InfoViewStyle + +public extension View { + func infoViewStyle(_ style: some InfoViewStyle) -> some View { + self.transformEnvironment(\.infoViewStyleStack) { stack in + stack.append(style) + } + } + + func infoViewStyle(@ViewBuilder content: @escaping (InfoViewConfiguration) -> some View) -> some View { + self.transformEnvironment(\.infoViewStyleStack) { stack in + let style = AnyInfoViewStyle(content) + stack.append(style) + } + } +} + // MARK: InformationViewStyle public extension View { diff --git a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift index 75bd1c3a4..78eec1715 100644 --- a/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/SupportingFiles/ViewEmptyChecking+Extension.generated.swift @@ -542,6 +542,16 @@ extension IncrementAction: _ViewEmptyChecking { } } +extension InfoView: _ViewEmptyChecking { + public var isEmpty: Bool { + title.isEmpty && + descriptionText.isEmpty && + action.isEmpty && + secondaryAction.isEmpty && + loadingIndicator.isEmpty + } +} + extension InformationView: _ViewEmptyChecking { public var isEmpty: Bool { icon.isEmpty && diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/OptionListPickerItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/OptionListPickerItem+API.generated.swift index 434b85d15..483a3b816 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/OptionListPickerItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/OptionListPickerItem+API.generated.swift @@ -13,8 +13,8 @@ public struct OptionListPickerItem { var _allowsMultipleSelection: Bool var _allowsEmptySelection: Bool var _onTap: ((_ index: Int) -> Void)? = nil - @State var _height: CGFloat = 0 var updateSearchListPickerHeight: ((CGFloat) -> ())? = nil + @State var _height: CGFloat = 0 var barItemFrame: CGRect = .zero public init(model: OptionListPickerItemModel) { self.init(value: Binding<[Int]>(get: { model.value }, set: { model.value = $0 }), valueOptions: model.valueOptions, hint: model.hint, title: model.title, itemLayout: model.itemLayout, allowsMultipleSelection: model.allowsMultipleSelection, allowsEmptySelection: model.allowsEmptySelection, onTap: model.onTap) diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchListPickerItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchListPickerItem+API.generated.swift index 7aaa25461..6dbdc0a22 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchListPickerItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/SearchListPickerItem+API.generated.swift @@ -9,20 +9,20 @@ public struct SearchListPickerItem { var _valueOptions: [String] var _hint: String? = nil var _onTap: ((_ index: Int) -> Void)? = nil - var disableListEntriesSection: Bool = false - var allowsEmptySelection: Bool = false - var barItemFrame: CGRect = .zero - let popoverWidth = 393.0 - var selectAll: ((Bool) -> ())? = nil + @State var _height: CGFloat = 44 + var allowsDisplaySelectionCount: Bool = true @State var _searchViewCornerRadius: CGFloat = 18 - var allowsMultipleSelection: Bool = false var updateSearchListPickerHeight: ((CGFloat) -> ())? = nil - var allowsDisplaySelectionCount: Bool = true - var uuidValueOptions: [[String: String]] = [] - var isSearchBarHidden: Bool = false + var barItemFrame: CGRect = .zero + var selectAll: ((Bool) -> ())? = nil + var allowsEmptySelection: Bool = false @State var _searchText: String = "" @State var _keyboardHeight: CGFloat = 0.0 - @State var _height: CGFloat = 44 + var disableListEntriesSection: Bool = false + var isSearchBarHidden: Bool = false + let popoverWidth = 393.0 + var allowsMultipleSelection: Bool = false + var uuidValueOptions: [[String: String]] = [] public init(model: SearchListPickerItemModel) { self.init(value: Binding<[Int]>(get: { model.value }, set: { model.value = $0 }), valueOptions: model.valueOptions, hint: model.hint, onTap: model.onTap) } diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_InfoView+API.generated.swift similarity index 83% rename from Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift rename to Sources/FioriSwiftUICore/_generated/ViewModels/API/_InfoView+API.generated.swift index a71a2d7fd..bfdd7c300 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/InfoView+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_InfoView+API.generated.swift @@ -2,7 +2,7 @@ // DO NOT EDIT import SwiftUI -public struct InfoView { +public struct _InfoView { @Environment(\.titleModifier) private var titleModifier @Environment(\.descriptionTextModifier) private var descriptionTextModifier @Environment(\.actionModifier) private var actionModifier @@ -41,30 +41,30 @@ public struct InfoView, ActionView == _ConditionalContent<_Action, EmptyView>, SecondaryActionView == _ConditionalContent<_Action, EmptyView> { - public init(model: InfoViewModel) { + public init(model: _InfoViewModel) { self.init(title: model.title, descriptionText: model.descriptionText, showLoadingIndicator: model.showLoadingIndicator, loadingIndicatorText: model.loadingIndicatorText, action: model.action != nil ? _Action(model: model.action!) : nil, secondaryAction: model.secondaryAction != nil ? _Action(model: model.secondaryAction!) : nil) } diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_KPIProgressItem+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_KPIProgressItem+API.generated.swift index 3eced22c7..6c2f09a78 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_KPIProgressItem+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_KPIProgressItem+API.generated.swift @@ -13,8 +13,8 @@ public struct _KPIProgressItem { let _fraction: Double? let _subtitle: Subtitle let _footnote: Footnote - var action: (() -> Void)? = nil @State var isPressed: Bool = false + var action: (() -> Void)? = nil private var isModelInit: Bool = false private var isKpiNil: Bool = false private var isSubtitleNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ObjectHeader+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ObjectHeader+API.generated.swift index 3a5778ab7..22f422800 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ObjectHeader+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_ObjectHeader+API.generated.swift @@ -25,11 +25,11 @@ public struct _ObjectHeader Void)? let _onDelete: (() -> Void)? - let _drawingViewMinHeight: CGFloat = 256 - var watermarkText: String? - var cropsImage = false - var hidesXmark = false - var strokeColor = Color.preferredColor(.primaryLabel) + var signatureLineColor = Color.preferredColor(.quaternaryLabel) @State var drawings = [Drawing]() + var titleColor = Color.preferredColor(.primaryLabel) + var indicatorFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) + var timestampFormatter: DateFormatter? + @State var fullSignatureImage: UIImage? var indicatorColor = Color.preferredColor(.primaryLabel) - var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) - @State var isSaved = false var isRequired = false - var watermarkTextColor: Color = .preferredColor(.tertiaryLabel) + var titleFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) + var addsTimestampInImage: Bool = false + var hidesXmark = false + var cropsImage = false + var hidesSignatureLine = false var xmarkColor = Color.preferredColor(.quaternaryLabel) - @State var fullSignatureImage: UIImage? + var strokeColor = Color.preferredColor(.primaryLabel) + var watermarkTextColor: Color = .preferredColor(.tertiaryLabel) + @State var isReenterTapped = false var watermarkTextAlignment: NSTextAlignment = .natural - var timestampFormatter: DateFormatter? - var appliesTintColorToImage = true - var titleFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) - var signatureLineColor = Color.preferredColor(.quaternaryLabel) + @State var currentDrawing = Drawing() var _drawingViewMaxHeight: CGFloat? - var titleColor = Color.preferredColor(.primaryLabel) - public private(set) var _heightDidChangePublisher = CurrentValueSubject(0) @State var isEditing = false - @State var currentDrawing = Drawing() - var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) - var hidesSignatureLine = false var strokeWidth: CGFloat = 3.0 - @State var isReenterTapped = false - var indicatorFont = Font.fiori(forTextStyle: .subheadline).weight(.semibold) - var addsTimestampInImage: Bool = false + var drawingViewBackgroundColor = Color.preferredColor(.primaryBackground) + @State var isSaved = false + var watermarkText: String? + var watermarkTextFont: UIFont = .preferredFont(forTextStyle: .caption1) + var appliesTintColorToImage = true + public private(set) var _heightDidChangePublisher = CurrentValueSubject(0) + let _drawingViewMinHeight: CGFloat = 256 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 9d5c198b9..abecdaea8 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_SingleStep+API.generated.swift @@ -14,15 +14,15 @@ public struct _SingleStep Void)? @State var size: CGSize = .zero - let popoverWidth = 393.0 @StateObject var context: SortFilterContext = SortFilterContext() + let popoverWidth = 393.0 private var isModelInit: Bool = false private var isCancelActionNil: Bool = false diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_StepProgressIndicator+API.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_StepProgressIndicator+API.generated.swift index 2c60b4d52..a4b07eabf 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/API/_StepProgressIndicator+API.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/API/_StepProgressIndicator+API.generated.swift @@ -13,11 +13,11 @@ public struct _StepProgressIndicator } } -// FIXME: - Implement InfoView specific LibraryContentProvider +// FIXME: - Implement _InfoView specific LibraryContentProvider @available(iOS 14.0, macOS 11.0, *) -struct InfoViewLibraryContent: LibraryContentProvider { +struct _InfoViewLibraryContent: LibraryContentProvider { @LibraryContentBuilder var views: [LibraryItem] { - LibraryItem(InfoView(model: LibraryPreviewData.Person.laurelosborn), + LibraryItem(_InfoView(model: LibraryPreviewData.Person.laurelosborn), category: .control) } } diff --git a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/_InfoView+Init.generated.swift similarity index 85% rename from Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift rename to Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/_InfoView+Init.generated.swift index e053b970f..46d2b1050 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/InfoView+Init.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Init+Extensions/_InfoView+Init.generated.swift @@ -2,7 +2,7 @@ // DO NOT EDIT import SwiftUI -extension InfoView where DescriptionText == EmptyView { +extension _InfoView where DescriptionText == EmptyView { public init( @ViewBuilder title: () -> Title, showLoadingIndicator: Bool? = nil, @@ -21,7 +21,7 @@ extension InfoView where DescriptionText == EmptyView { } } -extension InfoView where ActionView == EmptyView { +extension _InfoView where ActionView == EmptyView { public init( @ViewBuilder title: () -> Title, @ViewBuilder descriptionText: () -> DescriptionText, @@ -40,7 +40,7 @@ extension InfoView where ActionView == EmptyView { } } -extension InfoView where SecondaryActionView == EmptyView { +extension _InfoView where SecondaryActionView == EmptyView { public init( @ViewBuilder title: () -> Title, @ViewBuilder descriptionText: () -> DescriptionText, @@ -59,7 +59,7 @@ extension InfoView where SecondaryActionView == EmptyView { } } -extension InfoView where DescriptionText == EmptyView, ActionView == EmptyView { +extension _InfoView where DescriptionText == EmptyView, ActionView == EmptyView { public init( @ViewBuilder title: () -> Title, showLoadingIndicator: Bool? = nil, @@ -77,7 +77,7 @@ extension InfoView where DescriptionText == EmptyView, ActionView == EmptyView { } } -extension InfoView where DescriptionText == EmptyView, SecondaryActionView == EmptyView { +extension _InfoView where DescriptionText == EmptyView, SecondaryActionView == EmptyView { public init( @ViewBuilder title: () -> Title, showLoadingIndicator: Bool? = nil, @@ -95,7 +95,7 @@ extension InfoView where DescriptionText == EmptyView, SecondaryActionView == Em } } -extension InfoView where ActionView == EmptyView, SecondaryActionView == EmptyView { +extension _InfoView where ActionView == EmptyView, SecondaryActionView == EmptyView { public init( @ViewBuilder title: () -> Title, @ViewBuilder descriptionText: () -> DescriptionText, @@ -113,7 +113,7 @@ extension InfoView where ActionView == EmptyView, SecondaryActionView == EmptyVi } } -extension InfoView where DescriptionText == EmptyView, ActionView == EmptyView, SecondaryActionView == EmptyView { +extension _InfoView where DescriptionText == EmptyView, ActionView == EmptyView, SecondaryActionView == EmptyView { public init( @ViewBuilder title: () -> Title, showLoadingIndicator: Bool? = 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 similarity index 91% rename from Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift rename to Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/_InfoViewModel+Extensions.generated.swift index 1aa6e2218..8247c469b 100644 --- a/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/InfoViewModel+Extensions.generated.swift +++ b/Sources/FioriSwiftUICore/_generated/ViewModels/Model+Extensions/_InfoViewModel+Extensions.generated.swift @@ -2,7 +2,7 @@ // DO NOT EDIT import SwiftUI -public extension InfoViewModel { +public extension _InfoViewModel { var showLoadingIndicator: Bool? { return nil } diff --git a/Tests/FioriSwiftUITests/FioriSwiftUICore/InfoViewTests.swift b/Tests/FioriSwiftUITests/FioriSwiftUICore/InfoViewTests.swift new file mode 100644 index 000000000..2b2407d38 --- /dev/null +++ b/Tests/FioriSwiftUITests/FioriSwiftUICore/InfoViewTests.swift @@ -0,0 +1,21 @@ +@testable import FioriSwiftUICore +import SwiftUI +import XCTest + +final class InfoViewTests: XCTestCase { + func testInfoViewLeftPadding() { + XCTAssertEqual(getInfoViewLeftPadding(), 35.0) + } + + func testViewConfiguration() throws { + let view = InfoView( + title: { Text("Initial Title") }, + descriptionText: { Text("Initial Description") }, + action: { Button("Action") {} }, + secondaryAction: { Button("Secondary") {} } + ) + + XCTAssertTrue(type(of: view.title) == FioriSwiftUICore.Title.self, "type error") + XCTAssertTrue(type(of: view.action) == FioriSwiftUICore.Action.self, "type error") + } +} diff --git a/sourcery/.lib/Sources/utils/Type+Extensions.swift b/sourcery/.lib/Sources/utils/Type+Extensions.swift index 8a2916e65..3739a4e63 100644 --- a/sourcery/.lib/Sources/utils/Type+Extensions.swift +++ b/sourcery/.lib/Sources/utils/Type+Extensions.swift @@ -105,6 +105,7 @@ public extension Type { "_SliderPickerItemModel", "_EULAViewModel", "_DurationPickerModel", + "_InfoViewModel", "_ActivationScreenModel"] if deprecatedComponents.contains(name) {