83 lines
3.1 KiB
Swift
83 lines
3.1 KiB
Swift
//
|
|
// Loader.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 7/5/23.
|
|
//
|
|
|
|
import Foundation
|
|
import UIKit
|
|
import VDSColorTokens
|
|
|
|
|
|
@objc(VDSLoader)
|
|
/// A loader is an indicator that uses animation to show customers that there is an indefinite amount of wait time while a task is ongoing, e.g. a page is loading, a form is being submitted. The component disappears when the task is complete.
|
|
open class Loader: View {
|
|
//--------------------------------------------------
|
|
// MARK: - Private Properties
|
|
//--------------------------------------------------
|
|
private var icon = Icon().with { $0.name = .loader }
|
|
private var opacity: CGFloat = 0.8
|
|
private var iconColorConfiguration = SurfaceColorConfiguration(VDSColor.elementsPrimaryOnlight, VDSColor.elementsPrimaryOndark)
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Public Properties
|
|
//--------------------------------------------------
|
|
/// Loader will be active if 'active' prop is passed.
|
|
open var isActive: Bool = true { didSet { setNeedsUpdate() } }
|
|
|
|
/// The Int used to determine the height and width of the Loader
|
|
open var size: Int = 40 { didSet { setNeedsUpdate() } }
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Lifecycle
|
|
//--------------------------------------------------
|
|
open override func setup() {
|
|
super.setup()
|
|
addSubview(icon)
|
|
|
|
NSLayoutConstraint.activate([
|
|
icon.centerXAnchor.constraint(equalTo: centerXAnchor),
|
|
icon.centerYAnchor.constraint(equalTo: centerYAnchor),
|
|
icon.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor),
|
|
icon.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor),
|
|
icon.topAnchor.constraint(greaterThanOrEqualTo: topAnchor),
|
|
icon.bottomAnchor.constraint(lessThanOrEqualTo: bottomAnchor)
|
|
])
|
|
}
|
|
|
|
/// Function used to make changes to the View based off a change events or from local properties.
|
|
open override func updateView() {
|
|
super.updateView()
|
|
icon.color = iconColorConfiguration.getColor(self)
|
|
icon.customSize = size
|
|
if isActive {
|
|
startAnimating()
|
|
} else {
|
|
stopAnimating()
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// MARK: - Animation
|
|
//--------------------------------------------------
|
|
private let rotationLayerName = "rotationAnimation"
|
|
func startAnimating() {
|
|
icon.layer.remove(layerName: rotationLayerName)
|
|
let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
|
|
rotation.toValue = NSNumber(value: Double.pi * 2)
|
|
rotation.duration = 0.5 // the speed of the rotation
|
|
rotation.isCumulative = true
|
|
rotation.repeatCount = Float.greatestFiniteMagnitude
|
|
icon.layer.add(rotation, forKey: rotationLayerName)
|
|
}
|
|
|
|
func stopAnimating() {
|
|
icon.layer.removeAnimation(forKey: rotationLayerName)
|
|
}
|
|
}
|
|
|
|
extension Icon.Name {
|
|
static let loader = Icon.Name(name: "loader")
|
|
}
|