// // BreadcrumbItem.swift // VDS // // Created by Kanamarlapudi, Vasavi on 05/03/24. // import Foundation import UIKit import VDSCoreTokens import Combine /// A Breadcrumb Item contains href(link) and selected flag. /// Breadcrumb links to its respective page if it is not disabled. /// Breadcrumb contains text with a separator by default, highlights text in bold without a separator if selected. @objcMembers @objc (VDSBreadcrumbItem) open class BreadcrumbItem: ButtonBase { //-------------------------------------------------- // MARK: - Initializers //-------------------------------------------------- required public init() { super.init(frame: .zero) } public override init(frame: CGRect) { super.init(frame: .zero) } public required init?(coder: NSCoder) { super.init(coder: coder) } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- /// TextStyle used on the titleLabel. open override var textStyle: TextStyle { isSelected ? TextStyle.boldBodySmall : TextStyle.bodySmall } /// UIColor used on the titleLabel text. open override var textColor: UIColor { textColorConfiguration.getColor(self) } /// Determines if a slash is predended or not. open var hideSlash: Bool = false { didSet { setNeedsUpdate() } } private var slashText = "/ " open override var textAttributes: [any LabelAttributeModel]? { hideSlash ? nil : [ColorLabelAttribute(location: 0, length: 1, color: surface == .light ? VDSColor.elementsPrimaryOnlight : VDSColor.elementsPrimaryOndark), TextStyleLabelAttribute(location: 0, length: 1, textStyle: .bodySmall) ] } //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var textColorConfiguration = ControlColorConfiguration().with { $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .normal) $0.setSurfaceColors(VDSColor.interactiveActiveOnlight, VDSColor.interactiveActiveOndark, forState: .highlighted) $0.setSurfaceColors(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark, forState: .selected) } //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- open override func setDefaults() { super.setDefaults() isAccessibilityElement = true accessibilityTraits = .link titleLabel?.numberOfLines = 0 titleLabel?.lineBreakMode = .byWordWrapping contentHorizontalAlignment = .left bridge_accessibilityHintBlock = { [weak self] in guard let self else { return "" } return !isEnabled ? "" : "Double tap to open." } bridge_accessibilityLabelBlock = { [weak self] in guard let self else { return "" } return text } } /// Used to make changes to the View based off a change events or from local properties. open override func updateView() { //clear the arrays holding actions accessibilityCustomActions = [] if let text, !text.isEmpty { var updatedText = text if updatedText.hasPrefix(slashText) && hideSlash { updatedText = String(updatedText.dropFirst(slashText.count)) } else if !hideSlash, !updatedText.hasPrefix(slashText) { updatedText = slashText + updatedText } //create the primary string let mutableText = NSMutableAttributedString.mutableText(for: updatedText, textStyle: textStyle, useScaledFont: useScaledFont, textColor: textColor, alignment: titleLabel?.textAlignment ?? .center, lineBreakMode: titleLabel?.lineBreakMode ?? .byTruncatingTail) //apply any attributes if let attributes = textAttributes { mutableText.apply(attributes: attributes) } //set the attributed text setAttributedTitle(mutableText, for: .normal) setAttributedTitle(mutableText, for: .highlighted) invalidateIntrinsicContentSize() } else { setAttributedTitle(nil, for: .normal) setAttributedTitle(nil, for: .highlighted) titleLabel?.text = nil } } }