diff --git a/Resources/UI/SwiftUI/README.md b/Resources/UI/SwiftUI/README.md index 552c310d..ceec1b32 100644 --- a/Resources/UI/SwiftUI/README.md +++ b/Resources/UI/SwiftUI/README.md @@ -4,23 +4,24 @@ A package including components to help you out developing for SwiftUI framework. ### Components -| Views | | -| :--- | :--- | -| [ActionButton](ActionButton) | Generic and customizable CTA button | -| [PhotoPickerView](/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift) | Photo and Camera picker view used in combination with `PhotoPickerModifier` | -| [ProfileImageView](ProfileImageView) | Generic and customizable profile image view component | -| [ProgressStyle](/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift) | Customizable ProgressViewStyle | -| [RemoteImage](/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift) | Fetching remote images using Kingfisher | -| [ScrollViewWithOffset](/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift) | ScrollView that expose offset as we scroll | +| Views | Platform | | +| :--- | :--- | :--- | +| [ActionButton](ActionButton) | all | Generic and customizable CTA button | +| [PhotoPickerView](/Sources/UI/SwiftUI/Views/PhotoPickerView/PhotoPickerView.swift) | iOS | Photo and Camera picker view used in combination with `PhotoPickerModifier` | +| [ProfileImageView](ProfileImageView) | all | Generic and customizable profile image view component | +| [ProgressStyle](/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift) | all | Customizable ProgressViewStyle | +| [RemoteImage](/Sources/UI/SwiftUI/Views/RemoteImage/RemoteImage.swift) | all | Fetching remote images using Kingfisher | +| [ScrollViewWithOffset](/Sources/UI/SwiftUI/Views/ScrollViewWithOffset/ScrollViewWithOffset.swift) | all | ScrollView that expose offset as we scroll | +| [SimpleColorPicker](/Sources/UI/SwiftUI/Views/SimpleColorPicker/SimpleColorPicker.swift) | macOS | Wrapper for NSColorWell component | -| View Modifiers | | -| :--- | :--- | -| [MeasureSizeModifier](/Sources/UI/SwiftUI/View%20Modifiers/MeasureSizeModifier.swift) | A modifier to return size of the underlying view | -| [OnFirstAppearModifier](/Sources/UI/SwiftUI/View%20Modifiers/OnFirstAppearModifier.swift) | Similar to the `OnAppear` modifier, but only runs once per view lifecycle | -| [PhotoPickerModifier](/Sources/UI/SwiftUI/View%20Modifiers/PhotoPickerModifier.swift) | Easily add photo or camera picker to the view | -| [PinchToZoomModifier](/Sources/UI/SwiftUI/View%20Modifiers/PinchToZoomModifier.swift) | Pinching and zooming in/out with ease | -| [SquaredModifier](/Sources/UI/SwiftUI/View%20Modifiers/SquaredModifier.swift) | Make given view squared. This is mostly used with images to properly keep the aspect ratio | -| [TextFieldLimitModifer](/Sources/UI/SwiftUI/View%20Modifiers/TextFieldLimitModifer.swift) | This modifier adds an upper bound text length limitation to the TextField | +| View Modifiers | Platform | | +| :--- | :--- | :--- | +| [MeasureSizeModifier](/Sources/UI/SwiftUI/View%20Modifiers/MeasureSizeModifier.swift) | all | A modifier to return size of the underlying view | +| [OnFirstAppearModifier](/Sources/UI/SwiftUI/View%20Modifiers/OnFirstAppearModifier.swift) | all | Similar to the `OnAppear` modifier, but only runs once per view lifecycle | +| [PhotoPickerModifier](/Sources/UI/SwiftUI/View%20Modifiers/PhotoPickerModifier.swift) | iOS | Easily add photo or camera picker to the view | +| [PinchToZoomModifier](/Sources/UI/SwiftUI/View%20Modifiers/PinchToZoomModifier.swift) | iOS | Pinching and zooming in/out with ease | +| [SquaredModifier](/Sources/UI/SwiftUI/View%20Modifiers/SquaredModifier.swift) | all | Make given view squared. This is mostly used with images to properly keep the aspect ratio | +| [TextFieldLimitModifer](/Sources/UI/SwiftUI/View%20Modifiers/TextFieldLimitModifer.swift) | all | This modifier adds an upper bound text length limitation to the TextField | | Extensions | | :--- | diff --git a/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift b/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift index e126ae30..9d67fcf3 100644 --- a/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift +++ b/Sources/UI/SwiftUI/Views/ProgressStyle/ProgressStyle.swift @@ -6,7 +6,6 @@ // Copyright © 2024 Povio Inc. All rights reserved. // - import SwiftUI @available(iOS 15.0, *) diff --git a/Sources/UI/SwiftUI/Views/SimpleColorPicker/SimpleColorPicker.swift b/Sources/UI/SwiftUI/Views/SimpleColorPicker/SimpleColorPicker.swift new file mode 100644 index 00000000..a6d080ef --- /dev/null +++ b/Sources/UI/SwiftUI/Views/SimpleColorPicker/SimpleColorPicker.swift @@ -0,0 +1,79 @@ +// +// SimpleColorPicker.swift +// PovioKit +// +// Created by Borut Tomazin on 15/08/2024. +// Copyright © 2024 Povio Inc. All rights reserved. +// + +#if os(macOS) +import SwiftUI +import Combine + +/// SwiftUI wrapper for NSColorWell, allowing the selection of colors with a customizable size. +public struct SimpleColorPicker: NSViewRepresentable { + @Binding var selection: Color + var size: CGSize? + + public init(selection: Binding, size: CGSize? = nil) { + self._selection = selection + self.size = size + } + + public func makeNSView(context: Context) -> NSColorWell { + let colorWell: NSColorWell + if #available(macOS 13.0, *) { + colorWell = NSColorWell(style: .minimal) + } else { + colorWell = NSColorWell() + } + colorWell.color = NSColor(selection) + + context.coordinator.startObservingColorChange(of: colorWell) + + // override the size + if let size { + colorWell.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + colorWell.widthAnchor.constraint(equalToConstant: size.width), + colorWell.heightAnchor.constraint(equalToConstant: size.height) + ]) + } + + return colorWell + } + + public func updateNSView(_ nsView: NSColorWell, context: Context) { + context.coordinator.colorDidChange = { + selection = Color(nsColor: $0) + } + + // update the size + if let size { + if let widthConstraint = nsView.constraints.first(where: { $0.firstAttribute == .width }) { + widthConstraint.constant = size.width + } + if let heightConstraint = nsView.constraints.first(where: { $0.firstAttribute == .height }) { + heightConstraint.constant = size.height + } + } + } + + public func makeCoordinator() -> Coordinator { + Coordinator() + } + + @MainActor + public class Coordinator: NSObject { + var colorDidChange: ((NSColor) -> Void)? + + private var cancellable: AnyCancellable? + + func startObservingColorChange(of colorWell: NSColorWell) { + cancellable = colorWell.publisher(for: \.color).sink { [weak self] in + self?.colorDidChange?($0) + } + } + } +} +#endif