diff --git a/core/Sources/Components/Chip/View/UIKit/ChipUIView.swift b/core/Sources/Components/Chip/View/UIKit/ChipUIView.swift index c7e585c15..38fd90e0f 100644 --- a/core/Sources/Components/Chip/View/UIKit/ChipUIView.swift +++ b/core/Sources/Components/Chip/View/UIKit/ChipUIView.swift @@ -539,6 +539,10 @@ public final class ChipUIView: UIControl { self.viewModel.isPressed = false } } + + public func enableComponentUserInteraction(_ isEnabled: Bool) { + self.stackView.isUserInteractionEnabled = isEnabled + } } // MARK: - Label priorities diff --git a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIView.swift b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIView.swift index 1f8db7146..2d56bcccb 100644 --- a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIView.swift +++ b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIView.swift @@ -75,19 +75,7 @@ final class ChipComponentUIView: ComponentUIView { } self.viewModel.$alignment.subscribe(in: &self.cancellables) { [weak self] alignment in - guard let self = self else { return } - let iconAlignment: ChipComponentUIViewModel.IconPosition - if self.viewModel.showIcon { - switch alignment { - case .leadingIcon: iconAlignment = .leading - case .trailingIcon: iconAlignment = .trailing - @unknown default: fatalError() - } - } else { - iconAlignment = .none - } - self.viewModel.iconConfigurationItemViewModel.buttonTitle = iconAlignment.name - self.componentView.alignment = alignment + self?.componentView.alignment = alignment } self.viewModel.$title.subscribe(in: &self.cancellables) { [weak self] title in @@ -96,7 +84,6 @@ final class ChipComponentUIView: ComponentUIView { self.componentView.text = title } - self.viewModel.$icon.subscribe(in: &self.cancellables) { [weak self] icon in guard let self = self else { return } @@ -106,6 +93,11 @@ final class ChipComponentUIView: ComponentUIView { self.viewModel.$badge.subscribe(in: &self.cancellables) { [weak self] badge in guard let self = self else { return } + if let _ = badge as? UIButton { + self.componentView.enableComponentUserInteraction(true) + } else { + self.componentView.enableComponentUserInteraction(false) + } self.componentView.component = badge } diff --git a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewController.swift b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewController.swift index 47c2ad676..f1aadf64b 100644 --- a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewController.swift +++ b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewController.swift @@ -75,6 +75,10 @@ final class ChipComponentViewController: UIViewController { self.viewModel.showIconPosition.subscribe(in: &self.cancellables) { variants in self.presentIconAlignmentActionSheet(variants) } + + self.viewModel.showExtraComponent.subscribe(in: &self.cancellables) { variants in + self.presentExtraComponentActionSheet(variants) + } } } @@ -122,13 +126,16 @@ extension ChipComponentViewController { let actionSheet = SparkActionSheet.init( values: variants, texts: variants.map{ $0.name }) { variant in - switch variant { - case .none: self.viewModel.showIcon = false - case .leading: self.viewModel.showIcon = true - self.viewModel.alignment = .leadingIcon - case .trailing: self.viewModel.showIcon = true - self.viewModel.alignment = .trailingIcon - } + self.viewModel.iconAlignmentDidUpdate(variant) + } + self.present(actionSheet, animated: true) + } + + private func presentExtraComponentActionSheet(_ variants: [ChipComponentUIViewModel.ExtraComponent]) { + let actionSheet = SparkActionSheet.init( + values: variants, + texts: variants.map{ $0.name }) { variant in + self.viewModel.extraComponentDidUpdate(variant) } self.present(actionSheet, animated: true) } diff --git a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewModel.swift b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewModel.swift index 3a2ee9619..5c8999dbd 100644 --- a/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewModel.swift +++ b/spark/Demo/Classes/View/Components/Chip/UIKit/ChipComponentUIViewModel.swift @@ -19,6 +19,12 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { case none } + enum ExtraComponent: CaseIterable { + case badge + case button + case none + } + private static let alertIcon = UIImage(imageLiteralResourceName: "alert") private var label: String? = "Label" { @@ -47,6 +53,11 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { .eraseToAnyPublisher() } + var showExtraComponent: AnyPublisher<[ExtraComponent], Never> { + showExtraComponentSheetSubject + .eraseToAnyPublisher() + } + var themes = ThemeCellModel.themes // MARK: - Private Properties @@ -54,6 +65,7 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { private var showIntentSheetSubject: PassthroughSubject<[ChipIntent], Never> = .init() private var showVariantSheetSubject: PassthroughSubject<[ChipVariant], Never> = .init() private var showIconPositionSheetSubject: PassthroughSubject<[IconPosition], Never> = .init() + private var showExtraComponentSheetSubject: PassthroughSubject<[ExtraComponent], Never> = .init() // MARK: - Items Properties lazy var themeConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { @@ -81,10 +93,21 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { }() lazy var iconConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { - return .init( + let viewModel = ComponentsConfigurationItemUIViewModel( name: "Icon Alignment", type: .button, target: (source: self, action: #selector(self.presentIconPositonSheet))) + viewModel.buttonTitle = IconPosition.none.name + return viewModel + }() + + lazy var extraComponentConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { + let viewModel = ComponentsConfigurationItemUIViewModel( + name: "Extra Component", + type: .button, + target: (source: self, action: #selector(self.presentExtraComponentSheet))) + viewModel.buttonTitle = ExtraComponent.none.name + return viewModel }() lazy var labelContentConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { @@ -94,13 +117,6 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { target: (source: self, action: #selector(self.labelChanged(_:)))) }() - lazy var badgeConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { - return .init( - name: "Show Badge", - type: .checkbox(title: "", isOn: self.showBadge), - target: (source: self, action: #selector(self.showBadgeChanged))) - }() - lazy var disableConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { return .init( name: "Enable", @@ -128,12 +144,6 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { } } - var showBadge = false { - didSet { - self.badge = self.showBadge ? self.createBadge() : nil - } - } - // swiftlint:disable all var hasAction: Bool { set { @@ -149,7 +159,7 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { @Published var intent: ChipIntent @Published var variant: ChipVariant @Published var alignment: ChipAlignment = .leadingIcon - @Published var badge: BadgeUIView? + @Published var badge: UIView? @Published var isEnabled = true @Published var isSelected = false @Published var title: String? = "Label" @@ -162,8 +172,8 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { self.intentConfigurationItemViewModel, self.variantConfigurationItemViewModel, self.iconConfigurationItemViewModel, + self.extraComponentConfigurationItemViewModel, self.labelContentConfigurationItemViewModel, - self.badgeConfigurationItemViewModel, self.disableConfigurationItemViewModel, self.selectedConfigurationItemViewModel, self.hasActionConfigurationItemViewModel @@ -196,11 +206,56 @@ final class ChipComponentUIViewModel: ComponentUIViewModel { return badge } + private func createButton() -> UIButton { + let button = UIButton() + + let image = UIImage(systemName: "xmark.circle")? + .withRenderingMode(.alwaysTemplate) + + var configuration = UIButton.Configuration.bordered() + configuration.image = image + configuration.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) + configuration.baseBackgroundColor = .clear + + button.configuration = configuration + button.addTarget(self, action: #selector(self.deleteItem), for: .touchUpInside) + button.translatesAutoresizingMaskIntoConstraints = false + + button.tintColor = self.theme.colors.basic.basic.uiColor + return button + } + + func iconAlignmentDidUpdate(_ alignment: IconPosition) { + switch alignment { + case .none: self.showIcon = false + case .leading: self.showIcon = true + self.alignment = .leadingIcon + case .trailing: self.showIcon = true + self.alignment = .trailingIcon + } + + self.iconConfigurationItemViewModel.buttonTitle = alignment.name + } + + func extraComponentDidUpdate(_ component: ExtraComponent) { + self.extraComponentConfigurationItemViewModel.buttonTitle = component.name + + switch component { + case .none: self.badge = nil + case .button: self.badge = self.createButton() + case .badge: self.badge = self.createBadge() + } + } + } // MARK: - Navigation extension ChipComponentUIViewModel { + @objc func deleteItem() { + + } + @objc func presentThemeSheet() { self.showThemeSheetSubject.send(themes) } @@ -217,6 +272,10 @@ extension ChipComponentUIViewModel { self.showIconPositionSheetSubject.send(IconPosition.allCases) } + @objc func presentExtraComponentSheet() { + self.showExtraComponentSheetSubject.send(ExtraComponent.allCases) + } + @objc func labelChanged(_ textField: UITextField) { if textField.text?.isEmpty == false { self.label = textField.text @@ -225,10 +284,6 @@ extension ChipComponentUIViewModel { } } - @objc func showBadgeChanged() { - self.showBadge.toggle() - } - @objc func showIconChanged() { self.showIcon.toggle() }