Merge branch 'feature/monarch' of https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui into feature/monarch
@ -74,7 +74,7 @@ extension BaseItemPickerEntryField {
|
|||||||
|
|
||||||
@objc open override func setAccessibilityString(_ accessibilityString: String?) {
|
@objc open override func setAccessibilityString(_ accessibilityString: String?) {
|
||||||
|
|
||||||
var accessibilityString = accessibilityString ?? ""
|
let accessibilityString = accessibilityString ?? ""
|
||||||
textField.accessibilityTraits = .staticText
|
textField.accessibilityTraits = .staticText
|
||||||
textField.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item")
|
textField.accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "textfield_picker_item")
|
||||||
textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")"
|
textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")"
|
||||||
|
|||||||
@ -397,7 +397,7 @@ extension TextEntryField {
|
|||||||
|
|
||||||
@objc open override func setAccessibilityString(_ accessibilityString: String?) {
|
@objc open override func setAccessibilityString(_ accessibilityString: String?) {
|
||||||
|
|
||||||
var accessibilityString = accessibilityString ?? ""
|
let accessibilityString = accessibilityString ?? ""
|
||||||
|
|
||||||
textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")"
|
textField.accessibilityLabel = "\(accessibilityString) \(textField.isEnabled ? "" : MVMCoreUIUtility.hardcodedString(withKey: "textfield_disabled_state") ?? "")"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,7 +26,7 @@ open class CarouselIndicatorModel: CarouselPagingModelProtocol, MoleculeModelPro
|
|||||||
/// Sets the current Index to focus on.
|
/// Sets the current Index to focus on.
|
||||||
public var currentIndex: Int = 0
|
public var currentIndex: Int = 0
|
||||||
public var animated: Bool = true
|
public var animated: Bool = true
|
||||||
public var hidesForSinglePage: Bool = false
|
public var hidesForSinglePage: Bool = true
|
||||||
public var inverted: Bool = false
|
public var inverted: Bool = false
|
||||||
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
|
/// Set true to make the accessibility value as "Slide #currentPage of #totalPage", otherwise will be "Page #currentPage of #totalPage", default is false
|
||||||
public var accessibilityHasSlidesInsteadOfPage: Bool = false
|
public var accessibilityHasSlidesInsteadOfPage: Bool = false
|
||||||
|
|||||||
@ -94,7 +94,7 @@ open class HeadlineBodyModel: ParentMoleculeModelProtocol {
|
|||||||
public extension HeadlineBodyModel {
|
public extension HeadlineBodyModel {
|
||||||
func createHeaderTitleLockupModel(defaultStyle: Style = .header) throws -> TitleLockupModel {
|
func createHeaderTitleLockupModel(defaultStyle: Style = .header) throws -> TitleLockupModel {
|
||||||
guard let headline = headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") }
|
guard let headline = headline else { throw ModelRegistry.Error.decoderOther(message: "headline is required for this use case.") }
|
||||||
var body = self.body
|
let body = self.body
|
||||||
switch style ?? defaultStyle {
|
switch style ?? defaultStyle {
|
||||||
case .landingHeader:
|
case .landingHeader:
|
||||||
headline.fontStyle = Styler.Font.RegularTitle2XLarge
|
headline.fontStyle = Styler.Font.RegularTitle2XLarge
|
||||||
@ -106,7 +106,7 @@ public extension HeadlineBodyModel {
|
|||||||
headline.fontStyle = Styler.Font.RegularTitleXLarge
|
headline.fontStyle = Styler.Font.RegularTitleXLarge
|
||||||
body?.fontStyle = Styler.Font.RegularTitleMedium
|
body?.fontStyle = Styler.Font.RegularTitleMedium
|
||||||
}
|
}
|
||||||
let model = try TitleLockupModel(title: headline, subTitle: body)
|
let model = TitleLockupModel(title: headline, subTitle: body)
|
||||||
model.id = id
|
model.id = id
|
||||||
return model
|
return model
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,7 @@ open class Carousel: View {
|
|||||||
public var delegateObject: MVMCoreUIDelegateObject?
|
public var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
|
||||||
private var size: CGFloat?
|
private var size: CGFloat?
|
||||||
|
|
||||||
// Updates the model and index.
|
// Updates the model and index.
|
||||||
public func updateModelIndex() {
|
public func updateModelIndex() {
|
||||||
(model as? CarouselModel)?.index = pageIndex
|
(model as? CarouselModel)?.index = pageIndex
|
||||||
@ -90,12 +90,29 @@ open class Carousel: View {
|
|||||||
showPeaking(false)
|
showPeaking(false)
|
||||||
|
|
||||||
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
// Go to current cell. layoutIfNeeded is needed otherwise cellForItem returns nil for peaking logic. The dispatch is a sad way to ensure the collection view is ready to be scrolled.
|
||||||
guard let model = model as? CarouselModel, !model.molecules.isEmpty,
|
guard let model = model as? CarouselModel, !model.molecules.isEmpty else { return }
|
||||||
(model.paging == true || loop == true) else { return }
|
guard (model.paging == true || loop == true) else {
|
||||||
|
DispatchQueue.main.async { [self] in
|
||||||
|
updatePagerVisibility()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
DispatchQueue.main.async { [self] in
|
DispatchQueue.main.async { [self] in
|
||||||
collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false)
|
collectionView.scrollToItem(at: IndexPath(row: currentIndex, section: 0), at: itemAlignment, animated: false)
|
||||||
collectionView.layoutIfNeeded()
|
collectionView.layoutIfNeeded()
|
||||||
showPeaking(true)
|
showPeaking(true)
|
||||||
|
updatePagerVisibility()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates if the pager is visible or not.
|
||||||
|
private func updatePagerVisibility() {
|
||||||
|
guard let pagingView = pagingView else { return }
|
||||||
|
let shouldHidePager = collectionView.contentSize.width < bounds.width
|
||||||
|
if (shouldHidePager && !pagingView.isHidden) || (!shouldHidePager && pagingView.isHidden) {
|
||||||
|
pagingView.isHidden = shouldHidePager
|
||||||
|
pagingBottomPin?.isActive = !shouldHidePager
|
||||||
|
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,16 +157,6 @@ open class Carousel: View {
|
|||||||
(cell as? MVMCoreViewProtocol)?.updateView(size)
|
(cell as? MVMCoreViewProtocol)?.updateView(size)
|
||||||
}
|
}
|
||||||
layoutCollection()
|
layoutCollection()
|
||||||
|
|
||||||
// Check must be dispatched to main for the layout to complete in layoutCollection.
|
|
||||||
DispatchQueue.main.async { [self] in
|
|
||||||
let shouldHidePager = molecules?.count ?? 0 < 2 || collectionView.contentSize.width < bounds.width
|
|
||||||
if let pagingView = pagingView, shouldHidePager != pagingView.isHidden {
|
|
||||||
pagingView.isHidden = shouldHidePager
|
|
||||||
pagingBottomPin?.isActive = !shouldHidePager
|
|
||||||
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -244,7 +251,7 @@ open class Carousel: View {
|
|||||||
|
|
||||||
var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? = nil
|
var pagingView: (MoleculeViewProtocol & CarouselPageControlProtocol)? = nil
|
||||||
if let molecule = molecule,
|
if let molecule = molecule,
|
||||||
(!molecule.hidesForSinglePage || numberOfPages > 1) {
|
(numberOfPages > 1 || !molecule.hidesForSinglePage) {
|
||||||
pagingView = ModelRegistry.createMolecule(molecule, delegateObject: delegateObject) as? (MoleculeViewProtocol & CarouselPageControlProtocol)
|
pagingView = ModelRegistry.createMolecule(molecule, delegateObject: delegateObject) as? (MoleculeViewProtocol & CarouselPageControlProtocol)
|
||||||
pagingMoleculeName = molecule.moleculeName
|
pagingMoleculeName = molecule.moleculeName
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -35,16 +35,16 @@ public class PageGetContactBehavior: PageVisibilityBehavior {
|
|||||||
CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in
|
CNContactStore().requestAccess(for: .contacts) { [weak self] (access, error) in
|
||||||
guard access,
|
guard access,
|
||||||
error == nil,
|
error == nil,
|
||||||
let rootMolecules = self?.delegate?.moleculeDelegate?.getRootMolecules() else { return }
|
let rootMolecules = delegateObject?.moleculeDelegate?.getRootMolecules() else { return }
|
||||||
// Iterate models and provide contact
|
// Iterate models and provide contact
|
||||||
self?.getContacts(for: rootMolecules)
|
self?.getContacts(for: rootMolecules)
|
||||||
|
|
||||||
// Tell template to update
|
// Tell template to update
|
||||||
MVMCoreDispatchUtility.performBlock(onMainThread: {
|
Task { @MainActor in
|
||||||
// TODO: move to protocol function instead
|
// TODO: move to protocol function instead
|
||||||
guard let controller = self?.delegate?.moleculeDelegate as? ViewController else { return }
|
guard let controller = delegateObject?.moleculeDelegate as? ViewController else { return }
|
||||||
controller.handleNewData()
|
controller.handleNewData()
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ extension UIColor {
|
|||||||
/// Dictionary to access brand approved colors by name.
|
/// Dictionary to access brand approved colors by name.
|
||||||
public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"),
|
public static let names: [String: ColorHexTuple] = ["black": (.mvmBlack, "#000000"),
|
||||||
"white": (.mvmWhite, "#FFFFFF"),
|
"white": (.mvmWhite, "#FFFFFF"),
|
||||||
"red": (.mvmRed, "#F50A23"),
|
"red": (.mvmRed, "#EE0000"),
|
||||||
"pink": (.mvmPink, "#D90368"),
|
"pink": (.mvmPink, "#D90368"),
|
||||||
"pink33": (.mvmPink33, "#F2ABCD"),
|
"pink33": (.mvmPink33, "#F2ABCD"),
|
||||||
"pink66": (.mvmPink66, "#E6589B"),
|
"pink66": (.mvmPink66, "#E6589B"),
|
||||||
@ -88,7 +88,7 @@ extension UIColor {
|
|||||||
// MARK: - Red
|
// MARK: - Red
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
/// HEX: ##F50A23
|
/// HEX: #EE0000
|
||||||
@objc
|
@objc
|
||||||
public static let mvmRed = UIColor.assetColor(named: "red")
|
public static let mvmRed = UIColor.assetColor(named: "red")
|
||||||
|
|
||||||
@ -256,6 +256,7 @@ extension UIColor {
|
|||||||
return UIColor(named: name, in: MVMCoreUIUtility.bundleForMVMCoreUI(), compatibleWith: nil)!
|
return UIColor(named: name, in: MVMCoreUIUtility.bundleForMVMCoreUI(), compatibleWith: nil)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a color corresponding to the passed in color name.
|
||||||
@objc
|
@objc
|
||||||
public static func mvmCoreUIColor(with name: String) -> UIColor? {
|
public static func mvmCoreUIColor(with name: String) -> UIColor? {
|
||||||
return UIColor.names[name]?.uiColor
|
return UIColor.names[name]?.uiColor
|
||||||
|
|||||||
@ -77,7 +77,7 @@
|
|||||||
#pragma mark - legacy
|
#pragma mark - legacy
|
||||||
|
|
||||||
+ (nonnull UIColor *)mfRedColor {
|
+ (nonnull UIColor *)mfRedColor {
|
||||||
return [UIColor colorWithRed:.804 green:.016 blue:.043 alpha:1.0];
|
return [UIColor mvmRed];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (nonnull UIColor *)mfDarkerRedColor {
|
+ (nonnull UIColor *)mfDarkerRedColor {
|
||||||
@ -299,6 +299,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
+ (nullable UIColor *)mfGetColorForString:(nullable NSString *)string {
|
+ (nullable UIColor *)mfGetColorForString:(nullable NSString *)string {
|
||||||
|
if ([string hasPrefix:@"#"]) {
|
||||||
|
return [self mfGetColorForHex:string];
|
||||||
|
}
|
||||||
|
|
||||||
static NSDictionary *stringColorMapping;
|
static NSDictionary *stringColorMapping;
|
||||||
static dispatch_once_t once;
|
static dispatch_once_t once;
|
||||||
dispatch_once(&once, ^{
|
dispatch_once(&once, ^{
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
import MVMCore
|
||||||
|
|
||||||
extension UIStackView: MVMCoreViewProtocol {
|
extension UIStackView: MVMCoreViewProtocol {
|
||||||
public func updateView(_ size: CGFloat) {
|
public func updateView(_ size: CGFloat) {
|
||||||
@ -16,7 +17,7 @@ extension UIStackView: MVMCoreViewProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function for updating molecules. If model is nil, view is hidden.
|
/// A convenience function for updating molecules. If model is nil, view is hidden.
|
||||||
open func updateContainedMolecules(with models: [MoleculeModelProtocol?], _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
public func updateContainedMolecules(with models: [MoleculeModelProtocol?], _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
for (index, item) in arrangedSubviews.enumerated() {
|
for (index, item) in arrangedSubviews.enumerated() {
|
||||||
if let model = models[index] {
|
if let model = models[index] {
|
||||||
(item as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData)
|
(item as? MoleculeViewProtocol)?.set(with: model, delegateObject, additionalData)
|
||||||
|
|||||||
@ -5,9 +5,9 @@
|
|||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0x23",
|
"blue" : "0x00",
|
||||||
"green" : "0x0A",
|
"green" : "0x00",
|
||||||
"red" : "0xF5"
|
"red" : "0xEE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|||||||
@ -404,7 +404,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
|
|
||||||
public func update(percentage: CGFloat) {
|
public func update(percentage: CGFloat) {
|
||||||
guard customInteractor?.interactive == true,
|
guard customInteractor?.interactive == true,
|
||||||
let index = index else { return }
|
let _ = index else { return }
|
||||||
// tabs.progress(from: tabs.selectedIndex, toIndex: index, percentage: percentage)
|
// tabs.progress(from: tabs.selectedIndex, toIndex: index, percentage: percentage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,15 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"filename" : "Vector.svg",
|
||||||
"filename" : "exportBlack.png",
|
"idiom" : "universal"
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"filename" : "exportBlack@2x.png",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"filename" : "exportBlack@3x.png",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
MVMCoreUI/SupportingFiles/Media.xcassets/externalLink.imageset/Vector.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M20 -3.05176e-05V7.11108H18.7555V2.1333L11.9555 8.9333L11.0666 8.04441L17.8666 1.25553H12.8889V-3.05176e-05H20ZM15 18.7555H1.25553V4.99997H12.2222L13.3333 3.75552H-2.28882e-05V20H16.2555V6.66664L15 7.77775V18.7555Z" fill="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 343 B |
|
Before Width: | Height: | Size: 345 B |
|
Before Width: | Height: | Size: 589 B |
|
Before Width: | Height: | Size: 869 B |
@ -1,23 +1,15 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "nav_back.png",
|
"filename" : "Vector.svg",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal"
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "nav_back@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "nav_back@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"author" : "xcode",
|
"author" : "xcode",
|
||||||
"version" : 1
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
MVMCoreUI/SupportingFiles/Media.xcassets/nav_back.imageset/Vector.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M20 10.6361H2.46073L10.9975 19.1001L10.0897 20L0 10L10.0897 0L10.9974 0.899867L2.46077 9.36388H20V10.6361Z" fill="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 235 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 394 B |
|
Before Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 631 B |
|
Before Width: | Height: | Size: 257 B |
@ -1,23 +1,15 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "Close.png",
|
"filename" : "Vector.svg",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal"
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "Close-1.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "Close-2.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"author" : "xcode",
|
"author" : "xcode",
|
||||||
"version" : 1
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"preserves-vector-representation" : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
3
MVMCoreUI/SupportingFiles/Media.xcassets/nav_close.imageset/Vector.svg
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.87772 9.00001L17.7777 16.8889L16.8888 17.7778L8.99995 9.87778L1.11106 17.7778L0.222168 16.8889L8.11106 9.00001L0.222168 1.11112L1.11106 0.222229L8.99995 8.11112L16.8888 0.222229L17.7777 1.11112L9.87772 9.00001Z" fill="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 342 B |