Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ struct UKComponentPreview<View, Model>: UIViewRepresentable where View: UKCompon
let model: Model
let view: View

init(model: Model, view: @escaping () -> View) {
self.view = view()
self.model = model
init(view: View) {
self.view = view
self.model = view.model
}

func makeUIView(context: Context) -> Container {
Expand All @@ -51,3 +51,9 @@ struct UKComponentPreview<View, Model>: UIViewRepresentable where View: UKCompon
container.component.model = self.model
}
}

extension UKComponent {
var preview: some View {
UKComponentPreview(view: self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ struct ButtonPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKButton(model: self.model)
}
UKButton(model: self.model)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SUButton(model: self.model)
Expand All @@ -28,12 +27,12 @@ struct ButtonPreview: View {
Toggle("Full Width", isOn: self.$model.isFullWidth)
SizePicker(selection: self.$model.size)
Picker("Style", selection: self.$model.style) {
Text("Filled").tag(ButtonStyle.filled)
Text("Plain").tag(ButtonStyle.plain)
Text("Bordered with small border").tag(ButtonStyle.bordered(.small))
Text("Bordered with medium border").tag(ButtonStyle.bordered(.medium))
Text("Bordered with large border").tag(ButtonStyle.bordered(.large))
Text("Bordered with custom border: 6px").tag(ButtonStyle.bordered(.custom(6)))
Text("Filled").tag(ButtonVM.Style.filled)
Text("Plain").tag(ButtonVM.Style.plain)
Text("Bordered with small border").tag(ButtonVM.Style.bordered(.small))
Text("Bordered with medium border").tag(ButtonVM.Style.bordered(.medium))
Text("Bordered with large border").tag(ButtonVM.Style.bordered(.large))
Text("Bordered with custom border: 6px").tag(ButtonVM.Style.bordered(.custom(6)))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ struct CheckboxPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKCheckbox(
initialValue: false,
model: self.model
)
}
UKCheckbox(
initialValue: false,
model: self.model
)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SUCheckbox(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ struct DividerPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKDivider(model: self.model)
}
UKDivider(model: self.model)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SUDivider(model: self.model)
}
Form {
Picker("Orientation", selection: self.$model.orientation) {
Text("Horizontal").tag(DividerVM.DividerOrientation.horizontal)
Text("Vertical").tag(DividerVM.DividerOrientation.vertical)
Text("Horizontal").tag(DividerVM.Orientation.horizontal)
Text("Vertical").tag(DividerVM.Orientation.vertical)
}
SizePicker(selection: self.$model.size)
Picker("Color", selection: self.$model.color) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,24 @@ import SwiftUI
import UIKit

struct InputFieldPreview: View {
@State private var model = InputFieldVM {
$0.title = "Title"
}
@State private var model = Self.initialModel

@State private var text: String = ""
@FocusState private var isFocused: Bool

@ObservedObject private var inputField = PreviewInputField()
@ObservedObject private var inputField = PreviewInputField(model: Self.initialModel)

var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
self.inputField
}
self.inputField
.preview
.onAppear {
self.inputField.model = Self.initialModel
}
.onChange(of: self.model) { newValue in
self.inputField.model = newValue
}
}
PreviewWrapper(title: "SwiftUI") {
SUInputField(
Expand Down Expand Up @@ -74,6 +77,12 @@ struct InputFieldPreview: View {
}
}
}

private static var initialModel: InputFieldVM {
return .init {
$0.title = "Title"
}
}
}

private final class PreviewInputField: UKInputField, ObservableObject, UITextFieldDelegate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ struct LoadingPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKLoading(model: self.model)
}
UKLoading(model: self.model)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SULoading(model: self.model)
Expand All @@ -23,7 +22,7 @@ struct LoadingPreview: View {
}
SizePicker(selection: self.$model.size)
Picker("Style", selection: self.$model.style) {
Text("Spinner").tag(LoadingStyle.spinner)
Text("Spinner").tag(LoadingVM.Style.spinner)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ struct RadioGroupPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKRadioGroup(model: self.model)
}
UKRadioGroup(model: self.model)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SURadioGroup(selectedId: $selectedId, model: self.model)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ struct SegmentedControlPreview: View {
var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
UKSegmentedControl(
selectedId: .iPad,
model: self.model
)
}
UKSegmentedControl(
selectedId: .iPad,
model: self.model
)
.preview
}
PreviewWrapper(title: "SwiftUI") {
SUSegmentedControl(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ import SwiftUI
import UIKit

struct TextInputPreviewPreview: View {
@State private var model = TextInputVM {
$0.placeholder = "Placeholder"
$0.minRows = 1
$0.maxRows = nil
}
@State private var model = Self.initialModel

@State private var text: String = ""
@FocusState private var isFocused: Bool

@ObservedObject private var textInput = PreviewTextInput()
@ObservedObject private var textInput = PreviewTextInput(model: Self.initialModel)

var body: some View {
VStack {
PreviewWrapper(title: "UIKit") {
UKComponentPreview(model: self.model) {
self.textInput
}
self.textInput
.preview
.onAppear {
self.textInput.model = Self.initialModel
}
.onChange(of: self.model) { newValue in
self.textInput.model = newValue
}
}
PreviewWrapper(title: "SwiftUI") {
SUTextInput(
Expand Down Expand Up @@ -75,6 +76,14 @@ struct TextInputPreviewPreview: View {
}
}
}

private static var initialModel: TextInputVM {
return .init {
$0.placeholder = "Placeholder"
$0.minRows = 1
$0.maxRows = nil
}
}
}

private final class PreviewTextInput: UKTextInput, ObservableObject {
Expand Down
18 changes: 10 additions & 8 deletions Sources/ComponentsKit/Button/Models/ButtonStyle.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import Foundation

/// The buttons appearance style.
public enum ButtonStyle: Hashable {
/// A button with a filled background.
case filled
/// A button with a transparent background.
case plain
/// A button with a transparent background and a border.
case bordered(BorderWidth)
extension ButtonVM {
/// The buttons appearance style.
public enum Style: Hashable {
/// A button with a filled background.
case filled
/// A button with a transparent background.
case plain
/// A button with a transparent background and a border.
case bordered(BorderWidth)
}
}
2 changes: 1 addition & 1 deletion Sources/ComponentsKit/Button/Models/ButtonVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public struct ButtonVM: ComponentVM {
/// The visual style of the button.
///
/// Defaults to `.filled`.
public var style: ButtonStyle = .filled
public var style: Style = .filled

/// Initializes a new instance of `ButtonVM` with default values.
public init() {}
Expand Down
66 changes: 28 additions & 38 deletions Sources/ComponentsKit/Button/SUButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ public struct SUButton: View {
/// A Boolean value indicating whether the button is pressed.
@State public var isPressed: Bool = false

@State private var viewFrame: CGRect = .zero
@Environment(\.colorScheme) private var colorScheme

// MARK: Initialization

/// Initializer.
Expand All @@ -32,7 +29,33 @@ public struct SUButton: View {
// MARK: Body

public var body: some View {
Text(self.model.title)
Button(self.model.title, action: self.action)
.buttonStyle(CustomButtonStyle(model: self.model))
.simultaneousGesture(DragGesture(minimumDistance: 0.0)
.onChanged { _ in
self.isPressed = true
}
.onEnded { _ in
self.isPressed = false
}
)
.disabled(!self.model.isEnabled)
.scaleEffect(
self.isPressed ? self.model.animationScale.value : 1,
anchor: .center
)
}
}

// MARK: - Helpers

private struct CustomButtonStyle: SwiftUI.ButtonStyle {
let model: ButtonVM

@Environment(\.colorScheme) var colorScheme

func makeBody(configuration: Configuration) -> some View {
configuration.label
.font(self.model.preferredFont.font)
.lineLimit(1)
.padding(.leading, self.model.horizontalPadding)
Expand All @@ -41,27 +64,8 @@ public struct SUButton: View {
.frame(height: self.model.height)
.foregroundStyle(self.model.foregroundColor.color(for: self.colorScheme))
.background(
GeometryReader { proxy in
(self.model.backgroundColor?.color(for: self.colorScheme) ?? Color.clear)
.preference(key: ViewFrameKey.self, value: proxy.frame(in: .local))
}
self.model.backgroundColor?.color(for: self.colorScheme) ?? Color.clear
)
.onPreferenceChange(ViewFrameKey.self) { value in
self.viewFrame = value
}
.gesture(DragGesture(minimumDistance: 0.0)
.onChanged { _ in
self.isPressed = true
}
.onEnded { value in
defer { self.isPressed = false }

if self.viewFrame.contains(value.location) {
self.action()
}
}
)
.disabled(!self.model.isEnabled)
.clipShape(
RoundedRectangle(
cornerRadius: self.model.cornerRadius.value()
Expand All @@ -76,19 +80,5 @@ public struct SUButton: View {
lineWidth: self.model.borderWidth
)
}
.scaleEffect(
self.isPressed ? self.model.animationScale.value : 1,
anchor: .center
)
}
}

// MARK: - Helpers

private struct ViewFrameKey: PreferenceKey {
static var defaultValue: CGRect = .zero

static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}
8 changes: 1 addition & 7 deletions Sources/ComponentsKit/Button/UKButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,7 @@ open class UKButton: UIView, UKComponent {
) {
super.touchesCancelled(touches, with: event)

defer { self.isPressed = false }

if self.model.isEnabled,
let location = touches.first?.location(in: self),
self.bounds.contains(location) {
self.action()
}
self.isPressed = false
}

open override func traitCollectionDidChange(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation

extension DividerVM {
/// Defines the possible orientations for the divider.
public enum DividerOrientation {
public enum Orientation {
case horizontal
case vertical
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/ComponentsKit/Divider/Models/DividerVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ public struct DividerVM: ComponentVM {
/// The orientation of the divider (horizontal or vertical).
///
/// Defaults to `.horizontal`.
public var orientation: DividerOrientation = .horizontal
public var orientation: Orientation = .horizontal

/// The color of the divider.
///
Expand Down
Loading
Loading