react-numeric-input
Version:
Number input component that can replace the native number input which is not yet very well supported and where it is, it does not have the same appearance across the browsers. Additionally this component offers more flexible options and can be used for an
1,280 lines (1,080 loc) • 47.5 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("React"), require("PropTypes"));
else if(typeof define === 'function' && define.amd)
define(["React", "PropTypes"], factory);
else if(typeof exports === 'object')
exports["NumericInput"] = factory(require("React"), require("PropTypes"));
else
root["NumericInput"] = factory(root["React"], root["PropTypes"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_2__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _react = __webpack_require__(1);
var _react2 = _interopRequireDefault(_react);
var _propTypes = __webpack_require__(2);
var _propTypes2 = _interopRequireDefault(_propTypes);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var KEYCODE_UP = 38;
var KEYCODE_DOWN = 40;
var IS_BROWSER = typeof document != 'undefined';
var RE_NUMBER = /^[+-]?((\.\d+)|(\d+(\.\d+)?))$/;
var RE_INCOMPLETE_NUMBER = /^([+-]|\.0*|[+-]\.0*|[+-]?\d+\.)?$/;
/**
* Just a simple helper to provide support for older IEs. This is not exactly a
* polyfill for classList.add but it does what we need with minimal effort.
* Works with single className only!
*/
function addClass(element, className) {
if (element.classList) {
return element.classList.add(className);
}
if (!element.className.search(new RegExp("\\b" + className + "\\b"))) {
element.className = " " + className;
}
}
/**
* Just a simple helper to provide support for older IEs. This is not exactly a
* polyfill for classList.remove but it does what we need with minimal effort.
* Works with single className only!
*/
function removeClass(element, className) {
if (element.className) {
if (element.classList) {
return element.classList.remove(className);
}
element.className = element.className.replace(new RegExp("\\b" + className + "\\b", "g"), "");
}
}
/**
* Lookup the object.prop and returns it. If it happens to be a function,
* executes it with args and returns it's return value. It the prop does not
* exist on the object, or if it equals undefined, or if it is a function that
* returns undefined the defaultValue will be returned instead.
* @param {Object} object The object to look into
* @param {String} prop The property name
* @param {*} defaultValue The default value
* @param {*[]} args Any additional arguments to pass to the
* function (if the prop is a function).
* @return {*} Whatever happens to be the return value
*/
function access(object, prop, defaultValue) {
var result = object[prop];
if (typeof result == "function") {
for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
args[_key - 3] = arguments[_key];
}
result = result.apply(undefined, args);
}
return result === undefined ? defaultValue : result;
}
/* eslint-disable */
/*eslint-enable*/
var NumericInput = function (_Component) {
_inherits(NumericInput, _Component);
/**
* Set the initial state and bind this.stop to the instance.
*/
/**
* The step timer
* @type {Number}
*/
/**
* This holds the last known validation error. We need to compare that with
* new errors and detect validation changes...
* @type {[type]}
*/
/**
* The state of the component
* @type {Object}
*/
/**
* The stop method (need to declare it here to use it in the constructor)
* @type {Function}
*/
/**
* The constant indicating up direction (or increasing in general)
*/
/**
* When click and hold on a button - the speed of auto changing the value.
* This is a static property and can be modified if needed.
*/
/**
* The default behavior is to start from 0, use step of 1 and display
* integers
*/
function NumericInput() {
var _ref;
_classCallCheck(this, NumericInput);
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var _this = _possibleConstructorReturn(this, (_ref = NumericInput.__proto__ || Object.getPrototypeOf(NumericInput)).call.apply(_ref, [this].concat(args)));
_this._isStrict = !!_this.props.strict;
_this.state = _extends({
btnDownHover: false,
btnDownActive: false,
btnUpHover: false,
btnUpActive: false,
stringValue: ""
}, _this._propsToState(_this.props));
_this.stop = _this.stop.bind(_this);
_this.onTouchEnd = _this.onTouchEnd.bind(_this);
_this.refsInput = {};
_this.refsWrapper = {};
return _this;
}
/**
* The constant indicating down direction (or decreasing in general)
*/
/**
* When click and hold on a button - the delay before auto changing the value.
* This is a static property and can be modified if needed.
*/
/**
* This are the default styles that act as base for all the component
* instances. One can modify this object to change the default styles
* of all the widgets on the page.
*/
_createClass(NumericInput, [{
key: '_propsToState',
value: function _propsToState(props) {
var out = {};
if (props.hasOwnProperty("value")) {
out.stringValue = String(props.value || props.value === 0 ? props.value : '').trim();
out.value = out.stringValue !== '' ? this._parse(props.value) : null;
} else if (!this._isMounted && props.hasOwnProperty("defaultValue")) {
out.stringValue = String(props.defaultValue || props.defaultValue === 0 ? props.defaultValue : '').trim();
out.value = props.defaultValue !== '' ? this._parse(props.defaultValue) : null;
}
return out;
}
/**
* Special care is taken for the "value" prop:
* - If not provided - set it to null
* - If the prop is a number - use it as is
* - Otherwise:
* 1. Convert it to string (falsy values become "")
* 2. Then trim it.
* 3. Then parse it to number (delegating to this.props.parse if any)
*/
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(props) {
var _this2 = this;
this._isStrict = !!props.strict;
var nextState = this._propsToState(props);
if (Object.keys(nextState).length) {
this._ignoreValueChange = true;
this.setState(nextState, function () {
_this2._ignoreValueChange = false;
});
}
}
/**
* Save the input selection right before rendering
*/
}, {
key: 'componentWillUpdate',
value: function componentWillUpdate() {
this.saveSelection();
}
/**
* After the component has been rendered into the DOM, do whatever is
* needed to "reconnect" it to the outer world, i.e. restore selection,
* call some of the callbacks, validate etc.
*/
}, {
key: 'componentDidUpdate',
value: function componentDidUpdate(prevProps, prevState) {
// Call the onChange if needed. This is placed here because there are
// many reasons for changing the value and this is the common place
// that can capture them all
if (!this._ignoreValueChange // no onChange if re-rendered with different value prop
&& prevState.value !== this.state.value // no onChange if the value remains the same
&& (!isNaN(this.state.value) || this.state.value === null) // only if changing to number or null
) {
this._invokeEventCallback("onChange", this.state.value, this.refsInput.value, this.refsInput);
}
// focus the input is needed (for example up/down buttons set
// this._inputFocus to true)
if (this._inputFocus) {
this.refsInput.focus();
// Restore selectionStart (if any)
if (this.state.selectionStart || this.state.selectionStart === 0) {
this.refsInput.selectionStart = this.state.selectionStart;
}
// Restore selectionEnd (if any)
if (this.state.selectionEnd || this.state.selectionEnd === 0) {
this.refsInput.selectionEnd = this.state.selectionEnd;
}
}
this.checkValidity();
}
/**
* This is used to clear the timer if any
*/
}, {
key: 'componentWillUnmount',
value: function componentWillUnmount() {
this._isMounted = false;
this.stop();
}
/**
* Adds getValueAsNumber and setValue methods to the input DOM element.
*/
}, {
key: 'componentDidMount',
value: function componentDidMount() {
var _this3 = this;
this._isMounted = true;
this.refsInput.getValueAsNumber = function () {
return _this3.state.value || 0;
};
this.refsInput.setValue = function (value) {
_this3.setState({
value: _this3._parse(value),
stringValue: value
});
};
// This is a special case! If the component has the "autoFocus" prop
// and the browser did focus it we have to pass that to the onFocus
if (!this._inputFocus && IS_BROWSER && document.activeElement === this.refsInput) {
this._inputFocus = true;
this.refsInput.focus();
this._invokeEventCallback("onFocus", {
target: this.refsInput,
type: "focus"
});
}
this.checkValidity();
}
/**
* Saves the input selection in the state so that it can be restored after
* updates
*/
}, {
key: 'saveSelection',
value: function saveSelection() {
this.state.selectionStart = this.refsInput.selectionStart;
this.state.selectionEnd = this.refsInput.selectionEnd;
}
/**
* Unless noValidate is set to true, the component will check the
* existing validation state (if any) and will toggle the "has-error"
* CSS class on the wrapper
*/
}, {
key: 'checkValidity',
value: function checkValidity() {
var valid = void 0,
validationError = "";
var supportsValidation = !!this.refsInput.checkValidity;
// noValidate
var noValidate = !!(this.props.noValidate && this.props.noValidate != "false");
this.refsInput.noValidate = noValidate;
// If "noValidate" is set or "checkValidity" is not supported then
// consider the element valid. Otherwise consider it invalid and
// make some additional checks below
valid = noValidate || !supportsValidation;
if (valid) {
validationError = "";
} else {
// In some browsers once a pattern is set it cannot be removed. The
// browser sets it to "" instead which results in validation
// failures...
if (this.refsInput.pattern === "") {
this.refsInput.pattern = this.props.required ? ".+" : ".*";
}
// Now check validity
if (supportsValidation) {
this.refsInput.checkValidity();
valid = this.refsInput.validity.valid;
if (!valid) {
validationError = this.refsInput.validationMessage;
}
}
// Some browsers might fail to validate maxLength
if (valid && supportsValidation && this.props.maxLength) {
if (this.refsInput.value.length > this.props.maxLength) {
validationError = "This value is too long";
}
}
}
validationError = validationError || (valid ? "" : this.refsInput.validationMessage || "Unknown Error");
var validStateChanged = this._valid !== validationError;
this._valid = validationError;
if (validationError) {
addClass(this.refsWrapper, "has-error");
if (validStateChanged) {
this._invokeEventCallback("onInvalid", validationError, this.state.value, this.refsInput.value);
}
} else {
removeClass(this.refsWrapper, "has-error");
if (validStateChanged) {
this._invokeEventCallback("onValid", this.state.value, this.refsInput.value);
}
}
}
/**
* Used internally to parse the argument x to it's numeric representation.
* If the argument cannot be converted to finite number returns 0; If a
* "precision" prop is specified uses it round the number with that
* precision (no fixed precision here because the return value is float, not
* string).
*/
}, {
key: '_toNumber',
value: function _toNumber(x) {
var n = parseFloat(x);
if (isNaN(n) || !isFinite(n)) {
n = 0;
}
if (this._isStrict) {
var precision = access(this.props, "precision", null, this);
var q = Math.pow(10, precision === null ? 10 : precision);
var _min = +access(this.props, "min", NumericInput.defaultProps.min, this);
var _max = +access(this.props, "max", NumericInput.defaultProps.max, this);
n = Math.min(Math.max(n, _min), _max);
n = Math.round(n * q) / q;
}
return n;
}
/**
* This is used internally to parse any string into a number. It will
* delegate to this.props.parse function if one is provided. Otherwise it
* will just use parseFloat.
* @private
*/
}, {
key: '_parse',
value: function _parse(x) {
x = String(x);
if (typeof this.props.parse == 'function') {
return parseFloat(this.props.parse(x));
}
return parseFloat(x);
}
/**
* This is used internally to format a number to it's display representation.
* It will invoke the this.props.format function if one is provided.
* @private
*/
}, {
key: '_format',
value: function _format(n) {
var _n = this._toNumber(n);
var precision = access(this.props, "precision", null, this);
if (precision !== null) {
_n = n.toFixed(precision);
}
_n += "";
if (this.props.format) {
return this.props.format(_n);
}
return _n;
}
/**
* The internal method that actually sets the new value on the input
* @private
*/
}, {
key: '_step',
value: function _step(n, callback) {
var _isStrict = this._isStrict;
this._isStrict = true;
var _step = +access(this.props, "step", NumericInput.defaultProps.step, this, n > 0 ? NumericInput.DIRECTION_UP : NumericInput.DIRECTION_DOWN);
var _n = this._toNumber((this.state.value || 0) + _step * n);
if (this.props.snap) {
_n = Math.round(_n / _step) * _step;
}
this._isStrict = _isStrict;
if (_n !== this.state.value) {
this.setState({ value: _n, stringValue: _n + "" }, callback);
return true;
}
return false;
}
/**
* This binds the Up/Down arrow key listeners
*/
}, {
key: '_onKeyDown',
value: function _onKeyDown() {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
args[0].persist();
this._invokeEventCallback.apply(this, ["onKeyDown"].concat(args));
var e = args[0];
if (!e.isDefaultPrevented()) {
if (e.keyCode === KEYCODE_UP) {
e.preventDefault();
this._step(e.ctrlKey || e.metaKey ? 0.1 : e.shiftKey ? 10 : 1);
} else if (e.keyCode === KEYCODE_DOWN) {
e.preventDefault();
this._step(e.ctrlKey || e.metaKey ? -0.1 : e.shiftKey ? -10 : -1);
} else {
var _value = this.refsInput.value,
length = _value.length;
if (e.keyCode === 8) {
// backspace
if (this.refsInput.selectionStart == this.refsInput.selectionEnd && this.refsInput.selectionEnd > 0 && _value.length && _value.charAt(this.refsInput.selectionEnd - 1) === ".") {
e.preventDefault();
this.refsInput.selectionStart = this.refsInput.selectionEnd = this.refsInput.selectionEnd - 1;
}
} else if (e.keyCode === 46) {
// delete
if (this.refsInput.selectionStart == this.refsInput.selectionEnd && this.refsInput.selectionEnd < length + 1 && _value.length && _value.charAt(this.refsInput.selectionEnd) === ".") {
e.preventDefault();
this.refsInput.selectionStart = this.refsInput.selectionEnd = this.refsInput.selectionEnd + 1;
}
}
}
}
}
/**
* Stops the widget from auto-changing by clearing the timer (if any)
*/
}, {
key: 'stop',
value: function stop() {
if (this._timer) {
clearTimeout(this._timer);
}
}
/**
* Increments the value with one step and the enters a recursive calls
* after DELAY. This is bound to the mousedown event on the "up" button
* and will be stopped on mouseout/mouseup.
* @param {Boolean} _recursive The method is passing this to itself while
* it is in recursive mode.
* @return void
*/
}, {
key: 'increase',
value: function increase() {
var _this4 = this;
var _recursive = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var callback = arguments[1];
this.stop();
this._step(1, callback);
var _max = +access(this.props, "max", NumericInput.defaultProps.max, this);
if (isNaN(this.state.value) || +this.state.value < _max) {
this._timer = setTimeout(function () {
_this4.increase(true);
}, _recursive ? NumericInput.SPEED : NumericInput.DELAY);
}
}
/**
* Decrements the value with one step and the enters a recursive calls
* after DELAY. This is bound to the mousedown event on the "down" button
* and will be stopped on mouseout/mouseup.
* @param {Boolean} _recursive The method is passing this to itself while
* it is in recursive mode.
* @return void
*/
}, {
key: 'decrease',
value: function decrease() {
var _this5 = this;
var _recursive = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var callback = arguments[1];
this.stop();
this._step(-1, callback);
var _min = +access(this.props, "min", NumericInput.defaultProps.min, this);
if (isNaN(this.state.value) || +this.state.value > _min) {
this._timer = setTimeout(function () {
_this5.decrease(true);
}, _recursive ? NumericInput.SPEED : NumericInput.DELAY);
}
}
/**
* Handles the mousedown event on the up/down buttons. Changes The
* internal value and sets up a delay for auto increment/decrement
* (until mouseup or mouseleave)
*/
}, {
key: 'onMouseDown',
value: function onMouseDown(dir, callback) {
if (dir == 'down') {
this.decrease(false, callback);
} else if (dir == 'up') {
this.increase(false, callback);
}
}
/**
* Handles the touchstart event on the up/down buttons. Changes The
* internal value and DOES NOT sets up a delay for auto increment/decrement.
* Note that this calls e.preventDefault() so the event is not used for
* creating a virtual mousedown after it
*/
}, {
key: 'onTouchStart',
value: function onTouchStart(dir, e) {
e.preventDefault();
if (dir == 'down') {
this.decrease();
} else if (dir == 'up') {
this.increase();
}
}
}, {
key: 'onTouchEnd',
value: function onTouchEnd(e) {
e.preventDefault();
this.stop();
}
/**
* Helper method to invoke event callback functions if they are provided
* in the props.
* @param {String} callbackName The name of the function prop
* @param {*[]} args Any additional argument are passed thru
*/
}, {
key: '_invokeEventCallback',
value: function _invokeEventCallback(callbackName) {
if (typeof this.props[callbackName] == "function") {
var _props$callbackName;
for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
args[_key4 - 1] = arguments[_key4];
}
(_props$callbackName = this.props[callbackName]).call.apply(_props$callbackName, [null].concat(args));
}
}
/**
* Renders an input wrapped in relative span and up/down buttons
* @return {Component}
*/
}, {
key: 'render',
value: function render() {
var _this6 = this;
var props = this.props;
var state = this.state;
var css = {};
var _props = this.props,
step = _props.step,
min = _props.min,
max = _props.max,
precision = _props.precision,
parse = _props.parse,
format = _props.format,
mobile = _props.mobile,
snap = _props.snap,
componentClass = _props.componentClass,
value = _props.value,
type = _props.type,
style = _props.style,
defaultValue = _props.defaultValue,
onInvalid = _props.onInvalid,
onValid = _props.onValid,
strict = _props.strict,
noStyle = _props.noStyle,
rest = _objectWithoutProperties(_props, ['step', 'min', 'max', 'precision', 'parse', 'format', 'mobile', 'snap', 'componentClass', 'value', 'type', 'style', 'defaultValue', 'onInvalid', 'onValid', 'strict', 'noStyle']);
noStyle = noStyle || style === false;
// Build the styles
for (var x in NumericInput.style) {
css[x] = _extends({}, NumericInput.style[x], style ? style[x] || {} : {});
}
var hasFormControl = props.className && /\bform-control\b/.test(props.className);
if (mobile == 'auto') {
mobile = IS_BROWSER && 'ontouchstart' in document;
}
if (typeof mobile == "function") {
mobile = mobile.call(this);
}
mobile = !!mobile;
var attrs = {
wrap: {
style: noStyle ? null : css.wrap,
className: 'react-numeric-input',
ref: function ref(e) {
if (e != null && e != undefined) {
_this6.refsWrapper = e;
}
},
onMouseUp: undefined,
onMouseLeave: undefined
},
input: _extends({
ref: function ref(e) {
if (e != null && e != undefined) {
_this6.refsInput = e;
}
},
type: 'text',
style: noStyle ? null : _extends({}, css.input, !hasFormControl ? css['input:not(.form-control)'] : {}, this._inputFocus ? css['input:focus'] : {})
}, rest),
btnUp: {
onMouseEnter: undefined,
onMouseDown: undefined,
onMouseUp: undefined,
onMouseLeave: undefined,
onTouchStart: undefined,
onTouchEnd: undefined,
style: noStyle ? null : _extends({}, css.btn, css.btnUp, props.disabled || props.readOnly ? css['btn:disabled'] : state.btnUpActive ? css['btn:active'] : state.btnUpHover ? css['btn:hover'] : {})
},
btnDown: {
onMouseEnter: undefined,
onMouseDown: undefined,
onMouseUp: undefined,
onMouseLeave: undefined,
onTouchStart: undefined,
onTouchEnd: undefined,
style: noStyle ? null : _extends({}, css.btn, css.btnDown, props.disabled || props.readOnly ? css['btn:disabled'] : state.btnDownActive ? css['btn:active'] : state.btnDownHover ? css['btn:hover'] : {})
}
};
var stringValue = String(
// if state.stringValue is set and not empty
state.stringValue || (
// else if state.value is set and not null|undefined
state.value || state.value === 0 ? state.value : "") ||
// or finally use ""
"");
var loose = !this._isStrict && (this._inputFocus || !this._isMounted);
// incomplete number
if (loose && RE_INCOMPLETE_NUMBER.test(stringValue)) {
attrs.input.value = stringValue;
}
// Not a number and not empty (loose mode only)
else if (loose && stringValue && !RE_NUMBER.test(stringValue)) {
attrs.input.value = stringValue;
}
// number
else if (state.value || state.value === 0) {
attrs.input.value = this._format(state.value);
}
// empty
else {
attrs.input.value = "";
}
if (hasFormControl && !noStyle) {
_extends(attrs.wrap.style, css['wrap.hasFormControl']);
}
// mobile
if (mobile && !noStyle) {
_extends(attrs.input.style, css['input.mobile']);
_extends(attrs.btnUp.style, css['btnUp.mobile']);
_extends(attrs.btnDown.style, css['btnDown.mobile']);
}
// Attach event listeners if the widget is not disabled
if (!props.disabled && !props.readOnly) {
_extends(attrs.wrap, {
onMouseUp: this.stop,
onMouseLeave: this.stop
});
_extends(attrs.btnUp, {
onTouchStart: this.onTouchStart.bind(this, 'up'),
onTouchEnd: this.onTouchEnd,
onMouseEnter: function onMouseEnter() {
_this6.setState({
btnUpHover: true
});
},
onMouseLeave: function onMouseLeave() {
_this6.stop();
_this6.setState({
btnUpHover: false,
btnUpActive: false
});
},
onMouseUp: function onMouseUp() {
_this6.setState({
btnUpHover: true,
btnUpActive: false
});
},
onMouseDown: function onMouseDown() {
for (var _len5 = arguments.length, args = Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
args[_key5] = arguments[_key5];
}
args[0].preventDefault();
args[0].persist();
_this6._inputFocus = true;
_this6.setState({
btnUpHover: true,
btnUpActive: true
}, function () {
_this6._invokeEventCallback.apply(_this6, ["onFocus"].concat(args));
_this6.onMouseDown('up');
});
}
});
_extends(attrs.btnDown, {
onTouchStart: this.onTouchStart.bind(this, 'down'),
onTouchEnd: this.onTouchEnd,
onMouseEnter: function onMouseEnter() {
_this6.setState({
btnDownHover: true
});
},
onMouseLeave: function onMouseLeave() {
_this6.stop();
_this6.setState({
btnDownHover: false,
btnDownActive: false
});
},
onMouseUp: function onMouseUp() {
_this6.setState({
btnDownHover: true,
btnDownActive: false
});
},
onMouseDown: function onMouseDown() {
for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
args[_key6] = arguments[_key6];
}
args[0].preventDefault();
args[0].persist();
_this6._inputFocus = true;
_this6.setState({
btnDownHover: true,
btnDownActive: true
}, function () {
_this6._invokeEventCallback.apply(_this6, ["onFocus"].concat(args));
_this6.onMouseDown('down');
});
}
});
_extends(attrs.input, {
onChange: function onChange(e) {
var original = e.target.value;
var val = _this6._parse(original);
if (isNaN(val)) {
val = null;
}
_this6.setState({
value: _this6._isStrict ? _this6._toNumber(val) : val,
stringValue: original
});
},
onKeyDown: this._onKeyDown.bind(this),
onInput: function onInput() {
for (var _len7 = arguments.length, args = Array(_len7), _key7 = 0; _key7 < _len7; _key7++) {
args[_key7] = arguments[_key7];
}
_this6.saveSelection();
_this6._invokeEventCallback.apply(_this6, ["onInput"].concat(args));
},
onSelect: function onSelect() {
for (var _len8 = arguments.length, args = Array(_len8), _key8 = 0; _key8 < _len8; _key8++) {
args[_key8] = arguments[_key8];
}
_this6.saveSelection();
_this6._invokeEventCallback.apply(_this6, ["onSelect"].concat(args));
},
onFocus: function onFocus() {
for (var _len9 = arguments.length, args = Array(_len9), _key9 = 0; _key9 < _len9; _key9++) {
args[_key9] = arguments[_key9];
}
args[0].persist();
_this6._inputFocus = true;
var val = _this6._parse(args[0].target.value);
_this6.setState({
value: val,
stringValue: val || val === 0 ? val + "" : ""
}, function () {
_this6._invokeEventCallback.apply(_this6, ["onFocus"].concat(args));
});
},
onBlur: function onBlur() {
for (var _len10 = arguments.length, args = Array(_len10), _key10 = 0; _key10 < _len10; _key10++) {
args[_key10] = arguments[_key10];
}
var _isStrict = _this6._isStrict;
_this6._isStrict = true;
args[0].persist();
_this6._inputFocus = false;
var val = _this6._parse(args[0].target.value);
_this6.setState({
value: val
}, function () {
_this6._invokeEventCallback.apply(_this6, ["onBlur"].concat(args));
_this6._isStrict = _isStrict;
});
}
});
} else {
if (!noStyle && props.disabled) {
_extends(attrs.input.style, css['input:disabled']);
}
}
var InputTag = componentClass || 'input';
if (mobile) {
return _react2.default.createElement(
'span',
attrs.wrap,
_react2.default.createElement(InputTag, attrs.input),
_react2.default.createElement(
'b',
attrs.btnUp,
_react2.default.createElement('i', { style: noStyle ? null : css.minus }),
_react2.default.createElement('i', { style: noStyle ? null : css.plus })
),
_react2.default.createElement(
'b',
attrs.btnDown,
_react2.default.createElement('i', { style: noStyle ? null : css.minus })
)
);
}
return _react2.default.createElement(
'span',
attrs.wrap,
_react2.default.createElement(InputTag, attrs.input),
_react2.default.createElement(
'b',
attrs.btnUp,
_react2.default.createElement('i', { style: noStyle ? null : css.arrowUp })
),
_react2.default.createElement(
'b',
attrs.btnDown,
_react2.default.createElement('i', { style: noStyle ? null : css.arrowDown })
)
);
}
}]);
return NumericInput;
}(_react.Component);
NumericInput.propTypes = {
step: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
min: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
max: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
precision: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
maxLength: _propTypes2.default.number,
parse: _propTypes2.default.func,
format: _propTypes2.default.func,
className: _propTypes2.default.string,
disabled: _propTypes2.default.bool,
readOnly: _propTypes2.default.bool,
required: _propTypes2.default.bool,
snap: _propTypes2.default.bool,
noValidate: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.string]),
style: _propTypes2.default.oneOfType([_propTypes2.default.object, _propTypes2.default.bool]),
noStyle: _propTypes2.default.bool,
type: _propTypes2.default.string,
pattern: _propTypes2.default.string,
onFocus: _propTypes2.default.func,
onBlur: _propTypes2.default.func,
onKeyDown: _propTypes2.default.func,
onChange: _propTypes2.default.func,
onInvalid: _propTypes2.default.func,
onValid: _propTypes2.default.func,
onInput: _propTypes2.default.func,
onSelect: _propTypes2.default.func,
size: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
value: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
defaultValue: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]),
strict: _propTypes2.default.bool,
componentClass: _propTypes2.default.string,
mobile: function mobile(props, propName) {
var prop = props[propName];
if (prop !== true && prop !== false && prop !== 'auto' && typeof prop != 'function') {
return new Error('The "mobile" prop must be true, false, "auto" or a function');
}
}
};
NumericInput.defaultProps = {
step: 1,
min: Number.MIN_SAFE_INTEGER || -9007199254740991,
max: Number.MAX_SAFE_INTEGER || 9007199254740991,
precision: null,
parse: null,
format: null,
mobile: 'auto',
strict: false,
componentClass: "input",
style: {}
};
NumericInput.style = {
// The wrapper (span)
wrap: {
position: 'relative',
display: 'inline-block'
},
'wrap.hasFormControl': {
display: 'block'
},
// The increase button arrow (i)
arrowUp: {
position: 'absolute',
top: '50%',
left: '50%',
width: 0,
height: 0,
borderWidth: '0 0.6ex 0.6ex 0.6ex',
borderColor: 'transparent transparent rgba(0, 0, 0, 0.7)',
borderStyle: 'solid',
margin: '-0.3ex 0 0 -0.56ex'
},
// The decrease button arrow (i)
arrowDown: {
position: 'absolute',
top: '50%',
left: '50%',
width: 0,
height: 0,
borderWidth: '0.6ex 0.6ex 0 0.6ex',
borderColor: 'rgba(0, 0, 0, 0.7) transparent transparent',
borderStyle: 'solid',
margin: '-0.3ex 0 0 -0.56ex'
},
// The vertical segment of the plus sign (for mobile only)
plus: {
position: 'absolute',
top: '50%',
left: '50%',
width: 2,
height: 10,
background: 'rgba(0,0,0,.7)',
margin: '-5px 0 0 -1px'
},
// The horizontal segment of the plus/minus signs (for mobile only)
minus: {
position: 'absolute',
top: '50%',
left: '50%',
width: 10,
height: 2,
background: 'rgba(0,0,0,.7)',
margin: '-1px 0 0 -5px'
},
// Common styles for the up/down buttons (b)
btn: {
position: 'absolute',
right: 2,
width: '2.26ex',
borderColor: 'rgba(0,0,0,.1)',
borderStyle: 'solid',
textAlign: 'center',
cursor: 'default',
transition: 'all 0.1s',
background: 'rgba(0,0,0,.1)',
boxShadow: '-1px -1px 3px rgba(0,0,0,.1) inset,' + '1px 1px 3px rgba(255,255,255,.7) inset'
},
btnUp: {
top: 2,
bottom: '50%',
borderRadius: '2px 2px 0 0',
borderWidth: '1px 1px 0 1px'
},
'btnUp.mobile': {
width: '3.3ex',
bottom: 2,
boxShadow: 'none',
borderRadius: 2,
borderWidth: 1
},
btnDown: {
top: '50%',
bottom: 2,
borderRadius: '0 0 2px 2px',
borderWidth: '0 1px 1px 1px'
},
'btnDown.mobile': {
width: '3.3ex',
bottom: 2,
left: 2,
top: 2,
right: 'auto',
boxShadow: 'none',
borderRadius: 2,
borderWidth: 1
},
'btn:hover': {
background: 'rgba(0,0,0,.2)'
},
'btn:active': {
background: 'rgba(0,0,0,.3)',
boxShadow: '0 1px 3px rgba(0,0,0,.2) inset,' + '-1px -1px 4px rgba(255,255,255,.5) inset'
},
'btn:disabled': {
opacity: 0.5,
boxShadow: 'none',
cursor: 'not-allowed'
},
// The input (input[type="text"])
input: {
paddingRight: '3ex',
boxSizing: 'border-box',
fontSize: 'inherit'
},
// The input with bootstrap class
'input:not(.form-control)': {
border: '1px solid #ccc',
borderRadius: 2,
paddingLeft: 4,
display: 'block',
WebkitAppearance: 'none',
lineHeight: 'normal'
},
'input.mobile': {
paddingLeft: ' 3.4ex',
paddingRight: '3.4ex',
textAlign: 'center'
},
'input:focus': {},
'input:disabled': {
color: 'rgba(0, 0, 0, 0.3)',
textShadow: '0 1px 0 rgba(255, 255, 255, 0.8)'
}
};
NumericInput.SPEED = 50;
NumericInput.DELAY = 500;
NumericInput.DIRECTION_UP = "up";
NumericInput.DIRECTION_DOWN = "down";
module.exports = NumericInput;
/***/ }),
/* 1 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
/***/ }),
/* 2 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
/***/ })
/******/ ])
});
;