     return lhs.uuid == rhs.uuid
   }
 }
-
-/** The default tension configuration. */
-public let defaultSpringTension: CGFloat = 342
-
-/** The default friction configuration. */
-public let defaultSpringFriction: CGFloat = 30
-
-/** The default mass configuration. */
-public let defaultSpringMass: CGFloat = 1

   */
  public let suggestedDuration = createProperty("Spring.suggestedDuration", withInitialValue: TimeInterval(0))

  /** The value used when determining completion of the spring simulation. */
  public let threshold: ReactiveProperty<CGFloat>

  public let metadata = Metadata("Spring")

  fileprivate let system: SpringToStream<T>
  fileprivate let _state = createProperty("Spring._state", withInitialValue: MotionState.atRest)

  public func add(to property: ReactiveProperty<T>,
                  withRuntime runtime: MotionRuntime,

import IndefiniteObservable

/**
 The default tension configuration.
 */
public let defaultSpringTension: CGFloat = 342

/**
 The default friction configuration.
 */
public let defaultSpringFriction: CGFloat = 30

/**
 The default mass configuration.
 */
public let defaultSpringMass: CGFloat = 1

/**
 A spring pulls a value from an initial position to a destination using a physical simulation of a
 dampened oscillator.

 A spring can be associated with many properties. Each property receives its own distinct simulator
 that reads the property as the initial value and pulls the value towards the destination.
 Configuration values are shared across all running instances.

 **Constraints**

 T-value constraints may be applied to this interaction.
 */
public class Spring<T: Zeroable>: Interaction, Togglable, Stateful {
  /**
   Creates a spring with a given threshold and system.

   - parameter threshold: The threshold of movement defining the completion of the spring simulation.
   - parameter system: Often coreAnimation. Can be another system if a system support library is available.
   */
  public init(threshold: CGFloat, system: @escaping SpringToStream<T>) {
    self.threshold = createProperty("Spring.threshold", withInitialValue: threshold)
    self.system = system
  }

  /**
   The initial velocity of the spring.

   Applied to the physical simulation only when it starts.
   */
  public let initialVelocity = createProperty("Spring.initialVelocity", withInitialValue: T.zero() as! T)

  /**
   The destination value of the spring represented as a property.

   Changing this property will immediately affect the spring simulation.
   */
  public let destination = createProperty("Spring.destination", withInitialValue: T.zero() as! T)

  /**
   Tension defines how quickly the spring's value moves towards its destination.

   Higher tension means higher initial velocity and more overshoot.
   */
  public let tension = createProperty("Spring.tension", withInitialValue: defaultSpringTension)

  /**
   Tension defines how quickly the spring's velocity slows down.

   Higher friction means quicker deceleration and less overshoot.
   */
  public let friction = createProperty("Spring.friction", withInitialValue: defaultSpringFriction)

  /**
   The mass affects the value's acceleration.

   Higher mass means slower acceleration and deceleration.
   */
  public let mass = createProperty("Spring.mass", withInitialValue: defaultSpringMass)

  /**
