diff --git a/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift b/Apps/Examples/Examples/FioriSwiftUICore/Onboarding/InfoViewSample.swift index 800185326e..29e7a8ce9b 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 f260e7fea3..2f63de24de 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 8d4eeb6c3c..09f1a898bd 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 b986f61292..534d490f3a 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 0daad19eea..0af26e738a 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 0000000000..ead335d21f --- /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 1a97dbc77b..11101e3181 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 16fe266eda..ad9c8c3f1b 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 0000000000..bef17715d9 --- /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 0000000000..32b979dc7c --- /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 52d7c4fc4f..25357e268e 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 3ce3c4419e..4f9bec7a8d 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 d5893837bd..f0a528ca64 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 759f786aaa..0c6dd8c4c6 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 8a68a16b2b..6a21b5d61c 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 75bd1c3a42..78eec17154 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 434b85d153..483a3b816f 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 7aaa254610..6dbdc0a22b 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 a71a2d7fd7..bfdd7c3000 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 3eced22c7a..6c2f09a787 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 3a5778ab7b..22f4228002 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 9d5c198b98..abecdaea8c 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 2c60b4d52f..a4b07eabf8 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 e053b970f7..46d2b1050a 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 1aa6e22189..8247c469b9 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 0000000000..2b2407d381 --- /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 8a2916e658..3739a4e631 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) {