Edit in JSFiddle

<script src="http://fb.me/react-js-fiddle-integration.js"></script>


<script type="text/jsx">/** @jsx React.DOM */
  <component extends="span" name="tickTockClock">
    {function(template, props, state, update){
      var now = new Date;
      if (!state.now || +now - +state.now > 1000) {
        state.now = now;
        if (props.onchange) props.onchange(state.now);
      }
      state.alt = state.now.getSeconds() % 2;
      var hour = state.now.getHours();
      if (hour > 12) hour -= 12;
      
      <template style={{background:"blue", color:"white"}}>
        <span>{hour}</span>
        <span id="sep" style={{ visibility:state.alt ? 'hidden':'visible' }}>:</span>
        <span>{state.now.getMinutes()}</span>
        <span id="sep" style={{ visibility:state.alt ? 'hidden':'visible' }}>:</span>
        <span>{state.now.getSeconds()}</span>
      </template>
      
      setTimeout(update, 500);
    }}
  </component>
</script>

<script type="text/jsx">/** @jsx React.DOM */
  <component extends="form" name="inputToy">
    {function(template, props, state, redrawSoon){
      if (!state.foo) state.foo = (props.max - props.min) * Math.random() + props.min;
      var step = (props.max - props.min) / (props.steps || 100);
      if (state.shouldRound) state.foo = Math.round(state.foo);
      if (props.value) state.foo = props.value;
      
      <Spring input={+state.foo} precision={1000}>{state.springState || (state.springState = {value:state.foo})}</Spring>;
      if (state.springState.isDirty) redrawSoon();
      
      <template style={props.style}>
        <label>Round? <input type="checkbox" onChange={state.handlerFor('shouldRound')} /></label>
        <input type="range"  min={props.min} max={props.max} step={step} value={state.foo} onChange={state.handlerFor('foo')} />
        <input type="number" min={props.min} max={props.max} step={step} value={state.foo} onChange={state.handlerFor('foo')} />
        <input value={state.foo} readOnly size="4" />
        <input value={state.springState.value} readOnly size="4" />
        <Layer flow left={0} opacity={.25} w='100%' h="1.4em" scaleX={(state.springState.value - props.min) / props.max} origin='left center' />
      </template>
    }}
  </component>
</script>

<script type="text/jsx">/** @jsx React.DOM */
  <component extends="div" name="demo">
    {function(template, props, state, update){
      <template data-name="demo">
        <tickTockClock onchange={state.setterFor('time')} />
        <inputToy min="0" max="59" steps="1" value={state.time && state.time.getSeconds() || 0} />
        <inputToy min="0" max="11" steps="33" />
        <inputToy min="0" max="1" steps="8" />
        <inputToy min="123" max="456" />
      </template>
    }}
  </component>
</script>

<script type="text/jsx">/** @jsx React.DOM */
  <Root><demo /></Root>
</script>
function Root(props, firstChild){
  var parentNode = props && (props.parentNode || props.mountNode || (props.parentNodeId && document.getElementById(props.parentNodeId))) || document.body;
  if (!parentNode) return setTimeout(Root.bind(this, props, firstChild), 1000/60);
  var children = Array.prototype.slice.call(arguments, 1);
  if (children.length > 1) firstChild = React.DOM[props && props.nodeName || 'div'](null, children);
  React.renderComponent(
    firstChild,
    parentNode
  );
}

function component(componentProps, render){
  var root;
  var superComponent, superComponentId = componentProps && componentProps["extends"];
  superComponent = React.DOM[superComponentId] || window[superComponentId] || React.DOM.div;
  
  function template(props){
    var children = Array.prototype.slice.call(arguments, 1);
    return root = superComponent(props, children);
  }
  window[componentProps.name] = React.createClass({
    getInitialState: ComponentState.getInitialState,
    _render:render,
    render: function(){
      this._render(template, this.props, this.state, this.state.updateEventually);
      return root;
    }
  });
}

var requestAnimationFrame = (window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){return setTimeout(callback, 1000/30);}).bind(window);
var cancelAnimationFrame = (window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || function(timerId){return clearTimeout(timerId);}).bind(window);

function ComponentState(component){
  if (!(this instanceof ComponentState)) throw TypeError('ComponentState must be called with `new`');
  var state = this;
  state.update = component.replaceState.bind(component, state, undefined);
  state.updateEventually = state.updateEventually.bind(state);
}

ComponentState.getInitialState = function(){
  return new ComponentState(this);
}

ComponentState.prototype = {

  constructor: ComponentState,

  handlerFor: function(key){
    if (this[key + 'Handler']) return this[key + 'Handler'];
    return this[key + 'Handler'] = this.handler.bind(this, key);
  },
  handler: function(key, event){
    var value = event.target.value;
    if (event.target.type == 'checkbox'){
      if (event.target.checked){
        if (!value) value = true;
      }
      else value = null;
    }
    this.set(key, value);
  },
  setterFor: function(key){
    if (this[key + 'Setter']) return this[key + 'Setter'];
    return this[key + 'Setter'] = this.set.bind(this, key);
  },
  set: function(key, value){
    this[key] = value;
    this.updateEventually();
  },
  updateEventually: function(){
    if (this._updateTimer) cancelAnimationFrame(this._updateTimer);
    this._updateTimer = requestAnimationFrame(this.update);
  },
  update: function(callback){
    throw Error('Update is an abstract method. You need to override it');
  }
}

function CSSTransform(props){
  var cssText = '', value;
  for (var key in props) {
    if (!props.hasOwnProperty(key)) continue;
    value = props[key];
    if (value == null) continue;
    cssText += key + '(' + value + ') ';
  }
  return cssText;
}

function px(value){
  if (typeof value == 'number') return value + 'px';
  if (Array.isArray(value)) return value.map(px);
  return value;
}

function valueFromRangeToRange(value, fromMin, fromMax, toMin, toMax){
  if (typeof value != number) return value;
  var fromRange = fromMax - fromMin;
  var toRange = toMax - toMin;
  return (((fromValue - fromMin) * toRange) / fromRange) + toMin;
}


function Layer(props, firstChild){
  var children = firstChild && Array.prototype.slice.call(arguments, 1);
  var origin = props.origin;
  var transform = CSSTransform({
    matrix: props.matrix || props.m,
    matrix3d: props.matrix3d || props.m3d,

    translate: px(props.translate || props.t),
    translate3d: px(props.translate3d || props.t3d),
    translateX: px(props.translateX || props.tX),
    translateY: px(props.translateY || props.tY),
    translateZ: px(props.translateZ || props.tZ),

    scale: props.scale || props.s,
    scale3d: props.scale3d || props.s3d,
    scaleX: props.scaleX || props.sX,
    scaleY: props.scaleY || props.sY,
    scaleZ: props.scaleZ || props.sZ,

    skewX: props.skewX || props.kX,
    skewY: props.skewY || props.sY,

    rotate: props.rotate || props.r,
    rotate3d: props.rotate3d || props.r3d,
    rotateX: props.rotateX || props.rX,
    rotateY: props.rotateY || props.rY,
    rotateZ: props.rotateZ || props.rZ,

    perspective: props.perspective || props.p,
  });
  
  var filter = CSSTransform({
    "grayscale": props.grayscale,
    "sepia": props.sepia,
    "saturate": props.saturate,
    "hue-rotate": props.hue,
    "invert": props.invert,
    "opacity": props.opacity,
    "brightness": props.brightness,
    "contrast": props.contrast,
    "blur": px(props.blur),
    "drop-shadow": props.shadow,
  });
  
  var style = {
    display: 'inline-block',
    position: 'absolute',

    backgroundColor: props.fill || '#f00',
    opacity: props.alpha || props.opacity,
    width: props.width || props.w,
    height: props.height || props.h,

    'pointer-events': props.touchable ? 'auto' : 'none',

    'filter': filter,
    'transform-origin': origin,
    'transform': transform,
  };
  
  if (props.flow) style.top = style.left = 'auto';
  else style.top = style.left = 0;
  if ('top' in props) style.top = props.top;
  if ('left' in props) style.left = props.left;
  
  expandCSSCompat(style, 'filter');
  expandCSSCompat(style, 'transform');
  expandCSSCompat(style, 'transform-origin');
  
  return React.DOM.div({style:style}, children);
}

function expandCSSCompat(style, key){
  style['-webkit-' + key] = style[key];
  style['-moz-' + key] = style[key];
  style['-ms-' + key] = style[key];
  style['-o-' + key] = style[key];
}


function Spring(config, state){
  // config
  var mass = state.mass = config.mass || state.mass || Spring.prototype.mass;
  var friction = state.friction = config.friction || state.friction || Spring.prototype.friction;
  var stiffness = state.stiffness = config.stiffness || state.stiffness || Spring.prototype.stiffness;
  
  var precision = state.precision = config.precision || state.precision || Spring.prototype.precision || 1000;
  var min = state.min = config.min || state.min || Spring.prototype.min;
  
  var input = config.input || state.input || Spring.prototype.input;
  input = Math.round((input * precision)) / precision;
  
  var value = config.value || state.value || 0;
  // state.targetValue = value;
  var speed = config.speed || state.speed || 0;
  
  // if (typeof value != 'number') throw TypeError('expected "value" to be a number');
  
  var scale = config.scale || state.scale || 0;
  if (!scale){
    var ts = state.ts || Date.now();
    state.ts = Date.now();
    scale = (state.ts - ts) / 30 || 1;
  }
  
  // calculate
  var distance = value - input;
  if (!(distance > min && distance > -min
  ||  distance < min && distance < -min)){
    if (!(speed > min && speed > -min
    ||  speed < min && speed < -min)){
      distance = 0;
      value = input;
      speed = 0;
    }
  }
  
  state.isDirty = distance + speed;
  
  var dampingForce = -friction * speed;
  var springForce = -stiffness * distance;
  var totalForce = springForce + dampingForce;
  var acceleration = totalForce / mass;
  
  // output
  state.speed = speed + acceleration * scale;
  state.value = value + state.speed;
  // state.value = Math.round((state.value * precision)) / precision;
  
  return state.value
}

Spring.prototype.enabled = true;
Spring.prototype.mass = 10;
Spring.prototype.friction = 3;
Spring.prototype.stiffness = 120 / 100;
Spring.prototype.precision = 100;
Spring.prototype.min = 0.01;
Spring.prototype.input = 0;