diff --git a/Libraries/UI/Kit/Sources/Components/HostingConfiguration.swift b/Libraries/UI/Kit/Sources/Components/HostingConfiguration.swift new file mode 100644 index 0000000..0f2550f --- /dev/null +++ b/Libraries/UI/Kit/Sources/Components/HostingConfiguration.swift @@ -0,0 +1,100 @@ +// +// HostingConfiguration.swift +// ReviewsUIKit +// +// Created by Javier Cicchelli on 18/03/2024. +// Copyright © 2024 Röck+Cöde. All rights reserved. +// + +import SwiftUI + +public struct HostingConfiguration: UIContentConfiguration { + + // MARK: Type aliases + public typealias ContentClosure = () -> Content + + // MARK: Constants + fileprivate let hostingController: UIHostingController + + // MARK: Initialisers + public init(@ViewBuilder content: ContentClosure) { + hostingController = UIHostingController(rootView: content()) + } + + // MARK: Functions + public func makeContentView() -> UIView & UIContentView { + ContentView(self) + } + + public func updated( + for state: UIConfigurationState + ) -> HostingConfiguration { + self + } + +} + +// MARK: - Classes +class ContentView: UIView, UIContentView { + + // MARK: Properties + var configuration: UIContentConfiguration { + didSet { + configure(configuration) + } + } + + // MARK: Initialisers + init(_ configuration: UIContentConfiguration) { + self.configuration = configuration + + super.init(frame: .zero) + } + + required init?(coder: NSCoder) { + // This view shouldn't be initialized this way so we crash + fatalError("init(coder:) has not been implemented") + } + +} + +// MARK: - Helpers +private extension ContentView { + + // MARK: Functions + func configure(_ configuration: UIContentConfiguration) { + guard + let configuration = configuration as? HostingConfiguration, + let parent = findNextViewController() + else { + return + } + + let hostingController = configuration.hostingController + + guard + let swiftUICellView = hostingController.view, + subviews.isEmpty + else { + hostingController.view.invalidateIntrinsicContentSize() + return + } + + hostingController.view.backgroundColor = .clear + + parent.addChild(hostingController) + addSubview(hostingController.view) + + hostingController.view.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + leadingAnchor.constraint(equalTo: swiftUICellView.leadingAnchor), + trailingAnchor.constraint(equalTo: swiftUICellView.trailingAnchor), + topAnchor.constraint(equalTo: swiftUICellView.topAnchor), + bottomAnchor.constraint(equalTo: swiftUICellView.bottomAnchor) + ]) + + hostingController.didMove(toParent: parent) + } + +} diff --git a/Libraries/UI/Kit/Sources/Extensions/UIView+Functions.swift b/Libraries/UI/Kit/Sources/Extensions/UIView+Functions.swift new file mode 100644 index 0000000..ead5fb8 --- /dev/null +++ b/Libraries/UI/Kit/Sources/Extensions/UIView+Functions.swift @@ -0,0 +1,24 @@ +// +// UIView+Functions.swift +// ReviewsUIKit +// +// Created by Javier Cicchelli on 19/03/2024. +// Copyright © 2024 Röck+Cöde VoF. All rights reserved. +// + +import UIKit + +extension UIView { + + // MARK: Functions + func findNextViewController() -> UIViewController? { + if let nextResponder = next as? UIViewController { + return nextResponder + } else if let nextResponder = next as? UIView { + return nextResponder.findNextViewController() + } + + return nil + } + +}