diff --git a/Examples/DemosApp/DemosApp.xcodeproj/project.pbxproj b/Examples/DemosApp/DemosApp.xcodeproj/project.pbxproj index 81af7444..eb43c073 100644 --- a/Examples/DemosApp/DemosApp.xcodeproj/project.pbxproj +++ b/Examples/DemosApp/DemosApp.xcodeproj/project.pbxproj @@ -272,7 +272,7 @@ PRODUCT_BUNDLE_IDENTIFIER = io.componentskit.examples.DemosApp; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 6.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -300,7 +300,7 @@ PRODUCT_BUNDLE_IDENTIFIER = io.componentskit.examples.DemosApp; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 6.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift index 272810a2..b172d57a 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift @@ -126,6 +126,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri // MARK: - UIKit + @MainActor static func ukHeader(hasHeader: Bool) -> UKModalController.Content? { guard hasHeader else { return nil @@ -139,6 +140,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri } } + @MainActor static func ukBody(body: ContentBody) -> UKModalController.Content { return { _ in let subtitle = UILabel() @@ -154,36 +156,39 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri } } + @MainActor static func ukFooter(footer: ContentFooter?) -> UKModalController.Content? { - return footer.map { footer in - return { dismiss in - let stackView = UIStackView() - stackView.axis = .vertical - stackView.spacing = 16 - - let button = UKButton( - model: self.footerButtonVM, - action: { dismiss(true) } - ) - stackView.addArrangedSubview(button) - - switch footer { - case .button: - button.model.isEnabled = true - case .buttonAndCheckbox: - button.model.isEnabled = false - let checkbox = UKCheckbox( - initialValue: false, - model: self.footerCheckboxVM, - onValueChange: { isSelected in - button.model.isEnabled = isSelected - } - ) - stackView.insertArrangedSubview(checkbox, at: 0) - } + guard let footer else { + return nil + } + + return { dismiss in + let stackView = UIStackView() + stackView.axis = .vertical + stackView.spacing = 16 - return stackView + let button = UKButton( + model: self.footerButtonVM, + action: { dismiss(true) } + ) + stackView.addArrangedSubview(button) + + switch footer { + case .button: + button.model.isEnabled = true + case .buttonAndCheckbox: + button.model.isEnabled = false + let checkbox = UKCheckbox( + initialValue: false, + model: self.footerCheckboxVM, + onValueChange: { isSelected in + button.model.isEnabled = isSelected + } + ) + stackView.insertArrangedSubview(checkbox, at: 0) } + + return stackView } } @@ -220,6 +225,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri } } + @MainActor static func suFooter( isPresented: Binding, isCheckboxSelected: Binding, diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/UKComponentPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/UKComponentPreview.swift index b87bc7fd..8f8a903e 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/UKComponentPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/UKComponentPreview.swift @@ -38,6 +38,7 @@ struct UKComponentPreview: UIViewRepresentable where View: UKCompon let model: Model let view: View + @MainActor init(view: View) { self.view = view self.model = view.model @@ -53,6 +54,7 @@ struct UKComponentPreview: UIViewRepresentable where View: UKCompon } extension UKComponent { + @MainActor var preview: some View { UKComponentPreview(view: self) } diff --git a/Sources/ComponentsKit/Components/Alert/Helpers/AlertButtonsOrientationCalculator.swift b/Sources/ComponentsKit/Components/Alert/Helpers/AlertButtonsOrientationCalculator.swift index e12bb3e4..7bfe21ad 100644 --- a/Sources/ComponentsKit/Components/Alert/Helpers/AlertButtonsOrientationCalculator.swift +++ b/Sources/ComponentsKit/Components/Alert/Helpers/AlertButtonsOrientationCalculator.swift @@ -1,14 +1,12 @@ import UIKit +@MainActor struct AlertButtonsOrientationCalculator { enum Orientation { case vertical case horizontal } - private static let primaryButton = UKButton(model: .init()) - private static let secondaryButton = UKButton(model: .init()) - private init() {} static func preferredOrientation(model: AlertVM) -> Orientation { @@ -17,15 +15,15 @@ struct AlertButtonsOrientationCalculator { return .vertical } - self.primaryButton.model = primaryButtonVM.updating { + let primaryButton = UKButton(model: primaryButtonVM.updating { $0.isFullWidth = false - } - self.secondaryButton.model = secondaryButtonVM.updating { + }) + let secondaryButton = UKButton(model: secondaryButtonVM.updating { $0.isFullWidth = false - } + }) - let primaryButtonWidth = self.primaryButton.intrinsicContentSize.width - let secondaryButtonWidth = self.secondaryButton.intrinsicContentSize.width + let primaryButtonWidth = primaryButton.intrinsicContentSize.width + let secondaryButtonWidth = secondaryButton.intrinsicContentSize.width // Since the `maxWidth` of the alert is always less than the width of the // screen, we can assume that the width of the container is equal to this diff --git a/Sources/ComponentsKit/Components/Alert/UKAlertController.swift b/Sources/ComponentsKit/Components/Alert/UKAlertController.swift index f6ec2cc2..73780a41 100644 --- a/Sources/ComponentsKit/Components/Alert/UKAlertController.swift +++ b/Sources/ComponentsKit/Components/Alert/UKAlertController.swift @@ -158,6 +158,7 @@ open class UKAlertController: UKCenterModalController { // MARK: - Style Helpers extension UKAlertController { + @MainActor fileprivate enum Style { static func titleLabel(_ label: UILabel, text: String?) { label.text = text diff --git a/Sources/ComponentsKit/Components/Avatar/Helpers/AvatarImageManager.swift b/Sources/ComponentsKit/Components/Avatar/Helpers/AvatarImageManager.swift index b71cdc9b..9f15b983 100644 --- a/Sources/ComponentsKit/Components/Avatar/Helpers/AvatarImageManager.swift +++ b/Sources/ComponentsKit/Components/Avatar/Helpers/AvatarImageManager.swift @@ -1,11 +1,12 @@ import SwiftUI import UIKit +@MainActor final class AvatarImageManager: ObservableObject { @Published var avatarImage: UIImage private var model: AvatarVM - private static var remoteImagesCache = NSCache() + private static let remoteImagesCache = NSCache() init(model: AvatarVM) { self.model = model @@ -41,7 +42,7 @@ final class AvatarImageManager: ObservableObject { } private func downloadImage(url: URL) { - Task { @MainActor in + Task { let request = URLRequest(url: url) guard let (data, _) = try? await URLSession.shared.data(for: request), let image = UIImage(data: data) diff --git a/Sources/ComponentsKit/Components/Avatar/Models/AvatarImageSource.swift b/Sources/ComponentsKit/Components/Avatar/Models/AvatarImageSource.swift index 80e0697a..c9d29135 100644 --- a/Sources/ComponentsKit/Components/Avatar/Models/AvatarImageSource.swift +++ b/Sources/ComponentsKit/Components/Avatar/Models/AvatarImageSource.swift @@ -2,7 +2,7 @@ import Foundation /// Defines the source options for an avatar image. extension AvatarVM { - public enum ImageSource: Hashable { + public enum ImageSource: Hashable, Sendable { /// An image loaded from a remote URL. /// /// - Parameter url: The URL pointing to the remote image resource. diff --git a/Sources/ComponentsKit/Components/Avatar/Models/AvatarPlaceholder.swift b/Sources/ComponentsKit/Components/Avatar/Models/AvatarPlaceholder.swift index 9ddb89c2..b1f15e31 100644 --- a/Sources/ComponentsKit/Components/Avatar/Models/AvatarPlaceholder.swift +++ b/Sources/ComponentsKit/Components/Avatar/Models/AvatarPlaceholder.swift @@ -4,7 +4,7 @@ import Foundation /// /// It is used to provide a fallback or alternative visual representation when an image is not provided or fails to load. extension AvatarVM { - public enum Placeholder: Hashable { + public enum Placeholder: Hashable, Sendable { /// A placeholder that displays a text string. /// /// This option is typically used to show initials, names, or other textual representations. diff --git a/Sources/ComponentsKit/Components/Avatar/UIKit/UKAvatar.swift b/Sources/ComponentsKit/Components/Avatar/UIKit/UKAvatar.swift index 5b614f91..8ba2e30e 100644 --- a/Sources/ComponentsKit/Components/Avatar/UIKit/UKAvatar.swift +++ b/Sources/ComponentsKit/Components/Avatar/UIKit/UKAvatar.swift @@ -1,4 +1,4 @@ -import Combine +@preconcurrency import Combine import UIKit /// A UIKit component that displays a profile picture, initials or fallback icon for a user. diff --git a/Sources/ComponentsKit/Components/AvatarGroup/UIKit/AvatarContainer.swift b/Sources/ComponentsKit/Components/AvatarGroup/UIKit/AvatarContainer.swift index c37c9d9c..b154257b 100644 --- a/Sources/ComponentsKit/Components/AvatarGroup/UIKit/AvatarContainer.swift +++ b/Sources/ComponentsKit/Components/AvatarGroup/UIKit/AvatarContainer.swift @@ -81,6 +81,7 @@ final class AvatarContainer: UIView { // MARK: - Style Helpers extension AvatarContainer { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: AvatarGroupVM) { view.backgroundColor = model.borderColor.uiColor diff --git a/Sources/ComponentsKit/Components/AvatarGroup/UIKit/UKAvatarGroup.swift b/Sources/ComponentsKit/Components/AvatarGroup/UIKit/UKAvatarGroup.swift index dabc9411..fda26bf6 100644 --- a/Sources/ComponentsKit/Components/AvatarGroup/UIKit/UKAvatarGroup.swift +++ b/Sources/ComponentsKit/Components/AvatarGroup/UIKit/UKAvatarGroup.swift @@ -111,6 +111,7 @@ open class UKAvatarGroup: UIView, UKComponent { // MARK: - Style Helpers extension UKAvatarGroup { + @MainActor fileprivate enum Style { static func stackView(_ view: UIStackView, model: Model) { view.axis = .horizontal diff --git a/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift b/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift index 5cc3cdb8..c0c6f30a 100644 --- a/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift +++ b/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift @@ -2,7 +2,7 @@ import Foundation extension BadgeVM { /// Defines the available visual styles for a badge. - public enum Style: Equatable { + public enum Style: Equatable, Sendable { case filled case light } diff --git a/Sources/ComponentsKit/Components/Badge/UKBadge.swift b/Sources/ComponentsKit/Components/Badge/UKBadge.swift index 2dc63e3a..e8dfceb5 100644 --- a/Sources/ComponentsKit/Components/Badge/UKBadge.swift +++ b/Sources/ComponentsKit/Components/Badge/UKBadge.swift @@ -112,6 +112,7 @@ open class UKBadge: UIView, UKComponent { // MARK: - Style Helpers extension UKBadge { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: BadgeVM) { view.backgroundColor = model.backgroundColor.uiColor diff --git a/Sources/ComponentsKit/Components/Button/Models/ButtonImageLocation.swift b/Sources/ComponentsKit/Components/Button/Models/ButtonImageLocation.swift index e22a109a..c4bc0b4d 100644 --- a/Sources/ComponentsKit/Components/Button/Models/ButtonImageLocation.swift +++ b/Sources/ComponentsKit/Components/Button/Models/ButtonImageLocation.swift @@ -2,7 +2,7 @@ import Foundation /// Specifies the position of the image relative to the button's title. extension ButtonVM { - public enum ImageLocation { + public enum ImageLocation: Sendable { /// The image is displayed before the title. case leading /// The image is displayed after the title. diff --git a/Sources/ComponentsKit/Components/Button/UKButton.swift b/Sources/ComponentsKit/Components/Button/UKButton.swift index 5d39cce8..d4452759 100644 --- a/Sources/ComponentsKit/Components/Button/UKButton.swift +++ b/Sources/ComponentsKit/Components/Button/UKButton.swift @@ -236,6 +236,7 @@ open class UKButton: FullWidthComponent, UKComponent { // MARK: - Style Helpers extension UKButton { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: Model) { view.backgroundColor = nil diff --git a/Sources/ComponentsKit/Components/Card/UKCard.swift b/Sources/ComponentsKit/Components/Card/UKCard.swift index 14514b94..1fbe96ff 100644 --- a/Sources/ComponentsKit/Components/Card/UKCard.swift +++ b/Sources/ComponentsKit/Components/Card/UKCard.swift @@ -206,6 +206,7 @@ open class UKCard: UIView, UKComponent { } extension UKCard { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: Model) { view.layer.cornerRadius = model.cornerRadius.value diff --git a/Sources/ComponentsKit/Components/Checkbox/UKCheckbox.swift b/Sources/ComponentsKit/Components/Checkbox/UKCheckbox.swift index 164eeae0..8d3d31ab 100644 --- a/Sources/ComponentsKit/Components/Checkbox/UKCheckbox.swift +++ b/Sources/ComponentsKit/Components/Checkbox/UKCheckbox.swift @@ -254,6 +254,7 @@ open class UKCheckbox: UIView, UKComponent { // MARK: - Style Helpers extension UKCheckbox { + @MainActor fileprivate enum Style { static func stackView(_ stackView: UIStackView, model: Model) { stackView.axis = .horizontal diff --git a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressShape.swift b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressShape.swift index 7c4e4e1c..25cf7ea0 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressShape.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/Models/CircularProgressShape.swift @@ -2,7 +2,7 @@ import Foundation extension CircularProgressVM { /// Defines the shapes for the circular progress component. - public enum Shape { + public enum Shape: Sendable { /// Renders a complete circle to represent the progress. case circle /// Renders only a portion of the circle (an arc) to represent progress. diff --git a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift index dce73525..2dbcdf6e 100644 --- a/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift +++ b/Sources/ComponentsKit/Components/CircularProgress/UKCircularProgress.swift @@ -171,6 +171,7 @@ open class UKCircularProgress: UIView, UKComponent { // MARK: - Style Helpers extension UKCircularProgress { + @MainActor fileprivate enum Style { static func backgroundLayer( _ layer: CAShapeLayer, diff --git a/Sources/ComponentsKit/Components/Countdown/Helpers/CountdownWidthCalculator.swift b/Sources/ComponentsKit/Components/Countdown/Helpers/CountdownWidthCalculator.swift index 74e19403..653b8c15 100644 --- a/Sources/ComponentsKit/Components/Countdown/Helpers/CountdownWidthCalculator.swift +++ b/Sources/ComponentsKit/Components/Countdown/Helpers/CountdownWidthCalculator.swift @@ -1,18 +1,18 @@ import UIKit +@MainActor struct CountdownWidthCalculator { - private static let label = UILabel() - private init() {} static func preferredWidth( for attributedText: NSAttributedString, model: CountdownVM ) -> CGFloat { - self.style(self.label, with: model) - self.label.attributedText = attributedText + let label = UILabel() + self.style(label, with: model) + label.attributedText = attributedText - let estimatedSize = self.label.sizeThatFits(UIView.layoutFittingExpandedSize) + let estimatedSize = label.sizeThatFits(UIView.layoutFittingExpandedSize) return estimatedSize.width + 2 } diff --git a/Sources/ComponentsKit/Components/Countdown/Localization/UnitsLocalization.swift b/Sources/ComponentsKit/Components/Countdown/Localization/UnitsLocalization.swift index b51343fd..6d77eba0 100644 --- a/Sources/ComponentsKit/Components/Countdown/Localization/UnitsLocalization.swift +++ b/Sources/ComponentsKit/Components/Countdown/Localization/UnitsLocalization.swift @@ -3,9 +3,9 @@ import Foundation // MARK: - UnitsLocalization /// A structure that provides localized representations of time units (seconds, minutes, hours, days). -public struct UnitsLocalization: Equatable { +public struct UnitsLocalization: Equatable, Sendable { /// A structure that represents the localized short and long forms of a single time unit. - public struct UnitItemLocalization: Equatable { + public struct UnitItemLocalization: Equatable, Sendable { /// The short-form representation of the time unit (e.g., "s" for seconds). public let short: String /// The long-form representation of the time unit (e.g., "Seconds"). diff --git a/Sources/ComponentsKit/Components/Countdown/Manager/CountdownManager.swift b/Sources/ComponentsKit/Components/Countdown/Manager/CountdownManager.swift index 9303fb7b..3d3209d4 100644 --- a/Sources/ComponentsKit/Components/Countdown/Manager/CountdownManager.swift +++ b/Sources/ComponentsKit/Components/Countdown/Manager/CountdownManager.swift @@ -1,6 +1,6 @@ import SwiftUI -class CountdownManager: ObservableObject { +class CountdownManager: ObservableObject, @unchecked Sendable { // MARK: - Published Properties @Published var days: Int = 0 @@ -13,6 +13,10 @@ class CountdownManager: ObservableObject { private var timer: Timer? private var until: Date? + deinit { + self.stop() + } + // MARK: - Methods func start(until: Date) { diff --git a/Sources/ComponentsKit/Components/Countdown/Models/CountdownStyle.swift b/Sources/ComponentsKit/Components/Countdown/Models/CountdownStyle.swift index 3f2dcad3..95e3dc64 100644 --- a/Sources/ComponentsKit/Components/Countdown/Models/CountdownStyle.swift +++ b/Sources/ComponentsKit/Components/Countdown/Models/CountdownStyle.swift @@ -2,13 +2,13 @@ import Foundation extension CountdownVM { /// Defines the visual styles for the countdown component. - public enum Style: Equatable { + public enum Style: Equatable, Sendable { case plain case light } /// Defines the units style for the countdown component. - public enum UnitsStyle: Equatable { + public enum UnitsStyle: Equatable, Sendable { case hidden case bottom case trailing diff --git a/Sources/ComponentsKit/Components/Countdown/Models/CountdownVM.swift b/Sources/ComponentsKit/Components/Countdown/Models/CountdownVM.swift index 4c780a01..a1de98d1 100644 --- a/Sources/ComponentsKit/Components/Countdown/Models/CountdownVM.swift +++ b/Sources/ComponentsKit/Components/Countdown/Models/CountdownVM.swift @@ -212,6 +212,7 @@ extension CountdownVM { || self.locale != oldModel.locale } + @MainActor func timeWidth(manager: CountdownManager) -> CGFloat { let values: [(Int, CountdownHelpers.Unit)] = [ (manager.days, .days), diff --git a/Sources/ComponentsKit/Components/Countdown/UKCountdown.swift b/Sources/ComponentsKit/Components/Countdown/UKCountdown.swift index 570e48e2..e3cd465b 100644 --- a/Sources/ComponentsKit/Components/Countdown/UKCountdown.swift +++ b/Sources/ComponentsKit/Components/Countdown/UKCountdown.swift @@ -65,13 +65,6 @@ open class UKCountdown: UIView, UKComponent { fatalError("init(coder:) has not been implemented") } - deinit { - self.manager.stop() - self.cancellables.forEach { - $0.cancel() - } - } - // MARK: - Setup private func setup() { @@ -227,6 +220,7 @@ open class UKCountdown: UIView, UKComponent { // MARK: - Style Helpers extension UKCountdown { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: CountdownVM) { view.backgroundColor = .clear diff --git a/Sources/ComponentsKit/Components/Divider/Models/DividerOrientation.swift b/Sources/ComponentsKit/Components/Divider/Models/DividerOrientation.swift index b19df750..02f7c5f6 100644 --- a/Sources/ComponentsKit/Components/Divider/Models/DividerOrientation.swift +++ b/Sources/ComponentsKit/Components/Divider/Models/DividerOrientation.swift @@ -2,7 +2,7 @@ import Foundation extension DividerVM { /// Defines the possible orientations for the divider. - public enum Orientation { + public enum Orientation: Sendable { case horizontal case vertical } diff --git a/Sources/ComponentsKit/Components/InputField/Models/InputFieldTitlePosition.swift b/Sources/ComponentsKit/Components/InputField/Models/InputFieldTitlePosition.swift index 5fc920a7..4226a9e9 100644 --- a/Sources/ComponentsKit/Components/InputField/Models/InputFieldTitlePosition.swift +++ b/Sources/ComponentsKit/Components/InputField/Models/InputFieldTitlePosition.swift @@ -2,7 +2,7 @@ import Foundation extension InputFieldVM { /// Specifies the position of the title relative to the input field. - public enum TitlePosition { + public enum TitlePosition: Sendable { /// The title is displayed inside the input field. case inside /// The title is displayed above the input field. diff --git a/Sources/ComponentsKit/Components/InputField/UKInputField.swift b/Sources/ComponentsKit/Components/InputField/UKInputField.swift index 1c1e4bf1..a7290f75 100644 --- a/Sources/ComponentsKit/Components/InputField/UKInputField.swift +++ b/Sources/ComponentsKit/Components/InputField/UKInputField.swift @@ -219,6 +219,7 @@ open class UKInputField: FullWidthComponent, UKComponent { // MARK: - Style Helpers extension UKInputField { + @MainActor fileprivate enum Style { static func textFieldContainer( _ view: UIView, diff --git a/Sources/ComponentsKit/Components/Modal/Models/ModalOverlayStyle.swift b/Sources/ComponentsKit/Components/Modal/Models/ModalOverlayStyle.swift index 48d8f485..152aae6a 100644 --- a/Sources/ComponentsKit/Components/Modal/Models/ModalOverlayStyle.swift +++ b/Sources/ComponentsKit/Components/Modal/Models/ModalOverlayStyle.swift @@ -1,5 +1,5 @@ /// Defines the style of the overlay displayed behind a modal. -public enum ModalOverlayStyle { +public enum ModalOverlayStyle: Sendable { /// A dimmed overlay that darkens the background behind the modal. case dimmed /// A blurred overlay that applies a blur effect to the background behind the modal. diff --git a/Sources/ComponentsKit/Components/Modal/Models/ModalSize.swift b/Sources/ComponentsKit/Components/Modal/Models/ModalSize.swift index 5ef27461..6466f8b0 100644 --- a/Sources/ComponentsKit/Components/Modal/Models/ModalSize.swift +++ b/Sources/ComponentsKit/Components/Modal/Models/ModalSize.swift @@ -1,7 +1,7 @@ import Foundation /// Defines the size options for a modal. -public enum ModalSize { +public enum ModalSize: Sendable { /// A small modal size. case small /// A medium modal size. diff --git a/Sources/ComponentsKit/Components/Modal/Models/ModalTransition.swift b/Sources/ComponentsKit/Components/Modal/Models/ModalTransition.swift index f4c41c46..b9d472cb 100644 --- a/Sources/ComponentsKit/Components/Modal/Models/ModalTransition.swift +++ b/Sources/ComponentsKit/Components/Modal/Models/ModalTransition.swift @@ -1,7 +1,7 @@ import Foundation /// Defines the transition speed options for a modal's appearance and dismissal animations. -public enum ModalTransition: Hashable { +public enum ModalTransition: Hashable, Sendable { /// No transition is applied; the modal appears and disappears instantly. case none /// A slow transition speed. diff --git a/Sources/ComponentsKit/Components/Modal/UIKit/UKModalController.swift b/Sources/ComponentsKit/Components/Modal/UIKit/UKModalController.swift index d8c35efb..ee3bd43c 100644 --- a/Sources/ComponentsKit/Components/Modal/UIKit/UKModalController.swift +++ b/Sources/ComponentsKit/Components/Modal/UIKit/UKModalController.swift @@ -7,7 +7,7 @@ open class UKModalController: UIViewController { /// A typealias for content providers, which create views for the header, body, or footer. /// The content provider closure receives a dismiss action that can be called to close the modal. - public typealias Content = (_ dismiss: @escaping (_ animated: Bool) -> Void) -> UIView + public typealias Content = @MainActor (_ dismiss: @escaping (_ animated: Bool) -> Void) -> UIView // MARK: - Properties @@ -254,6 +254,7 @@ open class UKModalController: UIViewController { // MARK: - Style Helpers extension UKModalController { + @MainActor enum Style { static func overlay(_ view: UIView, model: VM) { switch model.overlayStyle { diff --git a/Sources/ComponentsKit/Components/ProgressBar/Models/ProgressBarStyle.swift b/Sources/ComponentsKit/Components/ProgressBar/Models/ProgressBarStyle.swift index 08c0639c..a2c7e80f 100644 --- a/Sources/ComponentsKit/Components/ProgressBar/Models/ProgressBarStyle.swift +++ b/Sources/ComponentsKit/Components/ProgressBar/Models/ProgressBarStyle.swift @@ -2,7 +2,7 @@ import Foundation extension ProgressBarVM { /// Defines the visual styles for the progress bar component. - public enum Style { + public enum Style: Sendable { case light case filled case striped diff --git a/Sources/ComponentsKit/Components/ProgressBar/UKProgressBar.swift b/Sources/ComponentsKit/Components/ProgressBar/UKProgressBar.swift index a275336d..05f8a24b 100644 --- a/Sources/ComponentsKit/Components/ProgressBar/UKProgressBar.swift +++ b/Sources/ComponentsKit/Components/ProgressBar/UKProgressBar.swift @@ -194,6 +194,7 @@ open class UKProgressBar: FullWidthComponent, UKComponent { // MARK: - Style Helpers extension UKProgressBar { + @MainActor fileprivate enum Style { static func backgroundView(_ view: UIView, model: ProgressBarVM) { view.backgroundColor = model.backgroundColor.uiColor diff --git a/Sources/ComponentsKit/Components/RadioGroup/Models/RadioGroupVM.swift b/Sources/ComponentsKit/Components/RadioGroup/Models/RadioGroupVM.swift index 5021a771..6cb01199 100644 --- a/Sources/ComponentsKit/Components/RadioGroup/Models/RadioGroupVM.swift +++ b/Sources/ComponentsKit/Components/RadioGroup/Models/RadioGroupVM.swift @@ -2,7 +2,7 @@ import Foundation import UIKit /// A model that defines the data and appearance properties for a radio group component. -public struct RadioGroupVM: ComponentVM { +public struct RadioGroupVM: ComponentVM { /// The scaling factor for the button's press animation, with a value between 0 and 1. /// /// Defaults to `.medium`. diff --git a/Sources/ComponentsKit/Components/RadioGroup/Models/RadioItemVM.swift b/Sources/ComponentsKit/Components/RadioGroup/Models/RadioItemVM.swift index ebbe1ba4..6fec5a29 100644 --- a/Sources/ComponentsKit/Components/RadioGroup/Models/RadioItemVM.swift +++ b/Sources/ComponentsKit/Components/RadioGroup/Models/RadioItemVM.swift @@ -1,7 +1,7 @@ import Foundation /// A model that defines the data and appearance properties for an item in a radio group. -public struct RadioItemVM { +public struct RadioItemVM: Sendable { /// The unique identifier for the radio item. public var id: ID diff --git a/Sources/ComponentsKit/Components/RadioGroup/SwiftUI/SURadioGroup.swift b/Sources/ComponentsKit/Components/RadioGroup/SwiftUI/SURadioGroup.swift index 2ed80164..da19c369 100644 --- a/Sources/ComponentsKit/Components/RadioGroup/SwiftUI/SURadioGroup.swift +++ b/Sources/ComponentsKit/Components/RadioGroup/SwiftUI/SURadioGroup.swift @@ -1,7 +1,7 @@ import SwiftUI /// A SwiftUI component that displays a group of radio buttons, allowing users to select one option from multiple choices. -public struct SURadioGroup: View { +public struct SURadioGroup: View { // MARK: Properties /// A model that defines the appearance properties. diff --git a/Sources/ComponentsKit/Components/RadioGroup/UIKit/RadioGroupItemView.swift b/Sources/ComponentsKit/Components/RadioGroup/UIKit/RadioGroupItemView.swift index 2348da38..af401d21 100644 --- a/Sources/ComponentsKit/Components/RadioGroup/UIKit/RadioGroupItemView.swift +++ b/Sources/ComponentsKit/Components/RadioGroup/UIKit/RadioGroupItemView.swift @@ -2,7 +2,7 @@ import AutoLayout import UIKit /// A view representing a single radio button item in a radio group. -open class RadioGroupItemView: UIView { +open class RadioGroupItemView: UIView { // MARK: Properties /// A view that represents an outer circle and contains an inner circle. @@ -183,6 +183,7 @@ open class RadioGroupItemView: UIView { // MARK: - Style Helpers extension RadioGroupItemView { + @MainActor fileprivate enum Style { static func mainView( _ view: UIView, diff --git a/Sources/ComponentsKit/Components/RadioGroup/UIKit/UKRadioGroup.swift b/Sources/ComponentsKit/Components/RadioGroup/UIKit/UKRadioGroup.swift index 229f4cba..e35fb310 100644 --- a/Sources/ComponentsKit/Components/RadioGroup/UIKit/UKRadioGroup.swift +++ b/Sources/ComponentsKit/Components/RadioGroup/UIKit/UKRadioGroup.swift @@ -2,7 +2,7 @@ import AutoLayout import UIKit /// A UIKit component that displays a group of radio buttons, allowing users to select one option from multiple choices. -open class UKRadioGroup: UIView, UKComponent, UIGestureRecognizerDelegate { +open class UKRadioGroup: UIView, UKComponent, UIGestureRecognizerDelegate { // MARK: Properties /// A closure that is triggered when a selected segment changes. @@ -180,6 +180,7 @@ open class UKRadioGroup: UIView, UKComponent, UIGestureRecognizerD // MARK: - Style Helpers extension UKRadioGroup { + @MainActor fileprivate enum Style { static func stackView(_ stackView: UIStackView, model: Model) { stackView.axis = .vertical diff --git a/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlItemVM.swift b/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlItemVM.swift index b51f9f4b..102d45f3 100644 --- a/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlItemVM.swift +++ b/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlItemVM.swift @@ -1,7 +1,7 @@ import Foundation /// A model that defines the data and appearance properties for an item in a segmented control. -public struct SegmentedControlItemVM: Updatable { +public struct SegmentedControlItemVM: Updatable, Sendable { /// The unique identifier for the segmented control item. public var id: ID diff --git a/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlVM.swift b/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlVM.swift index 8f0f8617..8ef91a85 100644 --- a/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlVM.swift +++ b/Sources/ComponentsKit/Components/SegmentedControl/Models/SegmentedControlVM.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// A model that defines the data and appearance properties for a segmented control component. -public struct SegmentedControlVM: ComponentVM { +public struct SegmentedControlVM: ComponentVM { /// The color of the segmented control. public var color: ComponentColor? diff --git a/Sources/ComponentsKit/Components/SegmentedControl/SUSegmentedControl.swift b/Sources/ComponentsKit/Components/SegmentedControl/SUSegmentedControl.swift index b001cae5..b79c12a6 100644 --- a/Sources/ComponentsKit/Components/SegmentedControl/SUSegmentedControl.swift +++ b/Sources/ComponentsKit/Components/SegmentedControl/SUSegmentedControl.swift @@ -1,7 +1,7 @@ import SwiftUI /// A SwiftUI component that allows users to choose between multiple segments or options. -public struct SUSegmentedControl: View { +public struct SUSegmentedControl: View { // MARK: Properties /// A model that defines the appearance properties. diff --git a/Sources/ComponentsKit/Components/SegmentedControl/UKSegmentedControl.swift b/Sources/ComponentsKit/Components/SegmentedControl/UKSegmentedControl.swift index e642c6cb..d9548c69 100644 --- a/Sources/ComponentsKit/Components/SegmentedControl/UKSegmentedControl.swift +++ b/Sources/ComponentsKit/Components/SegmentedControl/UKSegmentedControl.swift @@ -2,7 +2,7 @@ import AutoLayout import UIKit /// A UIKit component that allows users to choose between multiple segments or options. -open class UKSegmentedControl: FullWidthComponent, UKComponent { +open class UKSegmentedControl: FullWidthComponent, UKComponent { // MARK: Properties /// A closure that is triggered when a selected segment changes. @@ -307,6 +307,7 @@ open class UKSegmentedControl: FullWidthComponent, UKComponent { // MARK: - Style Helpers extension UKSegmentedControl { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: Model) { view.backgroundColor = model.backgroundColor.uiColor diff --git a/Sources/ComponentsKit/Components/Slider/Models/SliderStyle.swift b/Sources/ComponentsKit/Components/Slider/Models/SliderStyle.swift index c4a70868..e5e9fdb6 100644 --- a/Sources/ComponentsKit/Components/Slider/Models/SliderStyle.swift +++ b/Sources/ComponentsKit/Components/Slider/Models/SliderStyle.swift @@ -2,7 +2,7 @@ import Foundation extension SliderVM { /// Defines the visual styles for the slider component. - public enum Style { + public enum Style: Sendable { case light case striped } diff --git a/Sources/ComponentsKit/Components/Slider/UKSlider.swift b/Sources/ComponentsKit/Components/Slider/UKSlider.swift index 22615b63..d050193c 100644 --- a/Sources/ComponentsKit/Components/Slider/UKSlider.swift +++ b/Sources/ComponentsKit/Components/Slider/UKSlider.swift @@ -252,6 +252,7 @@ open class UKSlider: FullWidthComponent, UKComponent { // MARK: - Style Helpers extension UKSlider { + @MainActor fileprivate enum Style { static func backgroundView(_ view: UIView, model: SliderVM) { view.backgroundColor = model.color.background.uiColor diff --git a/Sources/ComponentsKit/Components/TextInput/Helpers/TextInputHeightCalculator.swift b/Sources/ComponentsKit/Components/TextInput/Helpers/TextInputHeightCalculator.swift index d01cbb8a..e7dcd165 100644 --- a/Sources/ComponentsKit/Components/TextInput/Helpers/TextInputHeightCalculator.swift +++ b/Sources/ComponentsKit/Components/TextInput/Helpers/TextInputHeightCalculator.swift @@ -1,8 +1,7 @@ import UIKit +@MainActor struct TextInputHeightCalculator { - private static let textView = UITextView() - private init() {} static func preferredHeight( @@ -10,19 +9,20 @@ struct TextInputHeightCalculator { model: TextInputVM, width: CGFloat ) -> CGFloat { - self.textView.text = text - self.style(self.textView, with: model) + let textView = UITextView() + textView.text = text + self.style(textView, with: model) let targetSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude) - let estimatedHeight = self.textView.sizeThatFits(targetSize).height + let estimatedHeight = textView.sizeThatFits(targetSize).height return estimatedHeight } private static func style(_ textView: UITextView, with model: TextInputVM) { - self.textView.isScrollEnabled = false - self.textView.font = model.preferredFont.uiFont - self.textView.textContainerInset = .init(inset: model.contentPadding) - self.textView.textContainer.lineFragmentPadding = 0 + textView.isScrollEnabled = false + textView.font = model.preferredFont.uiFont + textView.textContainerInset = .init(inset: model.contentPadding) + textView.textContainer.lineFragmentPadding = 0 } } diff --git a/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift b/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift index 7710feda..96979af4 100644 --- a/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift +++ b/Sources/ComponentsKit/Components/TextInput/UKTextInput.swift @@ -200,6 +200,7 @@ extension UKTextInput: UITextViewDelegate { // MARK: - Style Helpers extension UKTextInput { + @MainActor fileprivate enum Style { static func mainView(_ view: UIView, model: TextInputVM) { view.backgroundColor = model.backgroundColor.uiColor diff --git a/Sources/ComponentsKit/Shared/Colors/ComponentColor.swift b/Sources/ComponentsKit/Shared/Colors/ComponentColor.swift index be4238a5..f9bcbf45 100644 --- a/Sources/ComponentsKit/Shared/Colors/ComponentColor.swift +++ b/Sources/ComponentsKit/Shared/Colors/ComponentColor.swift @@ -1,7 +1,7 @@ import Foundation /// A structure that defines a color set for components. -public struct ComponentColor: Hashable { +public struct ComponentColor: Hashable, Sendable { // MARK: - Properties /// The primary color used for the component. diff --git a/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift b/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift index 03baf7b0..e14031d7 100644 --- a/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift +++ b/Sources/ComponentsKit/Shared/Colors/UniversalColor.swift @@ -3,11 +3,11 @@ import UIKit /// A structure that represents an universal color that can be used in both UIKit and SwiftUI, /// with light and dark theme variants. -public struct UniversalColor: Hashable { +public struct UniversalColor: Hashable, @unchecked Sendable { // MARK: - ColorRepresentable /// An enumeration that defines the possible representations of a color. - public enum ColorRepresentable: Hashable { + public enum ColorRepresentable: Hashable, @unchecked Sendable { /// A color defined by its RGBA components. /// /// - Parameters: diff --git a/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift b/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift index ccc6cd29..8122c54a 100644 --- a/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift +++ b/Sources/ComponentsKit/Shared/Fonts/UniversalFont.swift @@ -3,9 +3,9 @@ import UIKit /// A structure that represents an universal font that can be used in both UIKit and SwiftUI, /// with support for custom and system fonts. -public enum UniversalFont: Hashable { +public enum UniversalFont: Hashable, Sendable { /// An enumeration that defines the weight of a font. - public enum Weight: Hashable { + public enum Weight: Hashable, Sendable { /// Ultra-light font weight. case ultraLight /// Thin font weight. diff --git a/Sources/ComponentsKit/Shared/Image/UniversalImage.swift b/Sources/ComponentsKit/Shared/Image/UniversalImage.swift index a30a4443..a0f9bf5d 100644 --- a/Sources/ComponentsKit/Shared/Image/UniversalImage.swift +++ b/Sources/ComponentsKit/Shared/Image/UniversalImage.swift @@ -11,9 +11,9 @@ import UIKit /// /// This type is intended to be carried in view models and resolved into /// platform-specific images by higher-level helpers or components. -public struct UniversalImage: Hashable { +public struct UniversalImage: Hashable, @unchecked Sendable { /// Internal representation of the image source. - private enum ImageRepresentable: Hashable { + private enum ImageRepresentable: Hashable, @unchecked Sendable { /// An SF Symbol identified by its system name. case sfSymbol(String) /// An asset catalog image identified by name and an optional bundle. diff --git a/Sources/ComponentsKit/Shared/Protocols/ComponentVM.swift b/Sources/ComponentsKit/Shared/Protocols/ComponentVM.swift index 2cfa607d..41c2064b 100644 --- a/Sources/ComponentsKit/Shared/Protocols/ComponentVM.swift +++ b/Sources/ComponentsKit/Shared/Protocols/ComponentVM.swift @@ -1,2 +1,2 @@ /// A protocol that defines a component view model. -public protocol ComponentVM: Equatable, Initializable, Updatable {} +public protocol ComponentVM: Equatable, Initializable, Updatable, Sendable {} diff --git a/Sources/ComponentsKit/Shared/Types/AnimationScale.swift b/Sources/ComponentsKit/Shared/Types/AnimationScale.swift index 7d423ee5..ee8f14ea 100644 --- a/Sources/ComponentsKit/Shared/Types/AnimationScale.swift +++ b/Sources/ComponentsKit/Shared/Types/AnimationScale.swift @@ -1,7 +1,7 @@ import Foundation /// An enumeration that defines how much a component shrinks or expands during animations. -public enum AnimationScale: Hashable { +public enum AnimationScale: Hashable, Sendable { /// No scaling is applied, meaning the component remains at its original size. case none /// A small scaling effect is applied, using a predefined value from the configuration. diff --git a/Sources/ComponentsKit/Shared/Types/BackgroundStyle.swift b/Sources/ComponentsKit/Shared/Types/BackgroundStyle.swift index 783ab0f7..227387e6 100644 --- a/Sources/ComponentsKit/Shared/Types/BackgroundStyle.swift +++ b/Sources/ComponentsKit/Shared/Types/BackgroundStyle.swift @@ -1,7 +1,7 @@ import Foundation /// Defines how a component renders its background. -public enum BackgroundStyle { +public enum BackgroundStyle: Sendable { /// A regular filled background using the component's configured background color. case solid /// A system liquid glass effect that lets underlying content show through the component. diff --git a/Sources/ComponentsKit/Shared/Types/BorderWidth.swift b/Sources/ComponentsKit/Shared/Types/BorderWidth.swift index 6110b233..93bb205e 100644 --- a/Sources/ComponentsKit/Shared/Types/BorderWidth.swift +++ b/Sources/ComponentsKit/Shared/Types/BorderWidth.swift @@ -1,7 +1,7 @@ import Foundation /// An enumeration that defines border thickness for components. -public enum BorderWidth: Hashable { +public enum BorderWidth: Hashable, Sendable { /// No border. case none /// A small border width. diff --git a/Sources/ComponentsKit/Shared/Types/ButtonStyle.swift b/Sources/ComponentsKit/Shared/Types/ButtonStyle.swift index 0dc44879..d7a9263b 100644 --- a/Sources/ComponentsKit/Shared/Types/ButtonStyle.swift +++ b/Sources/ComponentsKit/Shared/Types/ButtonStyle.swift @@ -1,7 +1,7 @@ import Foundation /// The buttons appearance style. -public enum ButtonStyle: Hashable { +public enum ButtonStyle: Hashable, Sendable { /// A button with a filled background. case filled /// A button with a transparent background. diff --git a/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift b/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift index f62dad6a..d3033a89 100644 --- a/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift +++ b/Sources/ComponentsKit/Shared/Types/ComponentRadius.swift @@ -2,7 +2,7 @@ import Foundation import SwiftUI /// An enumeration that defines the corner radius options for components. -public enum ComponentRadius: Hashable { +public enum ComponentRadius: Hashable, Sendable { /// No corner radius, resulting in sharp edges. case none /// A small corner radius. diff --git a/Sources/ComponentsKit/Shared/Types/ComponentSize.swift b/Sources/ComponentsKit/Shared/Types/ComponentSize.swift index 14e0360f..d0ea00cd 100644 --- a/Sources/ComponentsKit/Shared/Types/ComponentSize.swift +++ b/Sources/ComponentsKit/Shared/Types/ComponentSize.swift @@ -1,7 +1,7 @@ import Foundation /// An enumeration that defines size options for a component. -public enum ComponentSize: Hashable { +public enum ComponentSize: Hashable, Sendable { /// A small-sized component. case small /// A medium-sized component. diff --git a/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift b/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift index ca62838b..8ac5dd95 100644 --- a/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift +++ b/Sources/ComponentsKit/Shared/Types/ContainerRadius.swift @@ -1,7 +1,7 @@ import Foundation /// Defines the corner radius options for a container's content area. -public enum ContainerRadius: Hashable { +public enum ContainerRadius: Hashable, Sendable { /// No corner radius is applied, resulting in sharp edges. case none /// A small corner radius is applied. diff --git a/Sources/ComponentsKit/Shared/Types/InputStyle.swift b/Sources/ComponentsKit/Shared/Types/InputStyle.swift index 34da511c..c89a0ed8 100644 --- a/Sources/ComponentsKit/Shared/Types/InputStyle.swift +++ b/Sources/ComponentsKit/Shared/Types/InputStyle.swift @@ -1,7 +1,7 @@ import Foundation /// The appearance style of inputs. -public enum InputStyle: Hashable { +public enum InputStyle: Hashable, Sendable { /// An input with a partially transparent background. case light /// An input with a transparent background and a border. diff --git a/Sources/ComponentsKit/Shared/Types/LineCap.swift b/Sources/ComponentsKit/Shared/Types/LineCap.swift index 833aa40c..07324ca9 100644 --- a/Sources/ComponentsKit/Shared/Types/LineCap.swift +++ b/Sources/ComponentsKit/Shared/Types/LineCap.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// Defines the style of line endings. -public enum LineCap { +public enum LineCap: Sendable { /// The line ends with a semicircular arc that extends beyond the endpoint, creating a rounded appearance. case rounded /// The line ends exactly at the endpoint with a flat edge. diff --git a/Sources/ComponentsKit/Shared/Types/Paddings.swift b/Sources/ComponentsKit/Shared/Types/Paddings.swift index 641fbf3c..e58de53e 100644 --- a/Sources/ComponentsKit/Shared/Types/Paddings.swift +++ b/Sources/ComponentsKit/Shared/Types/Paddings.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// Defines padding values for each edge. -public struct Paddings: Hashable { +public struct Paddings: Hashable, Sendable { /// The padding value for the top edge. public var top: CGFloat diff --git a/Sources/ComponentsKit/Shared/Types/Shadow.swift b/Sources/ComponentsKit/Shared/Types/Shadow.swift index ed873a18..681b7d9e 100644 --- a/Sources/ComponentsKit/Shared/Types/Shadow.swift +++ b/Sources/ComponentsKit/Shared/Types/Shadow.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// Defines shadow options for components. -public enum Shadow: Hashable { +public enum Shadow: Hashable, Sendable { /// No shadow is applied. case none /// A small shadow. diff --git a/Sources/ComponentsKit/Shared/Types/SubmitType.swift b/Sources/ComponentsKit/Shared/Types/SubmitType.swift index aab22ce7..e79d4672 100644 --- a/Sources/ComponentsKit/Shared/Types/SubmitType.swift +++ b/Sources/ComponentsKit/Shared/Types/SubmitType.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// Specifies the text string that displays in the Return key of a keyboard. -public enum SubmitType { +public enum SubmitType: Sendable { /// Specifies that the title of the Return key is *Done*. case done /// Specifies that the title of the Return key is *Go*. diff --git a/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift b/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift index cedc6c77..20c88097 100644 --- a/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift +++ b/Sources/ComponentsKit/Shared/Types/TextAutocapitalization.swift @@ -2,7 +2,7 @@ import SwiftUI import UIKit /// The autocapitalization behavior applied during text input. -public enum TextAutocapitalization { +public enum TextAutocapitalization: Sendable { /// Do not capitalize anything. case never /// Capitalize every letter. diff --git a/Sources/ComponentsKit/Theme/Layout.swift b/Sources/ComponentsKit/Theme/Layout.swift index c79f51a2..d2cf617f 100644 --- a/Sources/ComponentsKit/Theme/Layout.swift +++ b/Sources/ComponentsKit/Theme/Layout.swift @@ -2,11 +2,11 @@ import Foundation extension Theme { /// A structure that defines the layout-related configurations for components in the framework. - public struct Layout: Initializable, Updatable, Equatable { + public struct Layout: Initializable, Updatable, Equatable, Sendable { // MARK: - Radius /// A structure representing radius values for components. - public struct Radius: Equatable { + public struct Radius: Equatable, Sendable { /// The small radius size. public var small: CGFloat /// The medium radius size. @@ -30,7 +30,7 @@ extension Theme { // MARK: - BorderWidth /// A structure representing border width values for components. - public struct BorderWidth: Equatable { + public struct BorderWidth: Equatable, Sendable { /// The small border width. public var small: CGFloat /// The medium border width. @@ -56,7 +56,7 @@ extension Theme { /// A structure representing animation scale values for components. /// /// The values must be between `0.0` and `1.0`. - public struct AnimationScale: Equatable { + public struct AnimationScale: Equatable, Sendable { /// The small animation scale. public var small: CGFloat /// The medium animation scale. @@ -88,7 +88,7 @@ extension Theme { // MARK: - Shadow /// A structure that defines the parameters for a shadow effect. - public struct ShadowParams: Equatable { + public struct ShadowParams: Equatable, Sendable { /// The blur radius of the shadow. /// /// A larger radius results in a more diffuse shadow. @@ -119,7 +119,7 @@ extension Theme { } /// A structure that defines shadow presets for small, medium, and large shadows. - public struct Shadow: Equatable { + public struct Shadow: Equatable, Sendable { /// The shadow parameters for a small shadow. public var small: ShadowParams @@ -147,7 +147,7 @@ extension Theme { // MARK: - Typography /// A structure representing a set of fonts for different component sizes. - public struct FontSet: Equatable { + public struct FontSet: Equatable, Sendable { /// The small font. public var small: UniversalFont /// The medium font. @@ -169,7 +169,7 @@ extension Theme { } /// A structure representing typography settings for various components. - public struct Typography: Equatable { + public struct Typography: Equatable, Sendable { /// The font set for headlines. public var headline: FontSet /// The font set for body text. diff --git a/Sources/ComponentsKit/Theme/Palette.swift b/Sources/ComponentsKit/Theme/Palette.swift index fb435dfc..d674a47d 100644 --- a/Sources/ComponentsKit/Theme/Palette.swift +++ b/Sources/ComponentsKit/Theme/Palette.swift @@ -2,7 +2,7 @@ import Foundation extension Theme { /// Defines a set of colors that are used for styling components and interfaces. - public struct Palette: Initializable, Updatable, Equatable { + public struct Palette: Initializable, Updatable, Equatable, Sendable { /// The color for the main background of the interface. public var background: UniversalColor = .themed( light: .hex("#FFFFFF"), diff --git a/Sources/ComponentsKit/Theme/Theme.swift b/Sources/ComponentsKit/Theme/Theme.swift index 01aac7e4..537c17d5 100644 --- a/Sources/ComponentsKit/Theme/Theme.swift +++ b/Sources/ComponentsKit/Theme/Theme.swift @@ -2,7 +2,7 @@ import Foundation /// A predefined set of colors and layout attributes that ensure visual consistency across the /// application. -public struct Theme: Initializable, Updatable, Equatable { +public struct Theme: Initializable, Updatable, Equatable, Sendable { // MARK: - Properties /// The palette of colors. @@ -26,6 +26,7 @@ extension Theme { /// A current instance of `Theme` for global use. /// /// Triggers `Theme.didChangeThemeNotification` notification when the value changes. + nonisolated(unsafe) public static var current = Self() { didSet { NotificationCenter.default.post(