diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index af42161b..ee3a600c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -577,6 +577,8 @@ EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; }; EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; }; EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; }; + EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; }; + EA7D81662B2BABD200D29F9E /* Tooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81652B2BABD200D29F9E /* Tooltip.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 */; }; @@ -1174,6 +1176,8 @@ EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = ""; }; EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = ""; }; + EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = ""; }; + EA7D81652B2BABD200D29F9E /* Tooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tooltip.swift; sourceTree = ""; }; EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = ""; }; EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = ""; }; EA985C3D2970938F00F2FF2E /* Tilelet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tilelet.swift; sourceTree = ""; }; @@ -2255,6 +2259,8 @@ EA985C3D2970938F00F2FF2E /* Tilelet.swift */, EA7D81612B2B6E7F00D29F9E /* IconModel.swift */, EA7D815F2B2B6E6800D29F9E /* Icon.swift */, + EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */, + EA7D81652B2BABD200D29F9E /* Tooltip.swift */, ); path = Views; sourceTree = ""; @@ -2949,7 +2955,9 @@ 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */, D23118B325124E18001C8440 /* NotificationMoleculeView.swift in Sources */, + EA7D81662B2BABD200D29F9E /* Tooltip.swift in Sources */, AA9972502475309F00FC7472 /* ListLeftVariableIconAllTextLinksModel.swift in Sources */, + EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */, AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift b/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift new file mode 100644 index 00000000..92692265 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Tooltip.swift @@ -0,0 +1,66 @@ +// +// Tooltip.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class Tooltip: VDS.Tooltip, VDSMoleculeViewProtocol{ + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public var viewModel: MVMCoreUI.TooltipModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable: Any]? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public convenience required init() { + self.init(frame: .zero) + } + + //-------------------------------------------------- + // MARK: - Public + //-------------------------------------------------- + public func viewModelDidUpdate() { + surface = viewModel.surface + fillColor = viewModel.fillColor + size = viewModel.size + closeButtonText = viewModel.closeButtonText + title = viewModel.title + content = viewModel.content + + if let moleculeModel = viewModel.molecule { + if contentView != nil { + (contentView as? MoleculeViewProtocol)?.set(with: moleculeModel, delegateObject, additionalData) + } else if let molecule = ModelRegistry.createMolecule(moleculeModel, delegateObject: delegateObject, additionalData: additionalData) { + contentView = molecule + } + } + } + + //-------------------------------------------------- + // MARK: - MVMCoreViewProtocol + //-------------------------------------------------- + open func updateView(_ size: CGFloat) {} + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + //since this is a class func, we can't reference it directly + public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + VDS.Icon.Size.medium.dimensions.height + } +} + +extension Tooltip: MVMCoreUIViewConstrainingProtocol { + + public func needsToBeConstrained() -> Bool { true } + + public func horizontalAlignment() -> UIStackView.Alignment { .leading } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift new file mode 100644 index 00000000..713e18ea --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift @@ -0,0 +1,98 @@ +// +// TooltipModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 12/14/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS +import VDSColorTokens +import MVMCore + +open class TooltipModel: MoleculeModelProtocol { + + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "tooltip" + + @DecodableDefault.UUIDString public var id: String + + public var backgroundColor: Color? + + public var size: VDS.Tooltip.Size = .medium + + public var fillColor: VDS.Tooltip.FillColor = .primary + + public var closeButtonText: String = "Close" + + public var title: String? + + public var content: String? + + public var molecule: MoleculeModelProtocol? + + /// surface of the object + public var surface: VDS.Surface = .light + + private enum CodingKeys: String, CodingKey { + case id + case moleculeName + case backgroundColor + case closeButtonText + case title + case content + case contentView + case size + case fillColor + case surface + } + + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + self.backgroundColor = try container.decodeIfPresent(Color.self, forKey: .backgroundColor) + + self.title = try container.decodeIfPresent(String.self, forKey: .title) + self.content = try container.decodeIfPresent(String.self, forKey: .content) + + self.molecule = try container.decodeModelIfPresent(codingKey: .contentView) + + if let closeButtonText = try container.decodeIfPresent(String.self, forKey: .closeButtonText) { + self.closeButtonText = closeButtonText + } + + if let surface = try container.decodeIfPresent(VDS.Surface.self, forKey: .surface) { + self.surface = surface + } + + if let size = try container.decodeIfPresent(VDS.Tooltip.Size.self, forKey: .size) { + self.size = size + } + + if let fillColor = try container.decodeIfPresent(VDS.Tooltip.FillColor.self, forKey: .fillColor) { + self.fillColor = fillColor + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(id, forKey: .id) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(surface, forKey: .surface) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + + try container.encodeIfPresent(size, forKey: .size) + try container.encodeIfPresent(fillColor, forKey: .fillColor) + + try container.encodeIfPresent(closeButtonText, forKey: .closeButtonText) + try container.encodeIfPresent(title, forKey: .title) + try container.encodeIfPresent(content, forKey: .content) + + try container.encodeModelIfPresent(molecule, forKey: .contentView) + } + +} diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 1d5705ae..6a9cc598 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -19,18 +19,20 @@ extension VDS.Badge.FillColor: Codable {} extension VDS.ButtonGroup.Alignment: Codable {} extension VDS.Icon.Name: Codable {} extension VDS.Icon.Size: Codable {} +extension VDS.Tabs.Orientation: Codable {} +extension VDS.Tabs.IndicatorPosition: Codable {} +extension VDS.Tabs.Overflow: Codable {} +extension VDS.Tabs.Size: Codable {} extension VDS.TextLink.Size: Codable {} extension VDS.TextLinkCaret.IconPosition: Codable {} extension VDS.TileContainer.BackgroundColor: Codable {} extension VDS.TileContainer.Padding: Codable {} extension VDS.TileContainer.AspectRatio: Codable {} +extension VDS.Tooltip.FillColor: Codable {} +extension VDS.Tooltip.Size: Codable {} extension VDS.Line.Style: Codable {} extension VDS.Line.Orientation: Codable {} extension VDS.Use: Codable {} -extension VDS.Tabs.Orientation: Codable {} -extension VDS.Tabs.IndicatorPosition: Codable {} -extension VDS.Tabs.Overflow: Codable {} -extension VDS.Tabs.Size: Codable {} extension VDS.Button.Size: RawRepresentableCodable { public static var mapping: [String : VDS.Button.Size] { ["standard": .large, "tiny": .small] } diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index b10742ab..2018c621 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -75,6 +75,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: Tilelet.self, for: TileletModel.self) ModelRegistry.register(handler: Badge.self, for: BadgeModel.self) ModelRegistry.register(handler: Icon.self, for: IconModel.self) + ModelRegistry.register(handler: Tooltip.self, for: TooltipModel.self) // MARK:- Horizontal Combination Molecules ModelRegistry.register(handler: StringAndMoleculeView.self, for: StringAndMoleculeModel.self)