Skip to content

Commit

Permalink
Merge pull request #1083 from adevinta/divider-demo
Browse files Browse the repository at this point in the history
New component: Divider
  • Loading branch information
LouisBorleeAdevinta authored Aug 2, 2024
2 parents 84457fe + 469cc51 commit fab7f7d
Show file tree
Hide file tree
Showing 9 changed files with 456 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .Demo/Classes/Enum/UIComponent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct UIComponent: RawRepresentable, CaseIterable, Equatable {
.iconButton,
.checkbox,
.chip,
.divider,
.formField,
.icon,
.popover,
Expand Down Expand Up @@ -43,6 +44,7 @@ struct UIComponent: RawRepresentable, CaseIterable, Equatable {
static let button = UIComponent(rawValue: "Button")
static let checkbox = UIComponent(rawValue: "Checkbox")
static let chip = UIComponent(rawValue: "Chip")
static let divider = UIComponent(rawValue: "Divider")
static let formField = UIComponent(rawValue: "FormField")
static let icon = UIComponent(rawValue: "Icon")
static let iconButton = UIComponent(rawValue: "Icon Button")
Expand Down
4 changes: 4 additions & 0 deletions .Demo/Classes/View/Components/ComponentsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ struct ComponentsView: View {
}
}

Button("Divider") {
self.navigateToView(DividerComponentView())
}

Button("FormField") {
self.navigateToView(FormFieldComponentView())
}
Expand Down
2 changes: 2 additions & 0 deletions .Demo/Classes/View/Components/ComponentsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ extension ComponentsViewController {
)
case .chip:
viewController = ChipComponentViewController.build()
case .divider:
viewController = DividerComponentUIViewController.build()
case .formField:
viewController = FormFieldComponentUIViewController.build()
case .icon:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// DividerComponentView.swift
// SparkDemo
//
// Created by louis.borlee on 31/07/2024.
// Copyright © 2024 Adevinta. All rights reserved.
//

import SwiftUI
import SparkDivider

struct DividerComponentView: View {

private let theme = SparkTheme()

@State private var text: String = "Text"
@State private var intent: DividerIntent = .outline
@State private var axis: DividerAxis = .horizontal
@State private var alignment: DividerAlignment = .center

@State private var withText: CheckboxSelectionState = .unselected

var body: some View {
Component(
name: "Divider") {
EnumSelector(
title: "Intent",
dialogTitle: "Select an intent",
values: DividerIntent.allCases,
value: self.$intent
)
EnumSelector(
title: "Axis",
dialogTitle: "Select an axis",
values: DividerAxis.allCases,
value: self.$axis
)
EnumSelector(
title: "Alignment",
dialogTitle: "Select an alignment",
values: DividerAlignment.allCases,
value: self.$alignment
)
HStack(spacing: 12) {
Text("Text")
TextField("Divider text", text: $text)
.textFieldStyle(.roundedBorder)
}
} integration: {
let divider = divider()
if axis == .vertical {
divider
.frame(height: 300)
} else {
divider
}
}
}

@ViewBuilder
private func divider() -> some View {
HStack {
Spacer(minLength: 0)
if text.isEmpty == false {
DividerView(
theme: theme,
intent: intent,
axis: axis,
alignment: alignment,
text: {
Text(text)
}
)
} else {
DividerView(
theme: SparkTheme(),
intent: intent,
axis: axis,
alignment: alignment
)
}
Spacer(minLength: 0)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// DividerComponentUIView.swift
// SparkDemo
//
// Created by louis.borlee on 31/07/2024.
// Copyright © 2024 Adevinta. All rights reserved.
//

import Combine
import UIKit
@_spi(SI_SPI) import SparkCommon

final class DividerComponentUIView: ComponentUIView {

// MARK: - Components
private let componentView: DividerUIView

// MARK: - Properties

private let viewModel: DividerComponentUIViewModel
private var cancellables: Set<AnyCancellable> = []

private var heightConstraint = NSLayoutConstraint()

// MARK: - Initializer
init(viewModel: DividerComponentUIViewModel) {
self.viewModel = viewModel

let divider = DividerUIView(
theme: self.viewModel.theme,
intent: self.viewModel.intent
)
divider.label.text = self.viewModel.text
divider.label.numberOfLines = 0
divider.axis = self.viewModel.axis
divider.alignment = self.viewModel.alignment

self.componentView = divider

super.init(
viewModel: viewModel,
integrationStackViewAlignment: .fill,
componentView: self.componentView
)

// Setup
self.setupSubscriptions()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - Subscribe
private func setupSubscriptions() {
self.viewModel.$theme.subscribe(in: &self.cancellables) { [weak self] theme in
guard let self = self else { return }
let themes = self.viewModel.themes
let themeTitle: String? = theme is SparkTheme ? themes.first?.title : themes.last?.title

self.viewModel.themeConfigurationItemViewModel.buttonTitle = themeTitle
self.viewModel.configurationViewModel.update(theme: theme)

self.componentView.theme = theme
}

self.viewModel.$intent.subscribe(in: &self.cancellables) { [weak self] intent in
guard let self = self else { return }
self.viewModel.intentConfigurationItemViewModel.buttonTitle = intent.name
self.componentView.intent = intent
}

self.viewModel.$axis.subscribe(in: &self.cancellables) { [weak self] axis in
guard let self = self else { return }
self.viewModel.axisConfigurationItemViewModel.buttonTitle = axis.name
self.componentView.axis = axis
if axis == .vertical {
self.heightConstraint = self.componentView.heightAnchor.constraint(equalToConstant: 300)
self.heightConstraint.isActive = true
} else {
self.heightConstraint.isActive = false
self.componentView.removeConstraint(self.heightConstraint)
}
}

self.viewModel.$alignment.subscribe(in: &self.cancellables) { [weak self] alignment in
guard let self = self else { return }
self.viewModel.alignmentConfigurationItemViewModel.buttonTitle = alignment.name
self.componentView.alignment = alignment
}

self.viewModel.$text.subscribe(in: &self.cancellables) { [weak self] text in
guard let self = self else { return }
self.viewModel.textConfigurationItemViewModel.buttonTitle = text
self.componentView.label.text = text
if let text, text.isEmpty == false {
self.componentView.showLabel = true
} else {
self.componentView.showLabel = false
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//
// DividerComponentUIViewController.swift
// SparkDemo
//
// Created by louis.borlee on 31/07/2024.
// Copyright © 2024 Adevinta. All rights reserved.
//

import Combine
import SparkCore
import SwiftUI
import UIKit
@_spi(SI_SPI) import SparkCommon

final class DividerComponentUIViewController: UIViewController {

// MARK: - Published Properties
@ObservedObject private var themePublisher = SparkThemePublisher.shared

// MARK: - Properties
let componentView: DividerComponentUIView
let viewModel: DividerComponentUIViewModel
private var cancellables: Set<AnyCancellable> = []

// MARK: - Initializer
init(viewModel: DividerComponentUIViewModel) {
self.viewModel = viewModel
self.componentView = DividerComponentUIView(viewModel: viewModel)
super.init(nibName: nil, bundle: nil)

self.componentView.viewController = self
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - Lifecycle
override func loadView() {
super.loadView()
view = componentView
}

// MARK: - ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "Divider"
self.addPublisher()
}

// MARK: - Add Publishers
private func addPublisher() {

self.themePublisher
.$theme
.sink { [weak self] theme in
guard let self = self else { return }
self.viewModel.theme = theme
self.navigationController?.navigationBar.tintColor = theme.colors.main.main.uiColor
}
.store(in: &self.cancellables)

self.viewModel.showThemeSheet.subscribe(in: &self.cancellables) { intents in
self.presentThemeActionSheet(intents)
}

self.viewModel.showIntentSheet.subscribe(in: &self.cancellables) { intents in
self.presentIntentActionSheet(intents)
}

self.viewModel.showAxisSheet.subscribe(in: &self.cancellables) { axis in
self.presentAxisActionSheet(axis)
}

self.viewModel.showAlignmentSheet.subscribe(in: &self.cancellables) { alignments in
self.presentAlignmentActionSheet(alignments)
}
}
}

// MARK: - Builder
extension DividerComponentUIViewController {

static func build() -> DividerComponentUIViewController {
let viewModel = DividerComponentUIViewModel(theme: SparkThemePublisher.shared.theme)
return DividerComponentUIViewController(viewModel: viewModel)
}
}

// MARK: - Navigation
extension DividerComponentUIViewController {

private func presentThemeActionSheet(_ themes: [ThemeCellModel]) {
let actionSheet = SparkActionSheet<Theme>.init(
values: themes.map { $0.theme },
texts: themes.map { $0.title }) { theme in
self.themePublisher.theme = theme
}
self.present(actionSheet, isAnimated: true)
}

private func presentIntentActionSheet(_ intents: [DividerIntent]) {
let actionSheet = SparkActionSheet<DividerIntent>.init(
values: intents,
texts: intents.map { $0.name }) { intent in
self.viewModel.intent = intent
}
self.present(actionSheet, isAnimated: true)
}

private func presentAxisActionSheet(_ axis: [DividerAxis]) {
let actionSheet = SparkActionSheet<DividerAxis>.init(
values: axis,
texts: axis.map { $0.name }) { axis in
self.viewModel.axis = axis
}
self.present(actionSheet, isAnimated: true)
}

private func presentAlignmentActionSheet(_ alignments: [DividerAlignment]) {
let actionSheet = SparkActionSheet<DividerAlignment>.init(
values: alignments,
texts: alignments.map { $0.name }) { alignment in
self.viewModel.alignment = alignment
}
self.present(actionSheet, isAnimated: true)
}
}
Loading

0 comments on commit fab7f7d

Please sign in to comment.