From 1dc0bee894800cbbd9c21ffa20d48dda0b31d1a5 Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Thu, 16 Mar 2023 10:42:59 +0530 Subject: [PATCH 1/6] [UPDATE]rebase conflict --- Sources/YStepper/Enums/YStepper+Images.swift | 23 +++++++++++++++++++ Sources/YStepper/Enums/YStepper+Strings.swift | 21 +++++++++++++++++ .../UIKit/StepperControl+Appearance.swift | 1 + 3 files changed, 45 insertions(+) create mode 100644 Sources/YStepper/Enums/YStepper+Images.swift create mode 100644 Sources/YStepper/Enums/YStepper+Strings.swift diff --git a/Sources/YStepper/Enums/YStepper+Images.swift b/Sources/YStepper/Enums/YStepper+Images.swift new file mode 100644 index 0000000..7379dc0 --- /dev/null +++ b/Sources/YStepper/Enums/YStepper+Images.swift @@ -0,0 +1,23 @@ +// +// YStepper+Images.swift +// YStepper +// +// Created by Sahil Saini on 07/03/23. +// Copyright © 2023 Y Media Labs. All rights reserved. +// + +import UIKit +import YCoreUI + +/// Collection of Images +enum Images: String, CaseIterable { + case increment = "plus" + case decrement = "minus" + case delete = "trash" +} + +extension Images: ImageAsset { + func loadImage() -> UIImage? { + UIImage(systemName: rawValue) + } +} diff --git a/Sources/YStepper/Enums/YStepper+Strings.swift b/Sources/YStepper/Enums/YStepper+Strings.swift new file mode 100644 index 0000000..a230f4e --- /dev/null +++ b/Sources/YStepper/Enums/YStepper+Strings.swift @@ -0,0 +1,21 @@ +// +// YStepper+Strings.swift +// YStepper +// +// Created by Sahil Saini on 09/03/23. +// Copyright © 2023 Y Media Labs. All rights reserved. +// + +import Foundation +import YCoreUI + +// extension StepperControl { +// enum Strings: String, Localizable, CaseIterable { +// case incrementA11yButton = "Increment_Button_A11y_label" +// case decrementA11yButton = "Decrement_Button_A11y_label" +// case valueA11yLabel = "Value_A11y_label" +// case stepperButtonA11yHint = "Stepper_Button_A11y_Hint" +// +// static var bundle: Bundle { .module } +// } +// } diff --git a/Sources/YStepper/UIKit/StepperControl+Appearance.swift b/Sources/YStepper/UIKit/StepperControl+Appearance.swift index 036603b..d2359e5 100644 --- a/Sources/YStepper/UIKit/StepperControl+Appearance.swift +++ b/Sources/YStepper/UIKit/StepperControl+Appearance.swift @@ -40,6 +40,7 @@ extension StepperControl { /// - deleteImage: Delete button image. Default is `Appearance.defaultDeleteImage` /// - incrementImage: Increment button image. Default is `Appearance.defaultIncrementImage` /// - decrementImage: Decrement button image. Default is `Appearance.defaultDecrementImage` + /// - hasDeleteButton: Show delete image. Degault is `false` public init( textStyle: (textColor: UIColor, typography: Typography) = (.label, .systemLabel), foregroundColor: UIColor = .label, From c21ca99c0bab82b4f81f6456982ca52a62f4db44 Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Wed, 15 Mar 2023 12:28:55 +0530 Subject: [PATCH 2/6] [UPDATE] typo corrected --- Sources/YStepper/UIKit/StepperControl+Appearance.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/YStepper/UIKit/StepperControl+Appearance.swift b/Sources/YStepper/UIKit/StepperControl+Appearance.swift index d2359e5..036603b 100644 --- a/Sources/YStepper/UIKit/StepperControl+Appearance.swift +++ b/Sources/YStepper/UIKit/StepperControl+Appearance.swift @@ -40,7 +40,6 @@ extension StepperControl { /// - deleteImage: Delete button image. Default is `Appearance.defaultDeleteImage` /// - incrementImage: Increment button image. Default is `Appearance.defaultIncrementImage` /// - decrementImage: Decrement button image. Default is `Appearance.defaultDecrementImage` - /// - hasDeleteButton: Show delete image. Degault is `false` public init( textStyle: (textColor: UIColor, typography: Typography) = (.label, .systemLabel), foregroundColor: UIColor = .label, From c48fe31f0a06b6d2748473f196a1034fcd894187 Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Thu, 16 Mar 2023 10:44:53 +0530 Subject: [PATCH 3/6] [UPDATE] removed extra files [UPDATE] added shapes without stroke, test case updated --- Sources/YStepper/Enums/YStepper+Images.swift | 23 ------- Sources/YStepper/Enums/YStepper+Strings.swift | 21 ------- Sources/YStepper/SwiftUI/Views/Stepper.swift | 44 +++++++++++++- .../UIKit/StepperControl+Appearance.swift | 8 ++- Sources/YStepper/UIKit/YStepper+Shapes.swift | 23 +++++++ Tests/YStepperTests/Views/StepperTests.swift | 60 +++++++++++++++++++ 6 files changed, 131 insertions(+), 48 deletions(-) delete mode 100644 Sources/YStepper/Enums/YStepper+Images.swift delete mode 100644 Sources/YStepper/Enums/YStepper+Strings.swift create mode 100644 Sources/YStepper/UIKit/YStepper+Shapes.swift diff --git a/Sources/YStepper/Enums/YStepper+Images.swift b/Sources/YStepper/Enums/YStepper+Images.swift deleted file mode 100644 index 7379dc0..0000000 --- a/Sources/YStepper/Enums/YStepper+Images.swift +++ /dev/null @@ -1,23 +0,0 @@ -// -// YStepper+Images.swift -// YStepper -// -// Created by Sahil Saini on 07/03/23. -// Copyright © 2023 Y Media Labs. All rights reserved. -// - -import UIKit -import YCoreUI - -/// Collection of Images -enum Images: String, CaseIterable { - case increment = "plus" - case decrement = "minus" - case delete = "trash" -} - -extension Images: ImageAsset { - func loadImage() -> UIImage? { - UIImage(systemName: rawValue) - } -} diff --git a/Sources/YStepper/Enums/YStepper+Strings.swift b/Sources/YStepper/Enums/YStepper+Strings.swift deleted file mode 100644 index a230f4e..0000000 --- a/Sources/YStepper/Enums/YStepper+Strings.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// YStepper+Strings.swift -// YStepper -// -// Created by Sahil Saini on 09/03/23. -// Copyright © 2023 Y Media Labs. All rights reserved. -// - -import Foundation -import YCoreUI - -// extension StepperControl { -// enum Strings: String, Localizable, CaseIterable { -// case incrementA11yButton = "Increment_Button_A11y_label" -// case decrementA11yButton = "Decrement_Button_A11y_label" -// case valueA11yLabel = "Value_A11y_label" -// case stepperButtonA11yHint = "Stepper_Button_A11y_Hint" -// -// static var bundle: Bundle { .module } -// } -// } diff --git a/Sources/YStepper/SwiftUI/Views/Stepper.swift b/Sources/YStepper/SwiftUI/Views/Stepper.swift index a2487a4..eed2835 100644 --- a/Sources/YStepper/SwiftUI/Views/Stepper.swift +++ b/Sources/YStepper/SwiftUI/Views/Stepper.swift @@ -13,6 +13,7 @@ import YMatterType public struct Stepper { @Environment(\.sizeCategory) var sizeCategory let buttonSize: CGSize = CGSize(width: 44, height: 44) + @ObservedObject private var appearanceObserver = Stepper.AppearanceObserver() @ObservedObject private var valueObserver = Stepper.ValueObserver() @@ -96,9 +97,8 @@ extension Stepper: View { } .frame(width: (2 * buttonSize.width) + getStringSize(sizeCategory).width) .background( - Capsule() - .strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) - .background(Capsule().foregroundColor(Color(appearance.backgroundColor))) + getShape() + .background(getShapeWithoutStroke().foregroundColor(Color(appearance.backgroundColor))) ) } @@ -133,6 +133,44 @@ extension Stepper: View { .frame(width: getStringSize(sizeCategory).width) .accessibilityLabel(getAccessibilityLabelText()) } + + @ViewBuilder + func getShape() -> some View { + switch appearance.shape { + case .none: + EmptyView() + case .rectangle: + Rectangle().strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) + case .roundRect(cornerRadius: let cornerRadius): + RoundedRectangle( + cornerSize: CGSize( + width: cornerRadius, + height: cornerRadius + ) + ).strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) + case .capsule: + Capsule().strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) + } + } + + @ViewBuilder + func getShapeWithoutStroke() -> some View { + switch appearance.shape { + case .none: + EmptyView() + case .rectangle: + Rectangle() + case .roundRect(cornerRadius: let cornerRadius): + RoundedRectangle( + cornerSize: CGSize( + width: cornerRadius, + height: cornerRadius + ) + ) + case .capsule: + Capsule() + } + } } extension Stepper { diff --git a/Sources/YStepper/UIKit/StepperControl+Appearance.swift b/Sources/YStepper/UIKit/StepperControl+Appearance.swift index 036603b..1a23d99 100644 --- a/Sources/YStepper/UIKit/StepperControl+Appearance.swift +++ b/Sources/YStepper/UIKit/StepperControl+Appearance.swift @@ -26,6 +26,8 @@ extension StepperControl { public var incrementImage: UIImage /// Decrement button image public var decrementImage: UIImage + /// Stepper's shape + public var shape: Shape /// Whether to show delete button or not. var hasDeleteButton: Bool { deleteImage != nil } @@ -40,6 +42,8 @@ extension StepperControl { /// - deleteImage: Delete button image. Default is `Appearance.defaultDeleteImage` /// - incrementImage: Increment button image. Default is `Appearance.defaultIncrementImage` /// - decrementImage: Decrement button image. Default is `Appearance.defaultDecrementImage` + /// - shape: Stepper's shape. Default is `.capsule` + public init( textStyle: (textColor: UIColor, typography: Typography) = (.label, .systemLabel), foregroundColor: UIColor = .label, @@ -48,7 +52,8 @@ extension StepperControl { borderWidth: CGFloat = 1.0, deleteImage: UIImage? = Appearance.defaultDeleteImage, incrementImage: UIImage = Appearance.defaultIncrementImage, - decrementImage: UIImage = Appearance.defaultDecrementImage + decrementImage: UIImage = Appearance.defaultDecrementImage, + shape: Shape = .capsule ) { self.textStyle = textStyle self.backgroundColor = backgroundColor @@ -57,6 +62,7 @@ extension StepperControl { self.deleteImage = deleteImage self.incrementImage = incrementImage self.decrementImage = decrementImage + self.shape = shape } } } diff --git a/Sources/YStepper/UIKit/YStepper+Shapes.swift b/Sources/YStepper/UIKit/YStepper+Shapes.swift new file mode 100644 index 0000000..b503064 --- /dev/null +++ b/Sources/YStepper/UIKit/YStepper+Shapes.swift @@ -0,0 +1,23 @@ +// +// YStepper+Shapes.swift +// YStepper +// +// Created by Sahil Saini on 15/03/23. +// Copyright © 2023 Y Media Labs. All rights reserved. +// + +import UIKit + +extension StepperControl.Appearance { + /// Stepper's shape. + public enum Shape: Equatable { + /// None + case none + /// Rectangle. + case rectangle + /// Rounded rectangle. + case roundRect(cornerRadius: CGFloat) + /// Capsule. + case capsule + } +} diff --git a/Tests/YStepperTests/Views/StepperTests.swift b/Tests/YStepperTests/Views/StepperTests.swift index 24e1f4b..09b6671 100644 --- a/Tests/YStepperTests/Views/StepperTests.swift +++ b/Tests/YStepperTests/Views/StepperTests.swift @@ -152,6 +152,66 @@ final class StepperTests: XCTestCase { XCTAssertNotNil(button) } + func testShapesNotNill() { + var expectedAppearance = StepperControl.Appearance(shape: .rectangle) + var sut = makeSUT(appearance: expectedAppearance) + let rectShape = sut.getShape() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(rectShape) + + expectedAppearance = StepperControl.Appearance(shape: .roundRect(cornerRadius: 10)) + sut.appearance = expectedAppearance + let roundedRectShape = sut.getShape() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(roundedRectShape) + + expectedAppearance = StepperControl.Appearance(shape: .capsule) + sut.appearance = expectedAppearance + let capsuleShape = sut.getShape() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(capsuleShape) + + expectedAppearance = StepperControl.Appearance(shape: .none) + sut.appearance = expectedAppearance + let emptyView = sut.getShape() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(emptyView) + } + + func testShapesWithoutStrokeNotNill() { + var expectedAppearance = StepperControl.Appearance(shape: .rectangle) + var sut = makeSUT(appearance: expectedAppearance) + let rectShape = sut.getShapeWithoutStroke() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(rectShape) + + expectedAppearance = StepperControl.Appearance(shape: .roundRect(cornerRadius: 10)) + sut.appearance = expectedAppearance + let roundedRectShape = sut.getShapeWithoutStroke() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(roundedRectShape) + + expectedAppearance = StepperControl.Appearance(shape: .capsule) + sut.appearance = expectedAppearance + let capsuleShape = sut.getShapeWithoutStroke() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(capsuleShape) + + expectedAppearance = StepperControl.Appearance(shape: .none) + sut.appearance = expectedAppearance + let emptyView = sut.getShapeWithoutStroke() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(emptyView) + } + func testPreviewNotNil() { XCTAssertNotNil(Stepper_Previews.previews) } From 60abe95931c8610fb1296cae7745f9af7cd6b8aa Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Thu, 16 Mar 2023 13:03:24 +0530 Subject: [PATCH 4/6] [UPDATE] added scaled rounded rect --- Sources/YStepper/SwiftUI/Views/Stepper.swift | 16 +++++++++++++++- Sources/YStepper/UIKit/YStepper+Shapes.swift | 2 ++ Tests/YStepperTests/Views/StepperTests.swift | 20 +++++++++++++++++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Sources/YStepper/SwiftUI/Views/Stepper.swift b/Sources/YStepper/SwiftUI/Views/Stepper.swift index eed2835..a8508f1 100644 --- a/Sources/YStepper/SwiftUI/Views/Stepper.swift +++ b/Sources/YStepper/SwiftUI/Views/Stepper.swift @@ -13,7 +13,7 @@ import YMatterType public struct Stepper { @Environment(\.sizeCategory) var sizeCategory let buttonSize: CGSize = CGSize(width: 44, height: 44) - + @ScaledMetric var scale = 1.0 @ObservedObject private var appearanceObserver = Stepper.AppearanceObserver() @ObservedObject private var valueObserver = Stepper.ValueObserver() @@ -148,6 +148,13 @@ extension Stepper: View { height: cornerRadius ) ).strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) + case .scaledRoundRect(cornerRadius: let cornerRadius): + RoundedRectangle( + cornerSize: CGSize( + width: cornerRadius*scale, + height: cornerRadius*scale + ) + ).strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth*scale) case .capsule: Capsule().strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) } @@ -167,6 +174,13 @@ extension Stepper: View { height: cornerRadius ) ) + case .scaledRoundRect(cornerRadius: let cornerRadius): + RoundedRectangle( + cornerSize: CGSize( + width: cornerRadius*scale, + height: cornerRadius*scale + ) + ) case .capsule: Capsule() } diff --git a/Sources/YStepper/UIKit/YStepper+Shapes.swift b/Sources/YStepper/UIKit/YStepper+Shapes.swift index b503064..bfdb341 100644 --- a/Sources/YStepper/UIKit/YStepper+Shapes.swift +++ b/Sources/YStepper/UIKit/YStepper+Shapes.swift @@ -17,6 +17,8 @@ extension StepperControl.Appearance { case rectangle /// Rounded rectangle. case roundRect(cornerRadius: CGFloat) + /// Rounded rectangle that scales with Dynamic Type. + case scaledRoundRect(cornerRadius: CGFloat) /// Capsule. case capsule } diff --git a/Tests/YStepperTests/Views/StepperTests.swift b/Tests/YStepperTests/Views/StepperTests.swift index 09b6671..171fb44 100644 --- a/Tests/YStepperTests/Views/StepperTests.swift +++ b/Tests/YStepperTests/Views/StepperTests.swift @@ -145,14 +145,14 @@ final class StepperTests: XCTestCase { XCTAssertEqual(sut.value, sut.minimumValue) } - func testBackgroundNotNill() { + func testBackgroundNotNil() { let sut = makeSUT() let button = sut.getDecrementButton() XCTAssertNotNil(button) } - func testShapesNotNill() { + func testShapesNotNil() { var expectedAppearance = StepperControl.Appearance(shape: .rectangle) var sut = makeSUT(appearance: expectedAppearance) let rectShape = sut.getShape() @@ -167,6 +167,13 @@ final class StepperTests: XCTestCase { XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) XCTAssertNotNil(roundedRectShape) + expectedAppearance = StepperControl.Appearance(shape: .scaledRoundRect(cornerRadius: 10)) + sut.appearance = expectedAppearance + let scaledRoundRect = sut.getShape() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(scaledRoundRect) + expectedAppearance = StepperControl.Appearance(shape: .capsule) sut.appearance = expectedAppearance let capsuleShape = sut.getShape() @@ -182,7 +189,7 @@ final class StepperTests: XCTestCase { XCTAssertNotNil(emptyView) } - func testShapesWithoutStrokeNotNill() { + func testShapesWithoutStrokeNotNil() { var expectedAppearance = StepperControl.Appearance(shape: .rectangle) var sut = makeSUT(appearance: expectedAppearance) let rectShape = sut.getShapeWithoutStroke() @@ -197,6 +204,13 @@ final class StepperTests: XCTestCase { XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) XCTAssertNotNil(roundedRectShape) + expectedAppearance = StepperControl.Appearance(shape: .scaledRoundRect(cornerRadius: 10)) + sut.appearance = expectedAppearance + let scaledRoundRect = sut.getShapeWithoutStroke() + + XCTAssertEqual(sut.appearance.shape, expectedAppearance.shape) + XCTAssertNotNil(scaledRoundRect) + expectedAppearance = StepperControl.Appearance(shape: .capsule) sut.appearance = expectedAppearance let capsuleShape = sut.getShapeWithoutStroke() From 358b38f79f838ebc594d0bbc6ede58f3caf7762e Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Thu, 16 Mar 2023 14:00:44 +0530 Subject: [PATCH 5/6] [UPDATE] white space around operator, removed border scaling --- Sources/YStepper/SwiftUI/Views/Stepper.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/YStepper/SwiftUI/Views/Stepper.swift b/Sources/YStepper/SwiftUI/Views/Stepper.swift index a8508f1..5a71d1e 100644 --- a/Sources/YStepper/SwiftUI/Views/Stepper.swift +++ b/Sources/YStepper/SwiftUI/Views/Stepper.swift @@ -151,10 +151,10 @@ extension Stepper: View { case .scaledRoundRect(cornerRadius: let cornerRadius): RoundedRectangle( cornerSize: CGSize( - width: cornerRadius*scale, - height: cornerRadius*scale + width: cornerRadius * scale, + height: cornerRadius * scale ) - ).strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth*scale) + ).strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) case .capsule: Capsule().strokeBorder(Color(appearance.borderColor), lineWidth: appearance.borderWidth) } @@ -177,8 +177,8 @@ extension Stepper: View { case .scaledRoundRect(cornerRadius: let cornerRadius): RoundedRectangle( cornerSize: CGSize( - width: cornerRadius*scale, - height: cornerRadius*scale + width: cornerRadius * scale, + height: cornerRadius * scale ) ) case .capsule: From cd3bef47b27253da593a16fe7ae34bc50c70e097 Mon Sep 17 00:00:00 2001 From: Sahil Saini Date: Thu, 16 Mar 2023 16:27:01 +0530 Subject: [PATCH 6/6] [UPDATE] removed foreground from images and added text color --- Sources/YStepper/SwiftUI/Views/Stepper.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Sources/YStepper/SwiftUI/Views/Stepper.swift b/Sources/YStepper/SwiftUI/Views/Stepper.swift index 5a71d1e..74be2aa 100644 --- a/Sources/YStepper/SwiftUI/Views/Stepper.swift +++ b/Sources/YStepper/SwiftUI/Views/Stepper.swift @@ -105,7 +105,7 @@ extension Stepper: View { @ViewBuilder func getIncrementButton() -> some View { Button { buttonAction(buttonType: .increment) } label: { - getIncrementImage().renderingMode(.template).foregroundColor(Color(appearance.textStyle.textColor)) + getIncrementImage().renderingMode(.template) } .frame(width: buttonSize.width, height: buttonSize.height) .accessibilityLabel(StepperControl.Strings.incrementA11yButton.localized) @@ -114,9 +114,7 @@ extension Stepper: View { @ViewBuilder func getDecrementButton() -> some View { Button { buttonAction(buttonType: .decrement) } label: { - getImageForDecrementButton()?.renderingMode(.template).foregroundColor( - Color(appearance.textStyle.textColor) - ) + getImageForDecrementButton()?.renderingMode(.template) } .frame(width: buttonSize.width, height: buttonSize.height) .accessibilityLabel(getAccessibilityText()) @@ -129,6 +127,7 @@ extension Stepper: View { ) { label in label.textAlignment = .center label.numberOfLines = 1 + label.textColor = appearance.textStyle.textColor } .frame(width: getStringSize(sizeCategory).width) .accessibilityLabel(getAccessibilityLabelText())