-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(POM-398): support saving card during tokenization (#318)
* Conditionally display save card checkbox during card tokenization. * Expose savingAllowed within dynamic checkout API bindings. * Add checkbox toggle style. * Use monospaced numbers for list markers and dynamic checkout's express payments. * Remove unused UIKit extensions. * Interactively dismiss keyboard during DC.
- Loading branch information
1 parent
b232a2d
commit 9a341ed
Showing
37 changed files
with
679 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
Sources/ProcessOutCoreUI/Sources/Core/Shapes/ConstrainedRectangle/ConstrainedRectangle.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// ConstrainedRectangle.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
import SwiftUI | ||
|
||
/// A rectangular shape that automatically adjusts its size and position to | ||
/// satisfy minimum size requirement. | ||
struct ConstrainedRectangle: Shape { | ||
|
||
let minSize: CGSize | ||
|
||
// MARK: - Shape | ||
|
||
func path(in rect: CGRect) -> Path { | ||
let adjustedRect = rect.insetBy( | ||
dx: min(rect.width - minSize.width, 0) / 2, dy: min(rect.height - minSize.height, 0) / 2 | ||
) | ||
return Path(roundedRect: adjustedRect, cornerSize: .zero) | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
...rocessOutCoreUI/Sources/Core/Shapes/ConstrainedRectangle/Shape+ConstrainedRectangle.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// Shape+ConstrainedRectangle.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
import SwiftUI | ||
|
||
extension Shape where Self == ConstrainedRectangle { | ||
|
||
/// A rectangle shape with a minimum size of 44x44 points, ensuring it meets the standard | ||
/// clickable area requirements according to Human Interface Guidelines (HIG). | ||
static var standardHittableRect: ConstrainedRectangle { | ||
ConstrainedRectangle(minSize: CGSize(width: 44, height: 44)) | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
...rocessOutCoreUI/Sources/Core/UIKit+Extensions/UIFont+FontFeatures/FontNumberSpacing.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// FontNumberSpacing.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
import CoreText | ||
|
||
@_spi(PO) | ||
public struct POFontNumberSpacing { | ||
|
||
let rawValue: Int | ||
} | ||
|
||
extension POFontNumberSpacing { | ||
|
||
/// Uniform width numbers, useful for displaying in columns. | ||
public static let monospaced = Self(rawValue: kMonospacedNumbersSelector) | ||
|
||
/// Numbers whose widths vary. | ||
public static let proportional = Self(rawValue: kProportionalNumbersSelector) | ||
|
||
/// Thin numerals. | ||
public static let thirdWidth = Self(rawValue: kThirdWidthNumbersSelector) | ||
|
||
/// Very thin numerals. | ||
public static let quarterWidth = Self(rawValue: kQuarterWidthNumbersSelector) | ||
} | ||
|
||
extension POFontNumberSpacing: FontFeatureSetting { | ||
|
||
var featureType: Int { | ||
kNumberSpacingType | ||
} | ||
|
||
var featureSelector: Any { | ||
rawValue | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...essOutCoreUI/Sources/Core/UIKit+Extensions/UIFont+FontFeatures/POFontFeatureSetting.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// | ||
// FontFeatureSetting.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
protocol FontFeatureSetting { | ||
|
||
/// Indicates a general class of effect (e.g., ligatures). | ||
var featureType: Int { get } | ||
|
||
/// Indicates the specific effect (e.g., rare ligature). | ||
var featureSelector: Any { get } | ||
} |
13 changes: 13 additions & 0 deletions
13
...sOutCoreUI/Sources/Core/UIKit+Extensions/UIFont+FontFeatures/POFontFeaturesSettings.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// POFontFeaturesSettings.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
@_spi(PO) | ||
public struct POFontFeaturesSettings { | ||
|
||
/// The number spacing feature type specifies a choice for the appearance of digits. | ||
public var numberSpacing: POFontNumberSpacing = .proportional | ||
} |
24 changes: 24 additions & 0 deletions
24
...oreUI/Sources/Core/UIKit+Extensions/UIFont+FontFeatures/UIFont+FontFeaturesSettings.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// | ||
// UIFont+FontFeaturesSettings.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 30.07.2024. | ||
// | ||
|
||
import UIKit | ||
|
||
extension UIFont { | ||
|
||
func addingFeatures(_ settings: POFontFeaturesSettings) -> UIFont { | ||
let settings = [ | ||
settings.numberSpacing | ||
] | ||
let rawSettings = settings.map { setting -> [UIFontDescriptor.FeatureKey: Any] in | ||
[.featureIdentifier: setting.featureType, .typeIdentifier: setting.featureSelector] | ||
} | ||
let newDescriptor = fontDescriptor.addingAttributes( | ||
[.featureSettings: rawSettings] | ||
) | ||
return UIFont(descriptor: newDescriptor, size: 0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
Sources/ProcessOutCoreUI/Sources/DesignSystem/Checkbox/CheckboxButtonStyle.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// | ||
// CheckboxButtonStyle.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 29.07.2024. | ||
// | ||
|
||
import SwiftUI | ||
|
||
@available(iOS 14.0, *) | ||
struct CheckboxButtonStyle: ButtonStyle { | ||
|
||
/// Defines whether checkbox is selected. | ||
let isSelected: Bool | ||
|
||
/// Toggle style. | ||
let style: POCheckboxToggleStyle | ||
|
||
// MARK: - ButtonStyle | ||
|
||
func makeBody(configuration: Configuration) -> some View { | ||
ContentView { isInvalid, isEnabled, colorScheme in | ||
let style = resolveStyle(isInvalid: isInvalid, isEnabled: isEnabled) | ||
Label( | ||
title: { | ||
configuration.label | ||
.textStyle(style.value) | ||
.frame(maxWidth: .infinity, alignment: .leading) | ||
}, | ||
icon: { | ||
CheckboxView(isSelected: isSelected, style: style.checkmark) | ||
} | ||
) | ||
.brightness( | ||
brightnessAdjustment(isPressed: configuration.isPressed, colorScheme: colorScheme) | ||
) | ||
.contentShape(.standardHittableRect) | ||
.animation(.default, value: isSelected) | ||
.animation(.default, value: isEnabled) | ||
} | ||
.backport.geometryGroup() | ||
} | ||
|
||
// MARK: - Private Methods | ||
|
||
private func resolveStyle(isInvalid: Bool, isEnabled: Bool) -> POCheckboxToggleStateStyle { | ||
if !isEnabled { | ||
return style.disabled | ||
} | ||
if isInvalid { | ||
return style.error | ||
} | ||
if isSelected { | ||
return style.selected | ||
} | ||
return style.normal | ||
} | ||
|
||
// MARK: - Private Methods | ||
|
||
private func brightnessAdjustment(isPressed: Bool, colorScheme: ColorScheme) -> Double { | ||
guard isPressed else { | ||
return 0 | ||
} | ||
return colorScheme == .dark ? -0.08 : 0.15 // Darken if color is light or brighten otherwise | ||
} | ||
} | ||
|
||
// Environments are not propagated directly to ButtonStyle in any iOS before 14. | ||
private struct ContentView<Content: View>: View { | ||
|
||
@ViewBuilder | ||
let content: (_ isInvalid: Bool, _ isEnabled: Bool, _ colorScheme: ColorScheme) -> Content | ||
|
||
var body: some View { | ||
content(isInvalid, isEnabled, colorScheme) | ||
} | ||
|
||
// MARK: - Private Properties | ||
|
||
@Environment(\.isControlInvalid) | ||
private var isInvalid | ||
|
||
@Environment(\.isEnabled) | ||
private var isEnabled | ||
|
||
@Environment(\.colorScheme) | ||
private var colorScheme | ||
} |
39 changes: 39 additions & 0 deletions
39
Sources/ProcessOutCoreUI/Sources/DesignSystem/Checkbox/CheckboxView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// | ||
// CheckboxView.swift | ||
// ProcessOutCoreUI | ||
// | ||
// Created by Andrii Vysotskyi on 29.07.2024. | ||
// | ||
|
||
import SwiftUI | ||
|
||
struct CheckboxView: View { | ||
|
||
/// Determines whether the checkbox is selected or not. | ||
let isSelected: Bool | ||
|
||
/// Resolved style. | ||
let style: POCheckboxToggleStateStyle.Checkmark | ||
|
||
// MARK: - View | ||
|
||
var body: some View { | ||
CheckmarkShape() | ||
.trim(from: 0, to: isSelected ? 1.0 : 0) | ||
.stroke( | ||
style.color, | ||
style: StrokeStyle(lineWidth: style.width, lineCap: .round, lineJoin: .round) | ||
) | ||
.frame(width: Constants.checkmarkSize, height: Constants.checkmarkSize) | ||
.frame(width: Constants.size, height: Constants.size) | ||
.background(style.backgroundColor) | ||
.border(style: style.border) | ||
} | ||
|
||
// MARK: - Private Nested Types | ||
|
||
private enum Constants { | ||
static let size: CGFloat = 22 | ||
static let checkmarkSize = Constants.size * 0.75 | ||
} | ||
} |
Oops, something went wrong.