added TextField

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2024-03-13 13:40:37 -05:00
parent 413d5567af
commit bd50e75f85
3 changed files with 258 additions and 4 deletions

View File

@ -132,6 +132,7 @@
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD068912A560B65002E3A2D /* LoaderViewController.swift */; };
EAD068942A560C13002E3A2D /* LoaderLaunchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD068932A560C13002E3A2D /* LoaderLaunchable.swift */; };
EAD8D2C128BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */; };
EAE785352BA22825009428EA /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAE785342BA22825009428EA /* TextField.swift */; };
EAEEEC922B1F807300531FC2 /* BadgeChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = EAEEEC912B1F807300531FC2 /* BadgeChangeLog.txt */; };
EAEEEC962B1F893B00531FC2 /* ButtonChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = EAEEEC952B1F893B00531FC2 /* ButtonChangeLog.txt */; };
EAEEEC982B1F8DD100531FC2 /* LineChangeLog.txt in Resources */ = {isa = PBXBuildFile; fileRef = EAEEEC972B1F8DD100531FC2 /* LineChangeLog.txt */; };
@ -303,6 +304,7 @@
EAD068912A560B65002E3A2D /* LoaderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoaderViewController.swift; sourceTree = "<group>"; };
EAD068932A560C13002E3A2D /* LoaderLaunchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoaderLaunchable.swift; sourceTree = "<group>"; };
EAD8D2C028BFDE8B006EB6A6 /* UIGestureRecognizer+Publisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+Publisher.swift"; sourceTree = "<group>"; };
EAE785342BA22825009428EA /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
EAEEEC912B1F807300531FC2 /* BadgeChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = BadgeChangeLog.txt; sourceTree = "<group>"; };
EAEEEC952B1F893B00531FC2 /* ButtonChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = ButtonChangeLog.txt; sourceTree = "<group>"; };
EAEEEC972B1F8DD100531FC2 /* LineChangeLog.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = LineChangeLog.txt; sourceTree = "<group>"; };
@ -800,6 +802,7 @@
isa = PBXGroup;
children = (
EAC925872911C9DE00091998 /* InputField.swift */,
EAE785342BA22825009428EA /* TextField.swift */,
);
path = InputField;
sourceTree = "<group>";
@ -1053,6 +1056,7 @@
EAD068922A560B65002E3A2D /* LoaderViewController.swift in Sources */,
EABFEB642A26473700C4C106 /* NSAttributedString.swift in Sources */,
EAF7F13328A2A16500B287F5 /* AttachmentLabelAttributeModel.swift in Sources */,
EAE785352BA22825009428EA /* TextField.swift in Sources */,
EA0FC2C62914222900DF80B4 /* ButtonGroup.swift in Sources */,
EA89200628B526D6006B9984 /* CheckboxGroup.swift in Sources */,
EA8E40932A82889500934ED3 /* TooltipDialog.swift in Sources */,

View File

@ -64,10 +64,7 @@ open class InputField: EntryFieldBase, UITextFieldDelegate {
}
/// UITextField shown in the InputField.
open var textField = UITextField().with {
$0.translatesAutoresizingMaskIntoConstraints = false
$0.font = TextStyle.bodyLarge.font
}
open var textField = TextField()
/// Color configuration for the textField.
open var textFieldTextColorConfiguration: AnyColorable = ViewColorConfiguration().with {

View File

@ -0,0 +1,253 @@
//
// TextField.swift
// VDS
//
// Created by Matt Bruce on 3/13/24.
//
import Foundation
import UIKit
import Combine
import VDSColorTokens
@objc(VDSTextField)
open class TextField: UITextField, ViewProtocol {
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init() {
super.init(frame: .zero)
initialSetup()
}
public override init(frame: CGRect) {
super.init(frame: frame)
initialSetup()
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
initialSetup()
}
//--------------------------------------------------
// MARK: - Combine Properties
//--------------------------------------------------
/// Set of Subscribers for any Publishers for this Control.
open var subscribers = Set<AnyCancellable>()
//--------------------------------------------------
// MARK: - Private Properties
//--------------------------------------------------
private var initialSetupPerformed = false
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
/// Key of whether or not updateView() is called in setNeedsUpdate()
open var shouldUpdateView: Bool = true
open var surface: Surface = .light { didSet { setNeedsUpdate() } }
/// Array of LabelAttributeModel objects used in rendering the text.
open var textAttributes: [any LabelAttributeModel]? { didSet { setNeedsUpdate() } }
/// TextStyle used on the titleLabel.
open var textStyle: TextStyle { .defaultStyle }
/// Will determine if a scaled font should be used for the titleLabel font.
open var useScaledFont: Bool = false { didSet { setNeedsUpdate() } }
open override var isEnabled: Bool { didSet { setNeedsUpdate() } }
open override var isSelected: Bool { didSet { setNeedsUpdate() } }
/// State of animating isHighlight.
public var isHighlighting = false
/// Whether the Control should handle the isHighlighted state.
open var shouldHighlight: Bool { isHighlighting == false }
/// Whether the Control is highlighted or not.
open override var isHighlighted: Bool {
didSet {
if shouldHighlight {
isHighlighting = true
setNeedsUpdate()
isHighlighting = false
}
}
}
open var textColorConfiguration: AnyColorable = ViewColorConfiguration().with {
$0.setSurfaceColors(VDSColor.interactiveDisabledOnlight, VDSColor.interactiveDisabledOndark, forDisabled: true)
$0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forDisabled: false)
}.eraseToAnyColorable(){ didSet { setNeedsUpdate() }}
open override var textColor: UIColor? {
get { textColorConfiguration.getColor(self) }
set { }
}
private enum TextSetMode {
case text
case attributedText
}
private var textSetMode: TextSetMode = .text
/// :nodoc:
open override var text: String! {
get { super.text }
set {
// When text is set, we may need to re-style it as attributedText
// with the correct paragraph style to achieve the desired line height.
textSetMode = .text
styleText(newValue)
}
}
/// :nodoc:
open override var attributedText: NSAttributedString? {
get { super.attributedText }
set {
// When text is set, we may need to re-style it as attributedText
// with the correct paragraph style to achieve the desired line height.
textSetMode = .attributedText
styleAttributedText(newValue)
}
}
/// :nodoc:
open override var textAlignment: NSTextAlignment {
didSet {
if textAlignment != oldValue {
// Text alignment can be part of our paragraph style, so we may need to
// re-style when changed
restyleText()
}
}
}
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
open func initialSetup() {
if !initialSetupPerformed {
initialSetupPerformed = true
backgroundColor = .clear
translatesAutoresizingMaskIntoConstraints = false
accessibilityCustomActions = []
setup()
setNeedsUpdate()
}
}
open func setup() {
translatesAutoresizingMaskIntoConstraints = false
}
open func updateView() {
restyleText()
}
open func updateAccessibility() {}
open func reset() {
shouldUpdateView = false
surface = .light
text = nil
accessibilityCustomActions = []
shouldUpdateView = true
setNeedsUpdate()
}
//--------------------------------------------------
// MARK: - Overrides Methods
//--------------------------------------------------
/// :nodoc
open override func textRect(forBounds bounds: CGRect) -> CGRect {
super.textRect(forBounds: bounds).inset(by: textStyle.edgeInsets)
}
/// :nodoc
open override func editingRect(forBounds bounds: CGRect) -> CGRect {
super.editingRect(forBounds: bounds).inset(by: textStyle.edgeInsets)
}
/// :nodoc
open override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
super.clearButtonRect(forBounds: bounds).offsetBy(dx: -textStyle.edgeInsets.right, dy: 0)
}
/// :nodoc
open override func leftViewRect(forBounds bounds: CGRect) -> CGRect {
super.leftViewRect(forBounds: bounds).offsetBy(dx: textStyle.edgeInsets.left, dy: 0)
}
/// :nodoc
open override func rightViewRect(forBounds bounds: CGRect) -> CGRect {
super.rightViewRect(forBounds: bounds).offsetBy(dx: -textStyle.edgeInsets.right, dy: 0)
}
//--------------------------------------------------
// MARK: - Private Methods
//--------------------------------------------------
private func restyleText() {
if textSetMode == .text {
styleText(text)
} else {
styleAttributedText(attributedText)
}
}
private func styleText(_ newValue: String!) {
defer { invalidateIntrinsicContentSize() }
guard let newValue else {
// We don't need to use attributed text
super.attributedText = nil
super.text = newValue
return
}
accessibilityCustomActions = []
//create the primary string
let mutableText = NSMutableAttributedString.mutableText(for: newValue,
textStyle: textStyle,
useScaledFont: useScaledFont,
textColor: textColorConfiguration.getColor(self),
alignment: textAlignment,
lineBreakMode: .byWordWrapping)
applyAttributes(mutableText)
// Set attributed text to match typography
super.attributedText = mutableText
}
private func styleAttributedText(_ newValue: NSAttributedString?) {
defer { invalidateIntrinsicContentSize() }
guard let newValue = newValue else {
// We don't need any additional styling
super.attributedText = newValue
return
}
let mutableText = NSMutableAttributedString(attributedString: newValue)
applyAttributes(mutableText)
// Modify attributed text to match typography
super.attributedText = mutableText
}
private func applyAttributes(_ mutableAttributedString: NSMutableAttributedString) {
if let textAttributes {
mutableAttributedString.apply(attributes: textAttributes)
}
}
}