 /// Optionally, make the cycling `reversible`
 /// in either direction, so instead of starting
 /// again, it reverses when it reaches min/max.
+/// Alternatively, make this `finite` so that
+/// it stops when its bound is reached.
 /// See also @Cycled if this is used in SwiftUI.
 @propertyWrapper
-public struct CycledRaw {
-    private let min:Int
-    private let max:Int
-    private let reversible:Bool
+public struct CycledRaw<T:SignedNumeric & Comparable> {
+    public enum Mode {
+        case repeatable, reversible, finite
+    }
+    private let min:T
+    private let max:T
+    private let mode:Mode
+    private var reversible:Bool {
+        mode == .reversible
+    }
+    private var finite:Bool {
+        mode == .finite
+    }
     private var shouldReverse:Bool = false
-    private var number:Int
-    public var wrappedValue:Int {
+    private var number:T
+    public var wrappedValue:T {
         get { return number }
         set {
-            guard newValue != 0 else { return }
+            guard newValue != T.zero else { return }
             let value = shouldReverse ? -newValue : newValue
             let newNumber = number + value
-            if newValue < 0 { // decrementing
+            if newValue < T.zero { // decrementing
                 if newNumber < min {
-                    number = max
+                    if reversible || finite {
+                        number = min
+                    } else {
+                        number = max
+                    }
                 } else {
                     number = newNumber
                 }
             } else { // incrementing
                 if newNumber > max {
-                    number = min
+                    if reversible || finite {
+                        number = max
+                    } else {
+                        number = min
+                    }
                 } else {
                     number = newNumber
                 }

        }
        self.min = min
        self.max = max
        self.reversible = reversible
        self._number = State(wrappedValue:startingAt)
    }
    public var atMin:Bool {
        wrappedValue == min
    }
    public var atMax:Bool {
        wrappedValue == max
    }
    // Couldn't get this to work.. would just hit Int +=
    // Wanted syntax like: counter += 1

/// Optionally, make the cycling `reversible`
/// in either direction, so instead of starting
/// again, it reverses when it reaches min/max.
/// Alternatively, make this `finite` so that
/// it stops when its bound is reached.
@propertyWrapper
public struct Cycled<T:SignedNumeric & Comparable> : DynamicProperty {
    /// Type of cycling behavior
    public enum Mode {
        /// Cycle numbers from beginning and when
        /// reaching the end, start at the beginning.
        /// Default cycling behavior.
        case repeatable
        /// Cycle numbers from beginning and when
        /// reaching the end, go back to the beginning
        /// and vice versa.
        case reversible
        /// Cycle numbers from beginning and when
        /// reaching the end, stop.
        case finite
    }
    private let min:T
    private let max:T
    private let mode:Mode
    private var reversible:Bool {
        mode == .reversible
    }
    private var finite:Bool {
        mode == .finite
    }
    @State private var number:T = 0
    @State private var shouldReverse:Bool = false
    public var wrappedValue:T {
        get { return number }
        nonmutating set {
            guard newValue != T.zero else { return }
            let value = shouldReverse ? -newValue : newValue
            let newNumber = number + value
            if value < T.zero { // decrementing
                if newNumber < min {
                    if reversible || finite {
                        // Past min value, clamp to min.
                        // It will either start going back the opposite way
                        // for "reversible" or just stay there for "finite".
                        number = min
                    } else {
                        // Past min, start again at max. "repeatable"
                        number = max
                    }
                } else {
                    number = newNumber
                }
            } else { // incrementing
                if newNumber > max {
                    if reversible || finite {
                        number = max
                    } else {
                        number = min
                    }
                } else {
                    number = newNumber
                }
