Merge branch 'develop' into bugfix/PRODDEF-1289_accessibilityChanges
This commit is contained in:
commit
733a0a1b94
@ -296,6 +296,8 @@
|
||||
AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */; };
|
||||
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
|
||||
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; };
|
||||
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBE29DF34730005D28B /* BadgeModel.swift */; };
|
||||
B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4CC8FBC29DF34680005D28B /* Badge.swift */; };
|
||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
|
||||
BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; };
|
||||
@ -572,8 +574,8 @@
|
||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
||||
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
|
||||
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; };
|
||||
EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; };
|
||||
EA985C402970939A00F2FF2E /* TileletModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3F2970939A00F2FF2E /* TileletModel.swift */; };
|
||||
EA985C3E2970938F00F2FF2E /* Tilelet.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C3D2970938F00F2FF2E /* Tilelet.swift */; };
|
||||
EA985C602970A3F000F2FF2E /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C5F2970A3F000F2FF2E /* VDS.framework */; };
|
||||
EA985C642970A40E00F2FF2E /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA985C632970A40E00F2FF2E /* VDSTypographyTokens.xcframework */; };
|
||||
EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA985C842981AA9C00F2FF2E /* VDS-Enums+Codable.swift */; };
|
||||
@ -884,6 +886,8 @@
|
||||
AFA4935629EE3DCC001A9663 /* AlertDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertDelegateProtocol.swift; sourceTree = "<group>"; };
|
||||
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
|
||||
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
|
||||
B4CC8FBE29DF34730005D28B /* BadgeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeModel.swift; sourceTree = "<group>"; };
|
||||
B4CC8FBC29DF34680005D28B /* Badge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Badge.swift; sourceTree = "<group>"; };
|
||||
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; };
|
||||
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
|
||||
BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = "<group>"; };
|
||||
@ -2220,8 +2224,10 @@
|
||||
AA37CBD42519072F0027344C /* Stars.swift */,
|
||||
AA07EA902510A442009A2AE3 /* StarModel.swift */,
|
||||
AA07EA922510A451009A2AE3 /* Star.swift */,
|
||||
EA985C3D2970938F00F2FF2E /* Tilelet.swift */,
|
||||
B4CC8FBE29DF34730005D28B /* BadgeModel.swift */,
|
||||
B4CC8FBC29DF34680005D28B /* Badge.swift */,
|
||||
EA985C3F2970939A00F2FF2E /* TileletModel.swift */,
|
||||
EA985C3D2970938F00F2FF2E /* Tilelet.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
@ -2923,6 +2929,7 @@
|
||||
27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */,
|
||||
D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */,
|
||||
526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */,
|
||||
B4CC8FBD29DF34680005D28B /* Badge.swift in Sources */,
|
||||
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */,
|
||||
3265B30224BCA737000D154B /* HeadersH1NoButtonsBodyTextModel.swift in Sources */,
|
||||
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
|
||||
@ -3031,6 +3038,7 @@
|
||||
22B678F929E7944E00CF4196 /* GetNotificationAuthStatusBehavior.swift in Sources */,
|
||||
BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */,
|
||||
012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */,
|
||||
B4CC8FBF29DF34730005D28B /* BadgeModel.swift in Sources */,
|
||||
94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */,
|
||||
EA985C852981AA9C00F2FF2E /* VDS-Enums+Codable.swift in Sources */,
|
||||
AAB8549824DC01BD00477C40 /* ListThreeColumnBillHistoryDividerModel.swift in Sources */,
|
||||
|
||||
@ -27,54 +27,12 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
public var action: ActionModelProtocol
|
||||
public var enabled: Bool = true
|
||||
public var width: CGFloat?
|
||||
public var style: Use? {
|
||||
didSet {
|
||||
guard let style = style else { return }
|
||||
setFacade(by: style)
|
||||
}
|
||||
}
|
||||
public var style: Use = .primary
|
||||
public var size: VDS.Button.Size = .large
|
||||
public var groupName: String = ""
|
||||
public var inverted: Bool = false
|
||||
|
||||
public lazy var enabledColors: FacadeElements = (fill: enabled_fillColor(),
|
||||
text: enabled_textColor(),
|
||||
border: enabled_borderColor())
|
||||
|
||||
public lazy var disabledColors: FacadeElements = (fill: disabled_fillColor(),
|
||||
text: disabled_textColor(),
|
||||
border: disabled_borderColor())
|
||||
|
||||
public var enabledFillColor: Color?
|
||||
public var enabledTextColor: Color?
|
||||
public var enabledBorderColor: Color?
|
||||
|
||||
public var enabledFillColor_inverted: Color?
|
||||
public var enabledTextColor_inverted: Color?
|
||||
public var enabledBorderColor_inverted: Color?
|
||||
|
||||
public var disabledFillColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
public var disabledBorderColor: Color?
|
||||
|
||||
public var disabledFillColor_inverted: Color?
|
||||
public var disabledTextColor_inverted: Color?
|
||||
public var disabledBorderColor_inverted: Color?
|
||||
|
||||
private var _backgroundColor: Color?
|
||||
public var backgroundColor: Color? {
|
||||
get {
|
||||
if let backgroundColor = _backgroundColor { return backgroundColor }
|
||||
if inverted {
|
||||
return enabled ? enabledFillColor_inverted : disabledFillColor_inverted
|
||||
}
|
||||
return enabled ? enabledFillColor : disabledFillColor
|
||||
}
|
||||
set {
|
||||
_backgroundColor = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var backgroundColor: Color?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
@ -88,88 +46,18 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
public init(with title: String, action: ActionModelProtocol) {
|
||||
self.title = title
|
||||
self.action = action
|
||||
setFacade(by: .primary)
|
||||
}
|
||||
|
||||
public init(secondaryButtonWith title: String, action: ActionModelProtocol) {
|
||||
self.title = title
|
||||
self.action = action
|
||||
style = .secondary
|
||||
setFacade(by: .secondary)
|
||||
}
|
||||
|
||||
public init(primaryButtonWith title: String, action: ActionModelProtocol) {
|
||||
self.title = title
|
||||
self.action = action
|
||||
style = .primary
|
||||
setFacade(by: .primary)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func enabled_fillColor() -> UIColor? {
|
||||
(inverted ? enabledFillColor_inverted : enabledFillColor)?.uiColor
|
||||
}
|
||||
|
||||
public func enabled_textColor() -> UIColor? {
|
||||
(inverted ? enabledTextColor_inverted : enabledTextColor)?.uiColor
|
||||
}
|
||||
|
||||
public func enabled_borderColor() -> UIColor? {
|
||||
(inverted ? enabledBorderColor_inverted : enabledBorderColor)?.uiColor
|
||||
}
|
||||
|
||||
public func disabled_fillColor() -> UIColor? {
|
||||
(inverted ? disabledFillColor_inverted : disabledFillColor)?.uiColor
|
||||
}
|
||||
|
||||
public func disabled_textColor() -> UIColor? {
|
||||
(inverted ? disabledTextColor_inverted : disabledTextColor)?.uiColor
|
||||
}
|
||||
|
||||
public func disabled_borderColor() -> UIColor? {
|
||||
(inverted ? disabledBorderColor_inverted : disabledBorderColor)?.uiColor
|
||||
}
|
||||
|
||||
/// Defines the default appearance for the primary style.
|
||||
func setPrimaryFacade() {
|
||||
enabledFillColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
disabledFillColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
|
||||
disabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
|
||||
enabledFillColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
disabledFillColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
|
||||
disabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
}
|
||||
|
||||
/// Defines the default appearance for the Secondary style.
|
||||
func setSecondaryFacade() {
|
||||
enabledTextColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
enabledFillColor = Color(uiColor: UIColor.clear)
|
||||
enabledBorderColor = Color(uiColor: VDSColor.elementsPrimaryOnlight)
|
||||
disabledTextColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
|
||||
disabledBorderColor = Color(uiColor: VDSColor.interactiveDisabledOnlight)
|
||||
|
||||
enabledTextColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
enabledFillColor_inverted = Color(uiColor: UIColor.clear)
|
||||
enabledBorderColor_inverted = Color(uiColor: VDSColor.elementsPrimaryOndark)
|
||||
disabledTextColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
|
||||
disabledBorderColor_inverted = Color(uiColor: VDSColor.interactiveDisabledOndark)
|
||||
}
|
||||
|
||||
public func setFacade(by style: VDS.Use) {
|
||||
switch style {
|
||||
case .primary:
|
||||
setPrimaryFacade()
|
||||
case .secondary:
|
||||
setSecondaryFacade()
|
||||
@unknown default:
|
||||
setPrimaryFacade()
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -179,7 +67,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case accessibilityIdentifier
|
||||
case accessibilityText
|
||||
case title
|
||||
@ -189,12 +76,6 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
case style
|
||||
case size
|
||||
case groupName
|
||||
case fillColor
|
||||
case textColor
|
||||
case borderColor
|
||||
case disabledFillColor
|
||||
case disabledTextColor
|
||||
case disabledBorderColor
|
||||
case width
|
||||
}
|
||||
|
||||
@ -214,12 +95,8 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
///Style captured from the JSON
|
||||
if let style = try typeContainer.decodeIfPresent(Use.self, forKey: .style) {
|
||||
self.style = style
|
||||
setFacade(by: style)
|
||||
} else if let style = decoder.context?.value(forKey: CodingKeys.style.stringValue) as? Use { ///Reading the style param from context which is set is molecules, ex: TwoButtonView
|
||||
self.style = style
|
||||
setFacade(by: style)
|
||||
} else { ///Default style
|
||||
setFacade(by: .primary)
|
||||
}
|
||||
|
||||
if let size = try typeContainer.decodeIfPresent(VDS.Button.Size.self, forKey: .size) {
|
||||
@ -230,40 +107,57 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
self.enabled = enabled
|
||||
}
|
||||
|
||||
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
|
||||
self.inverted = inverted
|
||||
}
|
||||
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
|
||||
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||
|
||||
if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) {
|
||||
self.inverted = inverted
|
||||
} else {
|
||||
try setInverted(deprecatedFrom: decoder)
|
||||
}
|
||||
}
|
||||
|
||||
private enum DeprecatedCodingKeys: String, CodingKey {
|
||||
case fillColor
|
||||
case textColor
|
||||
case borderColor
|
||||
case backgroundColor
|
||||
}
|
||||
|
||||
private func setInverted(deprecatedFrom decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: DeprecatedCodingKeys.self)
|
||||
if let enabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .fillColor) {
|
||||
self.enabledFillColor = enabledFillColor
|
||||
if (self.style == .secondary) {
|
||||
self.inverted = enabledFillColor.uiColor.isDark()
|
||||
} else {
|
||||
self.inverted = !enabledFillColor.uiColor.isDark()
|
||||
}
|
||||
}
|
||||
|
||||
if let enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .textColor) {
|
||||
self.enabledTextColor = enabledTextColor
|
||||
if (self.style == .secondary) {
|
||||
self.inverted = !enabledTextColor.uiColor.isDark()
|
||||
} else {
|
||||
self.inverted = enabledTextColor.uiColor.isDark()
|
||||
}
|
||||
}
|
||||
|
||||
if let enabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) {
|
||||
self.enabledBorderColor = enabledBorderColor
|
||||
if (self.style == .secondary) {
|
||||
self.inverted = !enabledBorderColor.uiColor.isDark()
|
||||
}
|
||||
}
|
||||
|
||||
if let disabledFillColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledFillColor) {
|
||||
self.disabledFillColor = disabledFillColor
|
||||
|
||||
if let backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
||||
if (self.style == .secondary) {
|
||||
self.inverted = backgroundColor.uiColor.isDark()
|
||||
} else {
|
||||
self.inverted = !backgroundColor.uiColor.isDark()
|
||||
}
|
||||
}
|
||||
|
||||
if let disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor) {
|
||||
self.disabledTextColor = disabledTextColor
|
||||
}
|
||||
|
||||
if let disabledBorderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledBorderColor) {
|
||||
self.disabledBorderColor = disabledBorderColor
|
||||
}
|
||||
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
width = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .width)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
@ -274,17 +168,10 @@ open class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWat
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encode(inverted, forKey: .inverted)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor)
|
||||
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encodeIfPresent(enabledFillColor, forKey: .fillColor)
|
||||
try container.encodeIfPresent(enabledTextColor, forKey: .textColor)
|
||||
try container.encodeIfPresent(enabledBorderColor, forKey: .borderColor)
|
||||
try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor)
|
||||
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
|
||||
try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor)
|
||||
try container.encodeIfPresent(style, forKey: .style)
|
||||
try container.encodeIfPresent(size, forKey: .size)
|
||||
try container.encode(style, forKey: .style)
|
||||
try container.encode(size, forKey: .size)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
try container.encodeIfPresent(width, forKey: .width)
|
||||
}
|
||||
|
||||
60
MVMCoreUI/Atomic/Atoms/Views/Badge.swift
Normal file
60
MVMCoreUI/Atomic/Atoms/Views/Badge.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// Badge.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Rebecca Antonelli on 4/6/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
import VDS
|
||||
import Combine
|
||||
|
||||
open class Badge: VDS.Badge, VDSMoleculeViewProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Properties
|
||||
//--------------------------------------------------
|
||||
public var viewModel: BadgeModel!
|
||||
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
public var additionalData: [AnyHashable : Any]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Public Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
public func viewModelDidUpdate() {
|
||||
text = viewModel.text
|
||||
maxWidth = viewModel.maxWidth
|
||||
numberOfLines = viewModel.numberOfLines
|
||||
fillColor = viewModel.fillColor
|
||||
surface = viewModel.surface
|
||||
}
|
||||
|
||||
public func updateView(_ size: CGFloat) {}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Overrides
|
||||
//--------------------------------------------------
|
||||
open override func updateAccessibility() {
|
||||
super.updateAccessibility()
|
||||
|
||||
if let viewModel {
|
||||
if let accessibilityText = viewModel.accessibilityText {
|
||||
self.accessibilityLabel = accessibilityText
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//to deal with how it's parent constrains this control
|
||||
extension Badge: MVMCoreUIViewConstrainingProtocol {
|
||||
|
||||
public func needsToBeConstrained() -> Bool { true }
|
||||
|
||||
public func horizontalAlignment() -> UIStackView.Alignment { .leading }
|
||||
}
|
||||
56
MVMCoreUI/Atomic/Atoms/Views/BadgeModel.swift
Normal file
56
MVMCoreUI/Atomic/Atoms/Views/BadgeModel.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// BadgeModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Rebecca Antonelli on 4/6/23.
|
||||
// Copyright © 2023 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import VDS
|
||||
|
||||
open class BadgeModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "badge"
|
||||
public var id: String = UUID().uuidString
|
||||
public var backgroundColor: Color?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - VDS Properties
|
||||
//--------------------------------------------------
|
||||
public var text: String = ""
|
||||
public var accessibilityText: String?
|
||||
public var maxWidth: CGFloat?
|
||||
public var numberOfLines: Int = 1
|
||||
public var fillColor = Badge.FillColor.red
|
||||
public var surface: Surface = .light
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id, text, accessibilityText, fillColor, surface, numberOfLines, maxWidth
|
||||
}
|
||||
|
||||
required public convenience init(from decoder: Decoder) throws {
|
||||
self.init()
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString
|
||||
text = try container.decode(String.self, forKey: .text)
|
||||
accessibilityText = try container.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||
fillColor = try container.decodeIfPresent(Badge.FillColor.self, forKey: .fillColor) ?? .red
|
||||
surface = try container.decodeIfPresent(Surface.self, forKey: .surface) ?? .light
|
||||
numberOfLines = try container.decodeIfPresent(Int.self, forKey: .numberOfLines) ?? 1
|
||||
maxWidth = try container.decodeIfPresent(CGFloat.self, forKey: .maxWidth)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(text, forKey: .text)
|
||||
try container.encode(accessibilityText, forKey: .accessibilityText)
|
||||
try container.encode(fillColor, forKey: .fillColor)
|
||||
try container.encode(surface, forKey: .surface)
|
||||
try container.encode(numberOfLines, forKey: .numberOfLines)
|
||||
try container.encodeIfPresent(maxWidth, forKey: .maxWidth)
|
||||
}
|
||||
}
|
||||
@ -213,7 +213,9 @@ open class BarsIndicatorView: CarouselIndicator {
|
||||
let accessibleIndex = MVMCoreUIUtility.getOrdinalString(forIndex: NSNumber(value: index + 1))
|
||||
else { return }
|
||||
|
||||
view.accessibilityLabel = String(format: accessibleValueFormat, accessibleIndex, numberOfPages)
|
||||
let accessibilityValue = String(format: accessibleValueFormat, accessibleIndex, numberOfPages)
|
||||
view.accessibilityLabel = accessibilityValue
|
||||
view.accessibilityIdentifier = accessibilityValue
|
||||
}
|
||||
|
||||
public override func assessTouchOf(_ touchPoint_X: CGFloat) {
|
||||
|
||||
@ -11,149 +11,77 @@
|
||||
// MARK: - Outlets
|
||||
//--------------------------------------------------
|
||||
|
||||
public let heart = Heart()
|
||||
public let leftHeadline = Label(fontStyle: .BoldBodySmall)
|
||||
public let leftBody = Label(fontStyle: .RegularBodySmall)
|
||||
public let badge = Badge()
|
||||
public let leftHeadline = Label(fontStyle: .BoldTitleSmall)
|
||||
public let leftBody = Label(fontStyle: .RegularMicro)
|
||||
public let leftSubBody = Label(fontStyle: .RegularBodySmall)
|
||||
public let rightLabel = Label(fontStyle: .RegularBodySmall)
|
||||
private lazy var rightLabelStackItem: StackItem = {
|
||||
StackItem(andContain: rightLabel)
|
||||
}()
|
||||
public var model: ListStoreLocatorModel?
|
||||
|
||||
public lazy var horizontalStack: Stack<StackModel> = {
|
||||
return Stack<StackModel>(with: StackModel(molecules: [StackItemModel(horizontalAlignment: .fill),
|
||||
StackItemModel(horizontalAlignment: .fill),
|
||||
StackItemModel(horizontalAlignment: .trailing)],
|
||||
axis: .horizontal, spacing: Padding.Two), stackItems: [StackItem(andContain: leftHeadline), StackItem(andContain: heart), rightLabelStackItem])
|
||||
StackItemModel(horizontalAlignment: .trailing, verticalAlignment: .center)],
|
||||
axis: .horizontal, spacing: Padding.Two), stackItems: [StackItem(andContain: stack), StackItem(andContain: rightLabel)])
|
||||
}()
|
||||
|
||||
public lazy var stack: Stack<StackModel> = {
|
||||
return Stack<StackModel>.createStack(with: [horizontalStack, leftBody, leftSubBody], axis: .vertical, spacing: 0)
|
||||
}()
|
||||
public var sizeObject: MFSizeObject? = MFSizeObject(standardSize: 12, standardiPadPortraitSize: 18)
|
||||
return Stack<StackModel>(with: .init(molecules: [StackItemModel(horizontalAlignment: .leading),
|
||||
StackItemModel(horizontalAlignment: .fill), StackItemModel(horizontalAlignment: .fill), StackItemModel(horizontalAlignment: .fill)],
|
||||
axis: .vertical, spacing: Padding.One), stackItems: [StackItem(andContain: badge), StackItem(andContain: leftHeadline), StackItem(andContain: leftBody), StackItem(andContain: leftSubBody)])
|
||||
|
||||
}()
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//-------------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
addMolecule(stack)
|
||||
addMolecule(horizontalStack)
|
||||
stack.restack()
|
||||
horizontalStack.restack()
|
||||
leftSubBody.textColor = UIColor.mfTextLightGray()
|
||||
}
|
||||
|
||||
public override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
if let dimension = sizeObject?.getValueBased(onSize: size) {
|
||||
heart.widthConstraint?.constant = dimension
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//------------------------------------------------------
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? ListStoreLocatorModel else { return }
|
||||
horizontalStack.updateContainedMolecules(with: [model.leftHeadline, model.heart, model.rightLabel], delegateObject, additionalData)
|
||||
leftBody.set(with: model.leftBody, delegateObject, additionalData)
|
||||
leftSubBody.set(with: model.leftSubBody, delegateObject, additionalData)
|
||||
stack.updateContainedMolecules(with: [model.badge, model.leftHeadline, model.leftBody, model.leftSubBody], delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
self.model = model
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
|
||||
open override func alignAccessoryToHero() -> CGPoint? {
|
||||
let heroCenter = super.alignAccessoryToHero()
|
||||
|
||||
if let heroCenter = heroCenter {
|
||||
let convertedPoint = horizontalStack.convert(heroCenter, from: self)
|
||||
rightLabelStackItem.containerHelper.alignCenterVerticalConstraint?.constant = convertedPoint.y - horizontalStack.bounds.midY
|
||||
}
|
||||
return heroCenter
|
||||
}
|
||||
|
||||
public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
|
||||
if listItemModel?.action != nil {
|
||||
super.didSelectCell(at: index, delegateObject: delegateObject, additionalData: additionalData)
|
||||
} else {
|
||||
heart.tapAction()
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { 120 }
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftHeadline.setFontStyle(.BoldBodySmall)
|
||||
leftBody.setFontStyle(.RegularBodySmall)
|
||||
leftHeadline.setFontStyle(.BoldTitleSmall)
|
||||
leftBody.setFontStyle(.RegularMicro)
|
||||
leftSubBody.setFontStyle(.RegularBodySmall)
|
||||
rightLabel.setFontStyle(.RegularBodySmall)
|
||||
leftSubBody.textColor = UIColor.mfTextLightGray()
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Accessibility
|
||||
//--------------------------------------------------
|
||||
|
||||
func getAccessibilityMessage() -> String? {
|
||||
var message = ""
|
||||
heart.updateAccessibilityLabel()
|
||||
|
||||
if let leftHeadlineText = leftHeadline.text, !leftHeadlineText.isEmpty {
|
||||
message += leftHeadlineText + ", "
|
||||
}
|
||||
|
||||
if let leftBodyText = leftBody.text, !leftBodyText.isEmpty {
|
||||
message += leftBodyText + ", "
|
||||
}
|
||||
|
||||
if let leftSubBodyText = leftSubBody.text, !leftSubBodyText.isEmpty {
|
||||
message += leftSubBodyText + ", "
|
||||
}
|
||||
|
||||
if let rightLabelText = rightLabel.text, !rightLabelText.isEmpty {
|
||||
message += rightLabelText
|
||||
}
|
||||
return message.count > 0 ? message : nil
|
||||
}
|
||||
|
||||
func updateAccessibilityLabel() {
|
||||
let hasHeart = !(horizontalStack.stackModel?.molecules[1].gone ?? true)
|
||||
if let accessoryView = accessoryView,
|
||||
hasHeart {
|
||||
// Both accessory and heart actions.
|
||||
isAccessibilityElement = false
|
||||
accessoryView.accessibilityLabel = getAccessibilityMessage()
|
||||
accessibilityElements = [accessoryView, heart]
|
||||
} else {
|
||||
// Make whole cell focusable if no action.
|
||||
isAccessibilityElement = true
|
||||
var message = getAccessibilityMessage()
|
||||
if hasHeart {
|
||||
accessibilityHint = heart.accessibilityHint
|
||||
if let heartLabel = heart.accessibilityLabel {
|
||||
message = (message ?? "") + ", " + heartLabel
|
||||
}
|
||||
} else {
|
||||
accessibilityHint = nil
|
||||
}
|
||||
accessibilityLabel = message
|
||||
}
|
||||
}
|
||||
|
||||
// Ensures voice over does not read "selected" after user triggers action on cell.
|
||||
override public var accessibilityTraits: UIAccessibilityTraits {
|
||||
get {
|
||||
if (accessoryView != nil) {
|
||||
return .button
|
||||
} else if (!(horizontalStack.stackModel?.molecules[1].gone ?? true)) {
|
||||
return heart.accessibilityTraits
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
}
|
||||
set { }
|
||||
}
|
||||
|
||||
func updateAccessibilityLabel() {
|
||||
isAccessibilityElement = true
|
||||
let message = [model?.badge?.text, model?.leftHeadline.text, model?.leftBody.text, model?.leftSubBody.text, model?.rightLabel.text].compactMap { $0 }.joined(separator: ", ")
|
||||
accessibilityLabel = message
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier = "listStoreLocator"
|
||||
public var heart: HeartModel?
|
||||
public var badge: BadgeModel?
|
||||
public var leftHeadline: LabelModel
|
||||
public var leftBody: LabelModel
|
||||
public var leftSubBody: LabelModel
|
||||
@ -22,8 +22,8 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(heart: HeartModel?, leftHeadline: LabelModel, leftBody: LabelModel, leftSubBody: LabelModel, rightLabel: LabelModel) {
|
||||
self.heart = heart
|
||||
public init(badge: BadgeModel?, leftHeadline: LabelModel, leftBody: LabelModel, leftSubBody: LabelModel, rightLabel: LabelModel) {
|
||||
self.badge = badge
|
||||
self.leftHeadline = leftHeadline
|
||||
self.leftBody = leftBody
|
||||
self.leftSubBody = leftSubBody
|
||||
@ -49,7 +49,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case heart
|
||||
case badge
|
||||
case leftHeadline
|
||||
case leftBody
|
||||
case leftSubBody
|
||||
@ -62,7 +62,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
|
||||
|
||||
public required init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
heart = try typeContainer.decodeIfPresent(HeartModel.self, forKey:.heart)
|
||||
badge = try typeContainer.decodeIfPresent(BadgeModel.self, forKey:.badge)
|
||||
leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline)
|
||||
leftBody = try typeContainer.decode(LabelModel.self, forKey: .leftBody)
|
||||
leftSubBody = try typeContainer.decode(LabelModel.self, forKey: .leftSubBody)
|
||||
@ -74,7 +74,7 @@ public class ListStoreLocatorModel: ListItemModel, MoleculeModelProtocol {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encodeIfPresent(heart, forKey: .heart)
|
||||
try container.encodeIfPresent(badge, forKey: .badge)
|
||||
try container.encode(leftHeadline, forKey: .leftHeadline)
|
||||
try container.encode(leftBody, forKey: .leftBody)
|
||||
try container.encode(leftSubBody, forKey: .leftSubBody)
|
||||
|
||||
@ -93,11 +93,9 @@ open class NotificationMoleculeModel: ContainerModel, MoleculeModelProtocol {
|
||||
button?.style = .secondary
|
||||
switch style {
|
||||
case .error, .warning:
|
||||
button?.enabledTextColor = Color(uiColor: .mvmBlack)
|
||||
button?.enabledBorderColor = Color(uiColor: .mvmBlack)
|
||||
button?.inverted = false
|
||||
default:
|
||||
button?.enabledTextColor = Color(uiColor: .mvmWhite)
|
||||
button?.enabledBorderColor = Color(uiColor: .mvmWhite)
|
||||
button?.inverted = true
|
||||
}
|
||||
|
||||
if closeButton?.color == nil {
|
||||
|
||||
@ -372,7 +372,9 @@ open class Carousel: View {
|
||||
self.carouselAccessibilityElement = carouselAccessibilityElement
|
||||
}
|
||||
|
||||
if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) {
|
||||
if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)), let pagingView = self.pagingView {
|
||||
_accessibilityElements = [currentCell, carouselAccessibilityElement, pagingView]
|
||||
} else if let currentCell = collectionView.cellForItem(at: IndexPath(row: currentIndex, section: 0)) {
|
||||
_accessibilityElements = [currentCell, carouselAccessibilityElement]
|
||||
} else {
|
||||
_accessibilityElements = [carouselAccessibilityElement]
|
||||
|
||||
@ -72,6 +72,7 @@ open class CoreUIModelMapping: ModelMapping {
|
||||
ModelRegistry.register(handler: LoadingSpinner.self, for: LoadingSpinnerModel.self)
|
||||
ModelRegistry.register(handler: Video.self, for: VideoModel.self)
|
||||
ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self)
|
||||
ModelRegistry.register(handler: Badge.self, for: BadgeModel.self)
|
||||
|
||||
// MARK:- Horizontal Combination Molecules
|
||||
ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self)
|
||||
|
||||
@ -32,9 +32,4 @@ extension RawRepresentableCodable {
|
||||
throw RawRepresentableCodableError.invalid(value: "\(rawValue)")
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
try container.encode(self)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user