From 454264a6a440d93537afcb74d4db2f5c5de66651 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Thu, 22 May 2025 12:51:23 +0300 Subject: [PATCH 1/2] add `ImageRenderingMode` type --- .../Shared/Types/ImageRenderingMode.swift | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift diff --git a/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift b/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift new file mode 100644 index 0000000..4cf973b --- /dev/null +++ b/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift @@ -0,0 +1,40 @@ +import SwiftUI +import UIKit + +/// A type that indicates how images are rendered. +public enum ImageRenderingMode { + /// A mode that renders all non-transparent pixels as the foreground + /// color. + case template + /// A mode that renders pixels of bitmap images as-is. + /// + /// For system images created from the SF Symbol set, multicolor symbols + /// respect the current foreground and accent colors. + case original +} + +// MARK: - UIKit Helpers + +extension ImageRenderingMode { + var uiImageRenderingMode: UIImage.RenderingMode { + switch self { + case .template: + return .alwaysTemplate + case .original: + return .alwaysOriginal + } + } +} + +// MARK: - SwiftUI Helpers + +extension ImageRenderingMode { + var imageRenderingModel: Image.TemplateRenderingMode { + switch self { + case .template: + return .template + case .original: + return .original + } + } +} From e2a4c5c5857ec5cadc16f0e9425054f77ff8064e Mon Sep 17 00:00:00 2001 From: Mikhail Date: Thu, 22 May 2025 12:51:50 +0300 Subject: [PATCH 2/2] add image rendering mode to ButtonVM --- .../avatar_placeholder.imageset/Contents.json | 3 --- .../PreviewPages/ButtonPreview.swift | 5 +++++ .../Button/Models/ButtonImageSource.swift | 2 +- .../Components/Button/Models/ButtonVM.swift | 14 ++++++++------ .../Shared/Types/ImageRenderingMode.swift | 10 ++++++++++ 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Examples/DemosApp/DemosApp/Assets.xcassets/avatar_placeholder.imageset/Contents.json b/Examples/DemosApp/DemosApp/Assets.xcassets/avatar_placeholder.imageset/Contents.json index 1b231c5..68cb3fb 100644 --- a/Examples/DemosApp/DemosApp/Assets.xcassets/avatar_placeholder.imageset/Contents.json +++ b/Examples/DemosApp/DemosApp/Assets.xcassets/avatar_placeholder.imageset/Contents.json @@ -17,8 +17,5 @@ "info" : { "author" : "xcode", "version" : 1 - }, - "properties" : { - "template-rendering-intent" : "template" } } diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/ButtonPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/ButtonPreview.swift index 19dc015..5a9ce2b 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/ButtonPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/ButtonPreview.swift @@ -35,6 +35,11 @@ struct ButtonPreview: View { Text("Leading").tag(ButtonVM.ImageLocation.leading) Text("Trailing").tag(ButtonVM.ImageLocation.trailing) } + Picker("Image Rendering Mode", selection: self.$model.imageRenderingMode) { + Text("Default").tag(Optional.none) + Text("Template").tag(ImageRenderingMode.template) + Text("Original").tag(ImageRenderingMode.original) + } Picker("Image Source", selection: self.$model.imageSrc) { Text("SF Symbol").tag(ButtonVM.ImageSource.sfSymbol("camera.fill")) Text("Local").tag(ButtonVM.ImageSource.local("avatar_placeholder")) diff --git a/Sources/ComponentsKit/Components/Button/Models/ButtonImageSource.swift b/Sources/ComponentsKit/Components/Button/Models/ButtonImageSource.swift index c959830..f672cc0 100644 --- a/Sources/ComponentsKit/Components/Button/Models/ButtonImageSource.swift +++ b/Sources/ComponentsKit/Components/Button/Models/ButtonImageSource.swift @@ -1,7 +1,7 @@ import Foundation -/// Defines the image source options for a button. extension ButtonVM { + /// Defines the image source options for a button. public enum ImageSource: Hashable { /// An image loaded from a system SF Symbol. /// diff --git a/Sources/ComponentsKit/Components/Button/Models/ButtonVM.swift b/Sources/ComponentsKit/Components/Button/Models/ButtonVM.swift index 920cfb0..9303de5 100644 --- a/Sources/ComponentsKit/Components/Button/Models/ButtonVM.swift +++ b/Sources/ComponentsKit/Components/Button/Models/ButtonVM.swift @@ -30,6 +30,9 @@ public struct ButtonVM: ComponentVM { /// Defaults to `.leading`. public var imageLocation: ImageLocation = .leading + /// Defines how image is rendered. + public var imageRenderingMode: ImageRenderingMode? + /// The source of the image to be displayed. public var imageSrc: ImageSource? @@ -184,15 +187,14 @@ extension ButtonVM { extension ButtonVM { var image: UIImage? { guard let imageSrc else { return nil } - switch imageSrc { + + let image = switch imageSrc { case .sfSymbol(let name): - return UIImage(systemName: name)?.withTintColor( - self.foregroundColor.uiColor, - renderingMode: .alwaysOriginal - ) + UIImage(systemName: name) case .local(let name, let bundle): - return UIImage(named: name, in: bundle, compatibleWith: nil) + UIImage(named: name, in: bundle, compatibleWith: nil) } + return image?.withRenderingMode(self.imageRenderingMode) } } diff --git a/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift b/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift index 4cf973b..b4b8f66 100644 --- a/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift +++ b/Sources/ComponentsKit/Shared/Types/ImageRenderingMode.swift @@ -26,6 +26,16 @@ extension ImageRenderingMode { } } +extension UIImage { + func withRenderingMode(_ mode: ImageRenderingMode?) -> UIImage { + if let mode { + return self.withRenderingMode(mode.uiImageRenderingMode) + } else { + return self + } + } +} + // MARK: - SwiftUI Helpers extension ImageRenderingMode {