     var bounds: CGRect = .zero {
         didSet {
             // Update mask-layer frame accordingly.
-            maskLayerFrameAnimationSubject.value = maskLayerFrameAnimationForCurrentProgress(animated: false)
+            maskLayerFrameAnimationSubject.value = makeMaskLayerFrameAnimation(animated: false)
         }
     }
 
     /// The current progress.
-    var progress: Float = 0.5 {
-        didSet {
-            // Make sure progress value fits our bounds.
-            progress = min(1, max(0, progress))
-
-            if shouldUpdateMaskLayerFrameOnProgressChange {
-                maskLayerFrameAnimationSubject.value = maskLayerFrameAnimationForCurrentProgress(animated: false)
-            }
+    var progress: Float {
+        get { _progress }
+        set {
+            _progress = newValue.clamped(to: 0 ... 1)
+            maskLayerFrameAnimationSubject.value = makeMaskLayerFrameAnimation(animated: false)
         }
     }
 


    // MARK: - Private properties

    private let maskLayerFrameAnimationSubject: CurrentValueSubject<FrameAnimation, Never>
        = CurrentValueSubject(.zero)

    /// Boolean flag whether we should calculate a new frame for the mask-layer
    /// on setting the `progress` value.
    ///
    /// - SeeAlso: `setProgress(_:animated:)`
    private var shouldUpdateMaskLayerFrameOnProgressChange = true
    // swiftlint:disable:previous identifier_name

    // MARK: - Public methods

    /// Adjusts the current progress, optionally animating the change.
    func setProgress(_ progress: Float, animated: Bool = false) {
        // We don't want to update the mask-layer frame on setting the progress value here, as we might have to do it animated.
        shouldUpdateMaskLayerFrameOnProgressChange = false
        self.progress = progress
        shouldUpdateMaskLayerFrameOnProgressChange = true

        maskLayerFrameAnimationSubject.value = maskLayerFrameAnimationForCurrentProgress(animated: animated)
    }

    // MARK: - Private methods

    private func maskLayerFrameAnimationForCurrentProgress(animated: Bool) -> FrameAnimation {
        var maskLayerFrame = bounds
        maskLayerFrame.size.width *= CGFloat(progress)


        let timingFunction: CAMediaTimingFunction
    }
}

// MARK: - Helper

extension Comparable {

    /// Clamps the current value to the boundaries of the given `limits`.
    ///
    /// - Source: https://stackoverflow.com/a/40868784
    func clamped(to limits: ClosedRange<Self>) -> Self {
        min(max(self, limits.lowerBound), limits.upperBound)
    }
}
