Loic CHOLLIER
2014-05-01 12b8d7ccfe2a0e001157be55228a80be1aca7102
initial commit 4 + add test
18 files added
21 files modified
913 ■■■■■ changed files
Gruntfile.js 6 ●●●●● patch | view | raw | blame | history
README.md 2 ●●● patch | view | raw | blame | history
karma.dev.js 28 ●●●●● patch | view | raw | blame | history
package.json 18 ●●●● patch | view | raw | blame | history
src/DateTimeField.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePicker.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerDate.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerDays.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerHours.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerMinutes.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerMonths.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerTime.jsx 1 ●●●● patch | view | raw | blame | history
src/DateTimePickerYears.jsx 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimeField.jsx.coffee 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimePicker.jsx.coffee 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerDate.jsx.coffee 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerDays.jsx.coffee 2 ●●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerHours.jsx.coffee 2 ●●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerMinutes.jsx.coffee 2 ●●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerMonths.jsx.coffee 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerTime.jsx.coffee 1 ●●●● patch | view | raw | blame | history
src/coffee/DateTimePickerYears.jsx.coffee 2 ●●●●● patch | view | raw | blame | history
src/react-es6/index.js 1 ●●●● patch | view | raw | blame | history
src/react-es6/lib/ExecutionEnvironment.js 44 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/ReactPropTransferer.js 138 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/ReactTransitionEvents.js 97 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/cloneWithProps.js 30 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/copyProperties.js 48 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/cx.js 44 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/emptyFunction.js 43 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/invariant.js 38 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/joinClasses.js 44 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/keyMirror.js 55 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/keyOf.js 23 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/merge.js 37 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/mergeHelpers.js 119 ●●●●● patch | view | raw | blame | history
src/react-es6/lib/mergeInto.js 45 ●●●●● patch | view | raw | blame | history
test/DateTimePickerHoursSpec.jsx 19 ●●●●● patch | view | raw | blame | history
test/coffee/DateTimePickerHoursSpec.jsx.coffee 12 ●●●●● patch | view | raw | blame | history
Gruntfile.js
@@ -84,7 +84,7 @@
          {
            expand: true,
            cwd: 'src',
            src: ['**/*.jsx'],
            src: ['**/*.*', '!coffee/*'],
            dest: 'transpiled',
            ext: '.js'
          }
@@ -95,7 +95,7 @@
          {
            expand: true,
            cwd: 'test',
            src: ['**/*.jsx'],
            src: ['**/*.*', '!coffee/*'],
            dest: 'test-built',
            ext: '.js'
          }
@@ -231,6 +231,8 @@
    'clean:amd',
    'clean:cjs',
    'clean:test',
    'coffee:src',
    'coffee:test',
    'react:src',
    'react:test',
    'transpile',
README.md
@@ -1,4 +1,4 @@
react-bootstrap-datetime-picker
react-bootstrap-datetimepicker
===============================
This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker for React.js
karma.dev.js
New file
@@ -0,0 +1,28 @@
module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['mocha', 'chai'],
    files: [
      'test_bundle.js'
    ],
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    captureTimeout: 60000,
    singleRun: false
  });
};
package.json
@@ -3,7 +3,9 @@
  "version": "0.0.1",
  "description": "A bootstrap datetime picker component for React.js",
  "scripts": {
    "build": "./node_modules/.bin/grunt build"
    "build": "./node_modules/.bin/grunt build",
    "test-watch": "./node_modules/.bin/grunt watch 2>&1 >/dev/null & karma start karma.dev.js",
    "test": "./node_modules/.bin/grunt build && karma start karma.ci.js"
  },
  "keywords": [
    "react",
@@ -17,9 +19,19 @@
    "react": ">=0.9"
  },
  "devDependencies": {
    "karma-chai": "0.0.2",
    "mocha": "~1.16.2",
    "karma-script-launcher": "~0.1.0",
    "karma-chrome-launcher": "~0.1.2",
    "karma-html2js-preprocessor": "~0.1.0",
    "karma-firefox-launcher": "~0.1.3",
    "karma-jasmine": "~0.1.5",
    "karma-coffee-preprocessor": "~0.1.2",
    "requirejs": "~2.1.9",
    "karma-requirejs": "~0.2.1",
    "karma-phantomjs-launcher": "~0.1.1",
    "karma": "~0.10.9",
    "karma-mocha": "~0.1.1",
    "react": "0.10.0",
    "envify": "~1.2.1",
    "grunt-es6-module-transpiler": "~0.6.0",
src/DateTimeField.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
import DateTimePicker from './DateTimePicker';
var DateTimeField;
src/DateTimePicker.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
import DateTimePickerDate from './DateTimePickerDate';
import DateTimePickerTime from './DateTimePickerTime';
var DateTimePicker;
src/DateTimePickerDate.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
import DateTimePickerDays from './DateTimePickerDays';
import DateTimePickerMonths from './DateTimePickerMonths';
import DateTimePickerYears from './DateTimePickerYears';
src/DateTimePickerDays.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
var DateTimePickerDays;
DateTimePickerDays = React.createClass({
src/DateTimePickerHours.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
var DateTimePickerHours;
DateTimePickerHours = React.createClass({
src/DateTimePickerMinutes.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
var DateTimePickerMinutes;
DateTimePickerMinutes = React.createClass({
src/DateTimePickerMonths.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
var DateTimePickerMonths;
DateTimePickerMonths = React.createClass({
src/DateTimePickerTime.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
import DateTimePickerMinutes from './DateTimePickerMinutes';
import DateTimePickerHours from './DateTimePickerHours';
var DateTimePickerTime;
src/DateTimePickerYears.jsx
@@ -1,5 +1,6 @@
/** @jsx React.DOM */
import React from './react-es6';
var DateTimePickerYears;
DateTimePickerYears = React.createClass({
src/coffee/DateTimeField.jsx.coffee
@@ -1,5 +1,6 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
`import DateTimePicker from './DateTimePicker'`
DateTimeField = React.createClass(
src/coffee/DateTimePicker.jsx.coffee
@@ -1,5 +1,6 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
`import DateTimePickerDate from './DateTimePickerDate'`
`import DateTimePickerTime from './DateTimePickerTime'`
src/coffee/DateTimePickerDate.jsx.coffee
@@ -1,5 +1,6 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
`import DateTimePickerDays from './DateTimePickerDays'`
`import DateTimePickerMonths from './DateTimePickerMonths'`
`import DateTimePickerYears from './DateTimePickerYears'`
src/coffee/DateTimePickerDays.jsx.coffee
@@ -1,5 +1,7 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
DateTimePickerDays = React.createClass(
  propTypes:
src/coffee/DateTimePickerHours.jsx.coffee
@@ -1,5 +1,7 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
DateTimePickerHours = React.createClass(
  render: ->
src/coffee/DateTimePickerMinutes.jsx.coffee
@@ -1,5 +1,7 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
DateTimePickerMinutes = React.createClass(
  render: ->
src/coffee/DateTimePickerMonths.jsx.coffee
@@ -1,5 +1,6 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
DateTimePickerMonths = React.createClass(
src/coffee/DateTimePickerTime.jsx.coffee
@@ -1,5 +1,6 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
`import DateTimePickerMinutes from './DateTimePickerMinutes'`
`import DateTimePickerHours from './DateTimePickerHours'`
src/coffee/DateTimePickerYears.jsx.coffee
@@ -1,5 +1,7 @@
###* @jsx React.DOM ###
`import React from './react-es6'`
DateTimePickerYears = React.createClass(
  propTypes:
src/react-es6/index.js
New file
@@ -0,0 +1 @@
export default require('react');
src/react-es6/lib/ExecutionEnvironment.js
New file
@@ -0,0 +1,44 @@
/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule ExecutionEnvironment
 */
/*jslint evil: true */
"use strict";
var canUseDOM = typeof window !== 'undefined';
/**
 * Simple, lightweight module assisting with the detection and context of
 * Worker. Helps avoid circular dependencies and allows code to reason about
 * whether or not they are in a Worker, even if they never include the main
 * `ReactWorker` dependency.
 */
var ExecutionEnvironment = {
  canUseDOM: canUseDOM,
  canUseWorkers: typeof Worker !== 'undefined',
  canUseEventListeners:
    canUseDOM && (window.addEventListener || window.attachEvent),
  isInWorker: !canUseDOM // For now, this is true - might change in the future.
};
export default = ExecutionEnvironment;
src/react-es6/lib/ReactPropTransferer.js
New file
@@ -0,0 +1,138 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule ReactPropTransferer
 */
"use strict";
import emptyFunction from "./emptyFunction";
import invariant from "./invariant";
import joinClasses from "./joinClasses";
import merge from "./merge";
/**
 * Creates a transfer strategy that will merge prop values using the supplied
 * `mergeStrategy`. If a prop was previously unset, this just sets it.
 *
 * @param {function} mergeStrategy
 * @return {function}
 */
function createTransferStrategy (mergeStrategy) {
  return function (props, key, value) {
    if (!props.hasOwnProperty(key)) {
      props[key] = value;
    } else {
      props[key] = mergeStrategy(props[key], value);
    }
  };
}
/**
 * Transfer strategies dictate how props are transferred by `transferPropsTo`.
 */
var TransferStrategies = {
  /**
   * Never transfer `children`.
   */
  children: emptyFunction,
  /**
   * Transfer the `className` prop by merging them.
   */
  className: createTransferStrategy(joinClasses),
  /**
   * Never transfer the `key` prop.
   */
  key: emptyFunction,
  /**
   * Never transfer the `ref` prop.
   */
  ref: emptyFunction,
  /**
   * Transfer the `style` prop (which is an object) by merging them.
   */
  style: createTransferStrategy(merge)
};
/**
 * ReactPropTransferer are capable of transferring props to another component
 * using a `transferPropsTo` method.
 *
 * @class ReactPropTransferer
 */
var ReactPropTransferer = {
  TransferStrategies: TransferStrategies,
  /**
   * Merge two props objects using TransferStrategies.
   *
   * @param {object} oldProps original props (they take precedence)
   * @param {object} newProps new props to merge in
   * @return {object} a new object containing both sets of props merged.
   */
  mergeProps: function (oldProps, newProps) {
    var props = merge(oldProps);
    for (var thisKey in newProps) {
      if (!newProps.hasOwnProperty(thisKey)) {
        continue;
      }
      var transferStrategy = TransferStrategies[thisKey];
      if (transferStrategy) {
        transferStrategy(props, thisKey, newProps[thisKey]);
      } else if (!props.hasOwnProperty(thisKey)) {
        props[thisKey] = newProps[thisKey];
      }
    }
    return props;
  },
  /**
   * @lends {ReactPropTransferer.prototype}
   */
  Mixin: {
    /**
     * Transfer props from this component to a target component.
     *
     * Props that do not have an explicit transfer strategy will be transferred
     * only if the target component does not already have the prop set.
     *
     * This is usually used to pass down props to a returned root component.
     *
     * @param {ReactComponent} component Component receiving the properties.
     * @return {ReactComponent} The supplied `component`.
     * @final
     * @protected
     */
    transferPropsTo: function (component) {
      (invariant(component._owner === this));
      component.props = ReactPropTransferer.mergeProps(
        component.props,
        this.props
      );
      return component;
    }
  }
};
export default = ReactPropTransferer;
src/react-es6/lib/ReactTransitionEvents.js
New file
@@ -0,0 +1,97 @@
/**
 * Copyright 2013-2014 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule ReactTransitionEvents
 */
"use strict";
import ExecutionEnvironment from "./ExecutionEnvironment";
var EVENT_NAME_MAP = {
  transitionend: {
    'transition': 'transitionend',
    'WebkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'mozTransitionEnd',
    'OTransition': 'oTransitionEnd',
    'msTransition': 'MSTransitionEnd'
  },
  animationend: {
    'animation': 'animationend',
    'WebkitAnimation': 'webkitAnimationEnd',
    'MozAnimation': 'mozAnimationEnd',
    'OAnimation': 'oAnimationEnd',
    'msAnimation': 'MSAnimationEnd'
  }
};
var endEvents = [];
function detectEvents() {
  var testEl = document.createElement('div');
  var style = testEl.style;
  for (var baseEventName in EVENT_NAME_MAP) {
    var baseEvents = EVENT_NAME_MAP[baseEventName];
    for (var styleName in baseEvents) {
      if (styleName in style) {
        endEvents.push(baseEvents[styleName]);
        break;
      }
    }
  }
}
if (ExecutionEnvironment.canUseDOM) {
  detectEvents();
}
// We use the raw {add|remove}EventListener() call because EventListener
// does not know how to remove event listeners and we really should
// clean up. Also, these events are not triggered in older browsers
// so we should be A-OK here.
function addEventListener(node, eventName, eventListener) {
  node.addEventListener(eventName, eventListener, false);
}
function removeEventListener(node, eventName, eventListener) {
  node.removeEventListener(eventName, eventListener, false);
}
var ReactTransitionEvents = {
  addEndEventListener: function(node, eventListener) {
    if (endEvents.length === 0) {
      // If CSS transitions are not supported, trigger an "end animation"
      // event immediately.
      window.setTimeout(eventListener, 0);
      return;
    }
    endEvents.forEach(function(endEvent) {
      addEventListener(node, endEvent, eventListener);
    });
  },
  removeEndEventListener: function(node, eventListener) {
    if (endEvents.length === 0) {
      return;
    }
    endEvents.forEach(function(endEvent) {
      removeEventListener(node, endEvent, eventListener);
    });
  }
};
export default = ReactTransitionEvents;
src/react-es6/lib/cloneWithProps.js
New file
@@ -0,0 +1,30 @@
"use strict";
import ReactPropTransferer from './ReactPropTransferer';
import keyOf from './keyOf';
var CHILDREN_PROP = keyOf({children: null});
/**
 * Sometimes you want to change the props of a child passed to you. Usually
 * this is to add a CSS class.
 *
 * @param {object} child child component you'd like to clone
 * @param {object} props props you'd like to modify. They will be merged
 * as if you used `transferPropsTo()`.
 * @return {object} a clone of child with props merged in.
 */
function cloneWithProps (child, props) {
  var newProps = ReactPropTransferer.mergeProps(props, child.props);
  // Use `child.props.children` if it is provided.
  if (!newProps.hasOwnProperty(CHILDREN_PROP) &&
      child.props.hasOwnProperty(CHILDREN_PROP)) {
    newProps.children = child.props.children;
  }
  return child.constructor.ConvenienceConstructor(newProps);
}
export default = cloneWithProps;
src/react-es6/lib/copyProperties.js
New file
@@ -0,0 +1,48 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule copyProperties
 */
/**
 * Copy properties from one or more objects (up to 5) into the first object.
 * This is a shallow copy. It mutates the first object and also returns it.
 *
 * NOTE: `arguments` has a very significant performance penalty, which is why
 * we don't support unlimited arguments.
 */
function copyProperties(obj, a, b, c, d, e, f) {
  obj = obj || {};
  var args = [a, b, c, d, e];
  var ii = 0, v;
  while (args[ii]) {
    v = args[ii++];
    for (var k in v) {
      obj[k] = v[k];
    }
    // IE ignores toString in object iteration.. See:
    // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html
    if (v.hasOwnProperty && v.hasOwnProperty('toString') &&
        (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) {
      obj.toString = v.toString;
    }
  }
  return obj;
}
export default = copyProperties;
src/react-es6/lib/cx.js
New file
@@ -0,0 +1,44 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule cx
 */
/**
 * This function is used to mark string literals representing CSS class names
 * so that they can be transformed statically. This allows for modularization
 * and minification of CSS class names.
 *
 * In static_upstream, this function is actually implemented, but it should
 * eventually be replaced with something more descriptive, and the transform
 * that is used in the main stack should be ported for use elsewhere.
 *
 * @param string|object className to modularize, or an object of key/values.
 *                      In the object case, the values are conditions that
 *                      determine if the className keys should be included.
 * @param [string ...]  Variable list of classNames in the string case.
 * @return string       Renderable space-separated CSS className.
 */
function cx (classNames) {
  if (typeof classNames == 'object') {
    return Object.keys(classNames).map(function(className) {
      return classNames[className] ? className : '';
    }).join(' ');
  } else {
    return Array.prototype.join.call(arguments, ' ');
  }
}
export default = cx;
src/react-es6/lib/emptyFunction.js
New file
@@ -0,0 +1,43 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule emptyFunction
 */
import copyProperties from "./copyProperties";
function makeEmptyFunction (arg) {
  return function () {
    return arg;
  };
}
/**
 * This function accepts and discards inputs; it has no side effects. This is
 * primarily useful idiomatically for overridable function endpoints which
 * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
 */
function emptyFunction () {}
copyProperties(emptyFunction, {
  thatReturns: makeEmptyFunction,
  thatReturnsFalse: makeEmptyFunction(false),
  thatReturnsTrue: makeEmptyFunction(true),
  thatReturnsNull: makeEmptyFunction(null),
  thatReturnsThis: function() { return this; },
  thatReturnsArgument: function(arg) { return arg; }
});
export default = emptyFunction;
src/react-es6/lib/invariant.js
New file
@@ -0,0 +1,38 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule invariant
 */
/**
 * Use invariant() to assert state which your program assumes to be true.
 *
 * Provide sprintf-style format (only %s is supported) and arguments
 * to provide information about what broke and what you were
 * expecting.
 *
 * The invariant message will be stripped in production, but the invariant
 * will remain to ensure logic does not differ in production.
 */
function invariant (condition) {
  if (!condition) {
    var error = new Error('Invariant Violation');
    error.framesToPop = 1;
    throw error;
  }
}
export default = invariant;
src/react-es6/lib/joinClasses.js
New file
@@ -0,0 +1,44 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule joinClasses
 * @typechecks static-only
 */
"use strict";
/**
 * Combines multiple className strings into one.
 * http://jsperf.com/joinclasses-args-vs-array
 *
 * @param {...?string} classes
 * @return {string}
 */
function joinClasses (className/*, ... */) {
  if (!className) {
    className = '';
  }
  var nextClass;
  var argLength = arguments.length;
  if (argLength > 1) {
    for (var ii = 1; ii < argLength; ii++) {
      nextClass = arguments[ii];
      nextClass && (className += ' ' + nextClass);
    }
  }
  return className;
}
export default = joinClasses;
src/react-es6/lib/keyMirror.js
New file
@@ -0,0 +1,55 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule keyMirror
 * @typechecks static-only
 */
"use strict";
import invariant from "./invariant";
/**
 * Constructs an enumeration with keys equal to their value.
 *
 * For example:
 *
 *   var COLORS = keyMirror({blue: null, red: null});
 *   var myColor = COLORS.blue;
 *   var isColorValid = !!COLORS[myColor];
 *
 * The last line could not be performed if the values of the generated enum were
 * not equal to their keys.
 *
 *   Input:  {key1: val1, key2: val2}
 *   Output: {key1: key1, key2: key2}
 *
 * @param {object} obj
 * @return {object}
 */
var keyMirror = function(obj) {
  var ret = {};
  var key;
  (invariant(obj instanceof Object && !Array.isArray(obj)));
  for (key in obj) {
    if (!obj.hasOwnProperty(key)) {
      continue;
    }
    ret[key] = key;
  }
  return ret;
};
export default = keyMirror;
src/react-es6/lib/keyOf.js
New file
@@ -0,0 +1,23 @@
/**
 * Allows extraction of a minified key. Let's the build system minify keys
 * without loosing the ability to dynamically use key strings as values
 * themselves. Pass in an object with a single key/val pair and it will return
 * you the string key of that single record. Suppose you want to grab the
 * value for a key 'className' inside of an object. Key/val minification may
 * have aliased that key to be 'xa12'. keyOf({className: null}) will return
 * 'xa12' in that case. Resolve keys you want to use once at startup time, then
 * reuse those resolutions.
 */
var keyOf = function(oneKeyObj) {
  var key;
  for (key in oneKeyObj) {
    if (!oneKeyObj.hasOwnProperty(key)) {
      continue;
    }
    return key;
  }
  return null;
};
export default keyOf;
src/react-es6/lib/merge.js
New file
@@ -0,0 +1,37 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule merge
 */
"use strict";
import mergeInto from "./mergeInto";
/**
 * Shallow merges two structures into a return value, without mutating either.
 *
 * @param {?object} one Optional object with properties to merge from.
 * @param {?object} two Optional object with properties to merge from.
 * @return {object} The shallow extension of one by two.
 */
var merge = function (one, two) {
  var result = {};
  mergeInto(result, one);
  mergeInto(result, two);
  return result;
};
export default = merge;
src/react-es6/lib/mergeHelpers.js
New file
@@ -0,0 +1,119 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule mergeHelpers
 *
 * requiresPolyfills: Array.isArray
 */
"use strict";
import invariant from "./invariant";
import keyMirror from "./keyMirror";
/**
 * Maximum number of levels to traverse. Will catch circular structures.
 * @const
 */
var MAX_MERGE_DEPTH = 36;
/**
 * We won't worry about edge cases like new String('x') or new Boolean(true).
 * Functions are considered terminals, and arrays are not.
 * @param {*} o The item/object/value to test.
 * @return {boolean} true iff the argument is a terminal.
 */
var isTerminal = function (o) {
  return typeof o !== 'object' || o === null;
};
var mergeHelpers = {
  MAX_MERGE_DEPTH: MAX_MERGE_DEPTH,
  isTerminal: isTerminal,
  /**
   * Converts null/undefined values into empty object.
   *
   * @param {?Object=} arg Argument to be normalized (nullable optional)
   * @return {!Object}
   */
  normalizeMergeArg: function (arg) {
    return arg === undefined || arg === null ? {} : arg;
  },
  /**
   * If merging Arrays, a merge strategy *must* be supplied. If not, it is
   * likely the caller's fault. If this function is ever called with anything
   * but `one` and `two` being `Array`s, it is the fault of the merge utilities.
   *
   * @param {*} one Array to merge into.
   * @param {*} two Array to merge from.
   */
  checkMergeArrayArgs: function (one, two) {
    (invariant(Array.isArray(one) && Array.isArray(two)));
  },
  /**
   * @param {*} one Object to merge into.
   * @param {*} two Object to merge from.
   */
  checkMergeObjectArgs: function (one, two) {
    mergeHelpers.checkMergeObjectArg(one);
    mergeHelpers.checkMergeObjectArg(two);
  },
  /**
   * @param {*} arg
   */
  checkMergeObjectArg: function (arg) {
    (invariant(!isTerminal(arg) && !Array.isArray(arg)));
  },
  /**
   * Checks that a merge was not given a circular object or an object that had
   * too great of depth.
   *
   * @param {number} Level of recursion to validate against maximum.
   */
  checkMergeLevel: function (level) {
    (invariant(level < MAX_MERGE_DEPTH));
  },
  /**
   * Checks that the supplied merge strategy is valid.
   *
   * @param {string} Array merge strategy.
   */
  checkArrayStrategy: function (strategy) {
    (invariant(strategy === undefined || strategy in mergeHelpers.ArrayStrategies));
  },
  /**
   * Set of possible behaviors of merge algorithms when encountering two Arrays
   * that must be merged together.
   * - `clobber`: The left `Array` is ignored.
   * - `indexByIndex`: The result is achieved by recursively deep merging at
   *   each index. (not yet supported.)
   */
  ArrayStrategies: keyMirror({
    Clobber: true,
    IndexByIndex: true
  })
};
export default = mergeHelpers;
src/react-es6/lib/mergeInto.js
New file
@@ -0,0 +1,45 @@
/**
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @providesModule mergeInto
 * @typechecks static-only
 */
"use strict";
import mergeHelpers from "./mergeHelpers";
var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg;
/**
 * Shallow merges two structures by mutating the first parameter.
 *
 * @param {object} one Object to be merged into.
 * @param {?object} two Optional object with properties to merge from.
 */
function mergeInto (one, two) {
  checkMergeObjectArg(one);
  if (two != null) {
    checkMergeObjectArg(two);
    for (var key in two) {
      if (!two.hasOwnProperty(key)) {
        continue;
      }
      one[key] = two[key];
    }
  }
}
export default = mergeInto;
test/DateTimePickerHoursSpec.jsx
New file
@@ -0,0 +1,19 @@
/** @jsx React.DOM */
/* global describe, beforeEach, afterEach, it, assert */
var DateTimePickerHours, React, ReactTestUtils;
React = require('react');
ReactTestUtils = require('react/lib/ReactTestUtils');
DateTimePickerHours = require('../cjs/DateTimePickerHours');
describe('DateTimePickerHours', function() {
  return it('Should have a timepicker-hours class', function() {
    var instance;
    instance = ReactTestUtils.renderIntoDocument(DateTimePickerHours());
    return assert.ok(instance.getDOMNode().className.match(/\btimepicker-hours\b/));
  });
});
test/coffee/DateTimePickerHoursSpec.jsx.coffee
New file
@@ -0,0 +1,12 @@
###* @jsx React.DOM ###
### global describe, beforeEach, afterEach, it, assert ###
React = require('react')
ReactTestUtils = require('react/lib/ReactTestUtils')
DateTimePickerHours = require('../cjs/DateTimePickerHours')
describe 'DateTimePickerHours', ->
  it 'Should have a timepicker-hours class', ->
    instance = ReactTestUtils.renderIntoDocument(DateTimePickerHours())
    assert.ok(instance.getDOMNode().className.match(/\btimepicker-hours\b/))