diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..d065274 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "es2016", "react"] +} diff --git a/.esdoc.json b/.esdoc.json new file mode 100644 index 0000000..48d6315 --- /dev/null +++ b/.esdoc.json @@ -0,0 +1,17 @@ +{ + "source": "./src", + "destination": "./doc", + "plugins": [ + { + "name": "esdoc-importpath-plugin", + "option": { + "replaces": [ + { + "from": "^src/js/", + "to": "" + } + ] + } + } + ] +} diff --git a/.eslintrc b/.eslintrc index 916c105..3a4ba11 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,23 +1,47 @@ rules: + class-methods-use-this: + - 1 indent: - 2 - 2 + import/extensions: + - 0 + import/no-extraneous-dependencies: + - 0 + import/prefer-default-export: + - 1 + no-plusplus: + - 2 + - allowForLoopAfterthoughts: true + no-underscore-dangle: + - 0 quotes: - 2 - single semi: - 2 - always + jsx-a11y/anchor-has-content: + - 1 react/jsx-boolean-value: + - 1 + jsx-a11y/href-no-hash: + - 1 + jsx-a11y/no-static-element-interactions: + - 0 + react/jsx-curly-spacing: - 2 - always - react/sort-comp: - - 2 - - order - - lifecycle - - /^on.+$/ - - render - - everything-else + react/jsx-closing-bracket-location: + - 0 + react/jsx-filename-extension: + - 0 + react/no-unused-prop-types: + - 1 + react/no-string-refs: + - 1 + react/require-default-props: + - 0 env: es6: true browser: true diff --git a/.gitignore b/.gitignore index 5b0e61e..49c895f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,6 @@ -.DS_Store *.log -/bower_components -/build -/coverage -/example/build -/lib -/node_modules -/out +build +coverage +doc +lib +node_modules diff --git a/.npmignore b/.npmignore index 4a29469..a76a2ff 100644 --- a/.npmignore +++ b/.npmignore @@ -1,11 +1,11 @@ +*.conf.js +*.config.js +*.log **/.* -bower.json build +coverage +doc example -Gemfile* -gulpfile.babel.js -karma.conf.js node_modules src -tasks test diff --git a/.sass-lint.yml b/.sass-lint.yml new file mode 100644 index 0000000..861b958 --- /dev/null +++ b/.sass-lint.yml @@ -0,0 +1,35 @@ +files: + include: './src/scss/**/*.scss' +options: + formatter: stylish +rules: + class-name-format: &class-name-format + - 2 + - convention: ^(([A-Z][a-z]*)+$|(([A-Z][a-z]*)+|u|is|js)(-|--)([a-z]+([a-z]|[A-Z])*)+|(([A-Z][a-z]*)+|u|is|js)(-|--)([a-z]+([a-z]|[A-Z])*)+(--[a-z]+([a-z]|[A-Z])*)+)|[ng]-(\w)+(-(\w)*)*$ + empty-line-between-blocks: + - 2 + - ignore-single-line-rulesets: false + force-attribute-nesting: 0 + force-element-nesting: 0 + force-pseudo-nesting: 0 + function-name-format: 2 + hex-length: + - 2 + - style: long + indentation: + - 2 + - size: 2 + leading-zero: + - 2 + - include: true + mixin-name-format: 1 + nesting-depth: + - 2 + - max-depth: 2 + no-ids: 2 + no-important: 2 + placeholder-name-format: *class-name-format + quotes: + - 2 + - style: single + variable-name-format: *class-name-format diff --git a/.scss-lint.yml b/.scss-lint.yml deleted file mode 100644 index f3eb4fe..0000000 --- a/.scss-lint.yml +++ /dev/null @@ -1,167 +0,0 @@ -linters: - BangFormat: - enabled: true - space_before_bang: true - space_after_bang: false - - BorderZero: - enabled: true - - ColorKeyword: - enabled: false - - Comment: - enabled: false - - Compass::*: - enabled: false - - DebugStatement: - enabled: true - - DeclarationOrder: - enabled: true - - DuplicateProperty: - enabled: true - - ElsePlacement: - enabled: true - style: same_line - - EmptyLineBetweenBlocks: - enabled: false - ignore_single_line_blocks: true - - EmptyRule: - enabled: true - - FinalNewline: - enabled: true - present: true - - HexLength: - enabled: true - style: long - - HexNotation: - enabled: true - style: lowercase - - HexValidation: - enabled: true - - IdWithExtraneousSelector: - enabled: true - - ImportPath: - enabled: true - leading_underscore: false - filename_extension: false - - Indentation: - enabled: true - character: space - width: 2 - - LeadingZero: - enabled: true - style: include_zero - - MergeableSelector: - enabled: true - force_nesting: true - - NameFormat: - enabled: false - - NestingDepth: - enabled: true - max_depth: 2 - - PlaceholderInExtend: - enabled: false - - PropertySortOrder: - enabled: true - ignore_unspecified: false - - PropertySpelling: - enabled: true - extra_properties: [] - - QualifyingElement: - enabled: true - allow_with_attribute: false - allow_with_class: false - allow_with_id: false - - SelectorDepth: - enabled: true - max_depth: 3 - - SelectorFormat: - enabled: true - convention: ^(([A-Z][a-z]*)+$|(([A-Z][a-z]*)+|u|is|js)(-|--)([a-z]+([a-z]|[A-Z])*)+|(([A-Z][a-z]*)+|u|is|js)(-|--)([a-z]+([a-z]|[A-Z])*)+(--[a-z]+([a-z]|[A-Z])*)+)|[ng]-(\w)+(-(\w)*)*$ - ignored_names: ["better-timeinput"] - ignored_types: ["attribute", "element", "pseudo-selector"] - - Shorthand: - enabled: true - - SingleLinePerProperty: - enabled: true - allow_single_line_rule_sets: true - - SingleLinePerSelector: - enabled: true - - SpaceAfterComma: - enabled: true - - SpaceAfterPropertyColon: - enabled: true - style: one_space - - SpaceAfterPropertyName: - enabled: true - - SpaceBeforeBrace: - enabled: true - style: space - allow_single_line_padding: false - - SpaceBetweenParens: - enabled: true - spaces: 0 - - StringQuotes: - enabled: true - style: double_quotes - - TrailingSemicolon: - enabled: true - - TrailingZero: - enabled: false - - UnnecessaryMantissa: - enabled: true - - UnnecessaryParentReference: - enabled: true - - UrlFormat: - enabled: true - - UrlQuotes: - enabled: true - - VendorPrefixes: - enabled: true - identifier_list: base - include: [] - exclude: [] - - ZeroUnit: - enabled: true diff --git a/Gemfile b/Gemfile deleted file mode 100644 index 4ddf3a0..0000000 --- a/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source 'https://rubygems.org' - -gem 'scss_lint', '~> 0.41.0' diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 1761ed6..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,14 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - rainbow (2.0.0) - sass (3.4.18) - scss_lint (0.41.0) - rainbow (~> 2.0) - sass (~> 3.4.15) - -PLATFORMS - ruby - -DEPENDENCIES - scss_lint (~> 0.41.0) diff --git a/README.md b/README.md index 08b4004..e60e52f 100644 --- a/README.md +++ b/README.md @@ -90,12 +90,12 @@ value |number | Object.<number> |Current value(s) ( If you want to work on this project locally, you need to grab all of its dependencies. ``` -npm install && bundle install +npm install ``` After that, you should be able run ``` -npm start +npm run dev ``` Contributions are welcome. :) diff --git a/bower.json b/bower.json deleted file mode 100644 index 9523fc4..0000000 --- a/bower.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "react-input-range", - "main": [ - "dist/react-input-range.js", - "dist/react-input-range.css" - ], - "version": "0.10.0", - "description": "React component for inputting numeric values within a range", - "homepage": "https://github.com/davidchin/react-input-range", - "authors": [ - "davidchin " - ], - "keywords": [ - "react", - "react-component", - "range-slider", - "input-range", - "range", - "slider", - "form", - "input" - ], - "license": "MIT", - "moduleType": [ - "amd", - "globals", - "node", - "es6" - ], - "ignore": [ - "**/.*", - "build", - "example", - "Gemfile*", - "gulpfile.babel.js", - "karma.conf.js", - "lib", - "node_modules", - "package.json", - "scss", - "src", - "tasks", - "test" - ] -} diff --git a/dist/react-input-range.css b/dist/react-input-range.css deleted file mode 100644 index 4b38ee1..0000000 --- a/dist/react-input-range.css +++ /dev/null @@ -1,82 +0,0 @@ -.InputRange-slider { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background: #3f51b5; - border: 1px solid #3f51b5; - border-radius: 100%; - cursor: pointer; - display: block; - height: 1rem; - margin-left: -0.5rem; - margin-top: -0.65rem; - outline: none; - position: absolute; - top: 50%; - transition: transform 0.3s ease-out, box-shadow 0.3s ease-out; - width: 1rem; } - .InputRange-slider:active { - transform: scale(1.3); } - .InputRange-slider:focus { - box-shadow: 0 0 0 5px rgba(63, 81, 181, 0.2); } - .InputRange.is-disabled .InputRange-slider { - background: #cccccc; - border: 1px solid #cccccc; - box-shadow: none; - transform: none; } - -.InputRange-sliderContainer { - transition: left 0.3s ease-out; } - -.InputRange-label { - color: #aaaaaa; - font-family: "Helvetica Neue", san-serif; - font-size: 0.8rem; - white-space: nowrap; } - -.InputRange-label--min, -.InputRange-label--max { - bottom: -1.4rem; - position: absolute; } - -.InputRange-label--min { - left: 0; } - -.InputRange-label--max { - right: 0; } - -.InputRange-label--value { - position: absolute; - top: -1.8rem; } - -.InputRange-labelContainer { - left: -50%; - position: relative; } - .InputRange-label--max .InputRange-labelContainer { - left: 50%; } - -.InputRange-track { - background: #eeeeee; - border-radius: 0.3rem; - cursor: pointer; - display: block; - height: 0.3rem; - position: relative; - transition: left 0.3s ease-out, width 0.3s ease-out; } - .InputRange.is-disabled .InputRange-track { - background: #eeeeee; } - -.InputRange-track--container { - left: 0; - margin-top: -0.15rem; - position: absolute; - right: 0; - top: 50%; } - -.InputRange-track--active { - background: #3f51b5; } - -.InputRange { - height: 1rem; - position: relative; - width: 100%; } diff --git a/dist/react-input-range.js b/dist/react-input-range.js deleted file mode 100644 index 8d9acd8..0000000 --- a/dist/react-input-range.js +++ /dev/null @@ -1,1213 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.InputRange = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= props.minValue && values.max <= props.maxValue && values.min < values.max; - } - - return values.max >= props.minValue && values.max <= props.maxValue; -} - -function hasStepDifference(inputRange, values) { - var props = inputRange.props; - - var currentValues = _valueTransformer2['default'].valuesFromProps(inputRange); - - return (0, _util.length)(values.min, currentValues.min) >= props.step || (0, _util.length)(values.max, currentValues.max) >= props.step; -} - -function shouldUpdate(inputRange, values) { - return isWithinRange(inputRange, values) && hasStepDifference(inputRange, values); -} - -function getDocument(inputRange) { - var ownerDocument = inputRange.refs.inputRange.ownerDocument; - - return ownerDocument; -} - -function getComponentClassName(inputRange) { - var props = inputRange.props; - - if (!props.disabled) { - return props.classNames.component; - } - - return props.classNames.component + ' ' + props.classNames.disabled; -} - -function getKeyFromSlider(inputRange, slider) { - if (slider === inputRange.refs.sliderMin) { - return 'min'; - } - - return 'max'; -} - -function getKeys(inputRange) { - if (inputRange.isMultiValue) { - return ['min', 'max']; - } - - return ['max']; -} - -function getKeyByPosition(inputRange, position) { - var values = _valueTransformer2['default'].valuesFromProps(inputRange); - var positions = _valueTransformer2['default'].positionsFromValues(inputRange, values); - - if (inputRange.isMultiValue) { - var distanceToMin = (0, _util.distanceTo)(position, positions.min); - var distanceToMax = (0, _util.distanceTo)(position, positions.max); - - if (distanceToMin < distanceToMax) { - return 'min'; - } - } - - return 'max'; -} - -function renderSliders(inputRange) { - var classNames = inputRange.props.classNames; - - var sliders = []; - var keys = getKeys(inputRange); - var values = _valueTransformer2['default'].valuesFromProps(inputRange); - var percentages = _valueTransformer2['default'].percentagesFromValues(inputRange, values); - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var key = _step.value; - - var value = values[key]; - var percentage = percentages[key]; - var ref = 'slider' + (0, _util.captialize)(key); - - var _inputRange$props = inputRange.props; - var maxValue = _inputRange$props.maxValue; - var minValue = _inputRange$props.minValue; - - if (key === 'min') { - maxValue = values.max; - } else { - minValue = values.min; - } - - var slider = _react2['default'].createElement(_Slider2['default'], { - ariaLabelledby: inputRange.props.ariaLabelledby, - ariaControls: inputRange.props.ariaControls, - classNames: classNames, - formatLabel: inputRange.formatLabel, - key: key, - maxValue: maxValue, - minValue: minValue, - onSliderKeyDown: inputRange.handleSliderKeyDown, - onSliderMouseMove: inputRange.handleSliderMouseMove, - percentage: percentage, - ref: ref, - type: key, - value: value }); - - sliders.push(slider); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator['return']) { - _iterator['return'](); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - return sliders; -} - -function renderHiddenInputs(inputRange) { - var inputs = []; - var keys = getKeys(inputRange); - - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = keys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var key = _step2.value; - - var _name = inputRange.isMultiValue ? '' + inputRange.props.name + (0, _util.captialize)(key) : inputRange.props.name; - - var input = _react2['default'].createElement('input', { type: 'hidden', name: _name }); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2['return']) { - _iterator2['return'](); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - return inputs; -} - -var InputRange = (function (_React$Component) { - _inherits(InputRange, _React$Component); - - function InputRange(props) { - _classCallCheck(this, InputRange); - - _get(Object.getPrototypeOf(InputRange.prototype), 'constructor', this).call(this, props); - - internals.set(this, {}); - - (0, _util.autobind)(['formatLabel', 'handleInteractionEnd', 'handleInteractionStart', 'handleKeyDown', 'handleKeyUp', 'handleMouseDown', 'handleMouseUp', 'handleSliderKeyDown', 'handleSliderMouseMove', 'handleTouchStart', 'handleTouchEnd', 'handleTrackMouseDown'], this); - } - - _createClass(InputRange, [{ - key: 'updatePosition', - value: function updatePosition(key, position) { - var values = _valueTransformer2['default'].valuesFromProps(this); - var positions = _valueTransformer2['default'].positionsFromValues(this, values); - - positions[key] = position; - - this.updatePositions(positions); - } - }, { - key: 'updatePositions', - value: function updatePositions(positions) { - var values = { - min: _valueTransformer2['default'].valueFromPosition(this, positions.min), - max: _valueTransformer2['default'].valueFromPosition(this, positions.max) - }; - - var transformedValues = { - min: _valueTransformer2['default'].stepValueFromValue(this, values.min), - max: _valueTransformer2['default'].stepValueFromValue(this, values.max) - }; - - this.updateValues(transformedValues); - } - }, { - key: 'updateValue', - value: function updateValue(key, value) { - var values = _valueTransformer2['default'].valuesFromProps(this); - - values[key] = value; - - this.updateValues(values); - } - }, { - key: 'updateValues', - value: function updateValues(values) { - if (!shouldUpdate(this, values)) { - return; - } - - if (this.isMultiValue) { - this.props.onChange(this, values); - } else { - this.props.onChange(this, values.max); - } - } - }, { - key: 'incrementValue', - value: function incrementValue(key) { - var values = _valueTransformer2['default'].valuesFromProps(this); - var value = values[key] + this.props.step; - - this.updateValue(key, value); - } - }, { - key: 'decrementValue', - value: function decrementValue(key) { - var values = _valueTransformer2['default'].valuesFromProps(this); - var value = values[key] - this.props.step; - - this.updateValue(key, value); - } - }, { - key: 'formatLabel', - value: function formatLabel(labelValue) { - var _props = this.props; - var formatLabel = _props.formatLabel; - var labelPrefix = _props.labelPrefix; - var labelSuffix = _props.labelSuffix; - - if (formatLabel) { - return formatLabel(labelValue, { labelPrefix: labelPrefix, labelSuffix: labelSuffix }); - } - - return '' + labelPrefix + labelValue + labelSuffix; - } - }, { - key: 'handleSliderMouseMove', - value: function handleSliderMouseMove(event, slider) { - if (this.props.disabled) { - return; - } - - var key = getKeyFromSlider(this, slider); - var position = _valueTransformer2['default'].positionFromEvent(this, event); - - this.updatePosition(key, position); - } - }, { - key: 'handleSliderKeyDown', - value: function handleSliderKeyDown(event, slider) { - if (this.props.disabled) { - return; - } - - var key = getKeyFromSlider(this, slider); - - switch (event.keyCode) { - case KeyCode.LEFT_ARROW: - case KeyCode.DOWN_ARROW: - event.preventDefault(); - this.decrementValue(key); - break; - - case KeyCode.RIGHT_ARROW: - case KeyCode.UP_ARROW: - event.preventDefault(); - this.incrementValue(key); - break; - - default: - break; - } - } - }, { - key: 'handleTrackMouseDown', - value: function handleTrackMouseDown(event, track, position) { - if (this.props.disabled) { - return; - } - - event.preventDefault(); - - var key = getKeyByPosition(this, position); - - this.updatePosition(key, position); - } - }, { - key: 'handleInteractionStart', - value: function handleInteractionStart() { - var _this = internals.get(this); - - if (!this.props.onChangeComplete || (0, _util.isDefined)(_this.startValue)) { - return; - } - - _this.startValue = this.props.value || this.props.defaultValue; - } - }, { - key: 'handleInteractionEnd', - value: function handleInteractionEnd() { - var _this = internals.get(this); - - if (!this.props.onChangeComplete || !(0, _util.isDefined)(_this.startValue)) { - return; - } - - if (_this.startValue !== this.props.value) { - this.props.onChangeComplete(this, this.props.value); - } - - _this.startValue = null; - } - }, { - key: 'handleKeyDown', - value: function handleKeyDown(event) { - this.handleInteractionStart(event); - } - }, { - key: 'handleKeyUp', - value: function handleKeyUp(event) { - this.handleInteractionEnd(event); - } - }, { - key: 'handleMouseDown', - value: function handleMouseDown(event) { - var document = getDocument(this); - - this.handleInteractionStart(event); - - document.addEventListener('mouseup', this.handleMouseUp); - } - }, { - key: 'handleMouseUp', - value: function handleMouseUp(event) { - var document = getDocument(this); - - this.handleInteractionEnd(event); - - document.removeEventListener('mouseup', this.handleMouseUp); - } - }, { - key: 'handleTouchStart', - value: function handleTouchStart(event) { - var document = getDocument(this); - - this.handleInteractionStart(event); - - document.addEventListener('touchend', this.handleTouchEnd); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(event) { - var document = getDocument(this); - - this.handleInteractionEnd(event); - - document.removeEventListener('touchend', this.handleTouchEnd); - } - }, { - key: 'render', - value: function render() { - var classNames = this.props.classNames; - - var componentClassName = getComponentClassName(this); - var values = _valueTransformer2['default'].valuesFromProps(this); - var percentages = _valueTransformer2['default'].percentagesFromValues(this, values); - - return _react2['default'].createElement( - 'div', - { - 'aria-disabled': this.props.disabled, - ref: 'inputRange', - className: componentClassName, - onKeyDown: this.handleKeyDown, - onKeyUp: this.handleKeyUp, - onMouseDown: this.handleMouseDown, - onTouchStart: this.handleTouchStart }, - _react2['default'].createElement( - _Label2['default'], - { - className: classNames.labelMin, - containerClassName: classNames.labelContainer, - formatLabel: this.formatLabel }, - this.props.minValue - ), - _react2['default'].createElement( - _Track2['default'], - { - classNames: classNames, - ref: 'track', - percentages: percentages, - onTrackMouseDown: this.handleTrackMouseDown }, - renderSliders(this) - ), - _react2['default'].createElement( - _Label2['default'], - { - className: classNames.labelMax, - containerClassName: classNames.labelContainer, - formatLabel: this.formatLabel }, - this.props.maxValue - ), - renderHiddenInputs(this) - ); - } - }, { - key: 'trackClientRect', - get: function get() { - var track = this.refs.track; - - if (track) { - return track.clientRect; - } - - return { - height: 0, - left: 0, - top: 0, - width: 0 - }; - } - }, { - key: 'isMultiValue', - get: function get() { - return (0, _util.isObject)(this.props.value) || (0, _util.isObject)(this.props.defaultValue); - } - }]); - - return InputRange; -})(_react2['default'].Component); - -exports['default'] = InputRange; - -InputRange.propTypes = { - ariaLabelledby: _react2['default'].PropTypes.string, - ariaControls: _react2['default'].PropTypes.string, - classNames: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.string), - defaultValue: _propTypes.maxMinValuePropType, - disabled: _react2['default'].PropTypes.bool, - formatLabel: _react2['default'].PropTypes.func, - labelPrefix: _react2['default'].PropTypes.string, - labelSuffix: _react2['default'].PropTypes.string, - maxValue: _propTypes.maxMinValuePropType, - minValue: _propTypes.maxMinValuePropType, - name: _react2['default'].PropTypes.string, - onChange: _react2['default'].PropTypes.func.isRequired, - onChangeComplete: _react2['default'].PropTypes.func, - step: _react2['default'].PropTypes.number, - value: _propTypes.maxMinValuePropType -}; - -InputRange.defaultProps = { - classNames: _defaultClassNames2['default'], - defaultValue: 0, - disabled: false, - labelPrefix: '', - labelSuffix: '', - maxValue: 10, - minValue: 0, - step: 1, - value: null -}; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Label":2,"./Slider":3,"./Track":4,"./defaultClassNames":5,"./propTypes":6,"./util":7,"./valueTransformer":8}],2:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - -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 _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var Label = (function (_React$Component) { - _inherits(Label, _React$Component); - - function Label() { - _classCallCheck(this, Label); - - _get(Object.getPrototypeOf(Label.prototype), 'constructor', this).apply(this, arguments); - } - - _createClass(Label, [{ - key: 'render', - value: function render() { - var _props = this.props; - var className = _props.className; - var containerClassName = _props.containerClassName; - - var labelValue = this.props.formatLabel ? this.props.formatLabel(this.props.children) : this.props.children; - - return _react2['default'].createElement( - 'span', - { className: className }, - _react2['default'].createElement( - 'span', - { className: containerClassName }, - labelValue - ) - ); - } - }]); - - return Label; -})(_react2['default'].Component); - -exports['default'] = Label; - -Label.propTypes = { - children: _react2['default'].PropTypes.node, - className: _react2['default'].PropTypes.string, - containerClassName: _react2['default'].PropTypes.string, - formatLabel: _react2['default'].PropTypes.func -}; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],3:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - -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 _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _Label = require('./Label'); - -var _Label2 = _interopRequireDefault(_Label); - -var _util = require('./util'); - -function getDocument(slider) { - var ownerDocument = slider.refs.slider.ownerDocument; - - return ownerDocument; -} - -function getStyle(slider) { - var perc = (slider.props.percentage || 0) * 100; - var style = { - position: 'absolute', - left: perc + '%' - }; - - return style; -} - -var Slider = (function (_React$Component) { - _inherits(Slider, _React$Component); - - function Slider(props) { - _classCallCheck(this, Slider); - - _get(Object.getPrototypeOf(Slider.prototype), 'constructor', this).call(this, props); - - (0, _util.autobind)(['handleClick', 'handleMouseDown', 'handleMouseUp', 'handleMouseMove', 'handleTouchStart', 'handleTouchEnd', 'handleTouchMove', 'handleKeyDown'], this); - } - - _createClass(Slider, [{ - key: 'handleClick', - value: function handleClick(event) { - event.preventDefault(); - } - }, { - key: 'handleMouseDown', - value: function handleMouseDown() { - var document = getDocument(this); - - document.addEventListener('mousemove', this.handleMouseMove); - document.addEventListener('mouseup', this.handleMouseUp); - } - }, { - key: 'handleMouseUp', - value: function handleMouseUp() { - var document = getDocument(this); - - document.removeEventListener('mousemove', this.handleMouseMove); - document.removeEventListener('mouseup', this.handleMouseUp); - } - }, { - key: 'handleMouseMove', - value: function handleMouseMove(event) { - this.props.onSliderMouseMove(event, this); - } - }, { - key: 'handleTouchStart', - value: function handleTouchStart(event) { - var document = getDocument(this); - - event.preventDefault(); - - document.addEventListener('touchmove', this.handleTouchMove); - document.addEventListener('touchend', this.handleTouchEnd); - } - }, { - key: 'handleTouchMove', - value: function handleTouchMove(event) { - this.props.onSliderMouseMove(event, this); - } - }, { - key: 'handleTouchEnd', - value: function handleTouchEnd(event) { - var document = getDocument(this); - - event.preventDefault(); - - document.removeEventListener('touchmove', this.handleTouchMove); - document.removeEventListener('touchend', this.handleTouchEnd); - } - }, { - key: 'handleKeyDown', - value: function handleKeyDown(event) { - this.props.onSliderKeyDown(event, this); - } - }, { - key: 'render', - value: function render() { - var classNames = this.props.classNames; - var style = getStyle(this); - - return _react2['default'].createElement( - 'span', - { - className: classNames.sliderContainer, - ref: 'slider', - style: style }, - _react2['default'].createElement( - _Label2['default'], - { - className: classNames.labelValue, - containerClassName: classNames.labelContainer, - formatLabel: this.props.formatLabel }, - this.props.value - ), - _react2['default'].createElement('a', { - 'aria-labelledby': this.props.ariaLabelledby, - 'aria-controls': this.props.ariaControls, - 'aria-valuemax': this.props.maxValue, - 'aria-valuemin': this.props.minValue, - 'aria-valuenow': this.props.formatLabel ? this.props.formatLabel(this.props.value) : this.props.value, - className: classNames.slider, - draggable: 'false', - href: '#', - onClick: this.handleClick, - onKeyDown: this.handleKeyDown, - onMouseDown: this.handleMouseDown, - onTouchStart: this.handleTouchStart, - role: 'slider' }) - ); - } - }]); - - return Slider; -})(_react2['default'].Component); - -exports['default'] = Slider; - -Slider.propTypes = { - ariaLabelledby: _react2['default'].PropTypes.string, - ariaControls: _react2['default'].PropTypes.string, - classNames: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.string), - formatLabel: _react2['default'].PropTypes.func, - maxValue: _react2['default'].PropTypes.number, - minValue: _react2['default'].PropTypes.number, - onSliderKeyDown: _react2['default'].PropTypes.func.isRequired, - onSliderMouseMove: _react2['default'].PropTypes.func.isRequired, - percentage: _react2['default'].PropTypes.number.isRequired, - type: _react2['default'].PropTypes.string.isRequired, - value: _react2['default'].PropTypes.number.isRequired -}; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Label":2,"./util":7}],4:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -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 _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - -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 _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _util = require('./util'); - -function getActiveTrackStyle(track) { - var props = track.props; - - var width = (props.percentages.max - props.percentages.min) * 100 + '%'; - var left = props.percentages.min * 100 + '%'; - - var activeTrackStyle = { - left: left, - width: width - }; - - return activeTrackStyle; -} - -var Track = (function (_React$Component) { - _inherits(Track, _React$Component); - - function Track(props) { - _classCallCheck(this, Track); - - _get(Object.getPrototypeOf(Track.prototype), 'constructor', this).call(this, props); - - (0, _util.autobind)(['handleMouseDown', 'handleTouchStart'], this); - } - - _createClass(Track, [{ - key: 'handleMouseDown', - value: function handleMouseDown(event) { - var trackClientRect = this.clientRect; - - var _ref = event.touches ? event.touches[0] : event; - - var clientX = _ref.clientX; - - var position = { - x: clientX - trackClientRect.left, - y: 0 - }; - - this.props.onTrackMouseDown(event, this, position); - } - }, { - key: 'handleTouchStart', - value: function handleTouchStart(event) { - event.preventDefault(); - - this.handleMouseDown(event); - } - }, { - key: 'render', - value: function render() { - var activeTrackStyle = getActiveTrackStyle(this); - var classNames = this.props.classNames; - - return _react2['default'].createElement( - 'div', - { - className: classNames.trackContainer, - onMouseDown: this.handleMouseDown, - onTouchStart: this.handleTouchStart, - ref: 'track' }, - _react2['default'].createElement('div', { - style: activeTrackStyle, - className: classNames.trackActive }), - this.props.children - ); - } - }, { - key: 'clientRect', - get: function get() { - var track = this.refs.track; - - var clientRect = track.getBoundingClientRect(); - - return clientRect; - } - }]); - - return Track; -})(_react2['default'].Component); - -exports['default'] = Track; - -Track.propTypes = { - children: _react2['default'].PropTypes.node, - classNames: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.string), - onTrackMouseDown: _react2['default'].PropTypes.func.isRequired, - percentages: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.number).isRequired -}; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./util":7}],5:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports['default'] = { - component: 'InputRange', - labelContainer: 'InputRange-labelContainer', - labelMax: 'InputRange-label InputRange-label--max', - labelMin: 'InputRange-label InputRange-label--min', - labelValue: 'InputRange-label InputRange-label--value', - slider: 'InputRange-slider', - sliderContainer: 'InputRange-sliderContainer', - trackActive: 'InputRange-track InputRange-track--active', - trackContainer: 'InputRange-track InputRange-track--container', - disabled: 'is-disabled' -}; -module.exports = exports['default']; - -},{}],6:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.maxMinValuePropType = maxMinValuePropType; - -var _util = require('./util'); - -function maxMinValuePropType(props) { - var maxValue = props.maxValue; - var minValue = props.minValue; - var value = props.value; - var defaultValue = props.defaultValue; - var isValueNumber = (0, _util.isNumber)(value); - var isDefaultValueNumber = (0, _util.isNumber)(defaultValue); - var isValueNumberObject = (0, _util.objectOf)(value, _util.isNumber); - var isDefaultValueNumberObject = (0, _util.objectOf)(defaultValue, _util.isNumber); - - if (value === undefined) { - return new Error('`value` must be defined'); - } - - if (!isValueNumber && !isDefaultValueNumber && !isValueNumberObject && !isDefaultValueNumberObject) { - return new Error('`value` or `defaultValue` must be a number or an array'); - } - - if (minValue >= maxValue) { - return new Error('`minValue` must be smaller than `maxValue`'); - } - - if (maxValue <= minValue) { - return new Error('`maxValue` must be larger than `minValue`'); - } - - if (value < minValue || value > maxValue) { - return new Error('`value` must be within `minValue` and `maxValue`'); - } -} - -},{"./util":7}],7:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports.clamp = clamp; -exports.extend = extend; -exports.includes = includes; -exports.omit = omit; -exports.captialize = captialize; -exports.distanceTo = distanceTo; -exports.length = length; -exports.isNumber = isNumber; -exports.isObject = isObject; -exports.isDefined = isDefined; -exports.isEmpty = isEmpty; -exports.arrayOf = arrayOf; -exports.objectOf = objectOf; -exports.autobind = autobind; - -function clamp(value, min, max) { - return Math.min(Math.max(value, min), max); -} - -function extend() { - return Object.assign.apply(Object, arguments); -} - -function includes(array, value) { - return array.indexOf(value) > -1; -} - -function omit(obj, omitKeys) { - var keys = Object.keys(obj); - var outputObj = {}; - - keys.forEach(function (key) { - if (!includes(omitKeys, key)) { - outputObj[key] = obj[key]; - } - }); - - return outputObj; -} - -function captialize(string) { - return string.charAt(0).toUpperCase() + string.slice(1); -} - -function distanceTo(pointA, pointB) { - return Math.sqrt(Math.pow(pointB.x - pointA.x, 2) + Math.pow(pointB.y - pointA.y, 2)); -} - -function length(numA, numB) { - return Math.abs(numA - numB); -} - -function isNumber(value) { - return typeof value === 'number'; -} - -function isObject(value) { - return value !== null && typeof value === 'object'; -} - -function isDefined(value) { - return value !== undefined && value !== null; -} - -function isEmpty(obj) { - if (!obj) { - return true; - } - - if (Array.isArray(obj)) { - return obj.length === 0; - } - - return Object.keys(obj).length === 0; -} - -function arrayOf(array, predicate) { - if (!Array.isArray(array)) { - return false; - } - - for (var i = 0, len = array.length; i < len; i++) { - if (!predicate(array[i])) { - return false; - } - } - - return true; -} - -function objectOf(object, predicate, keys) { - if (!isObject(object)) { - return false; - } - - var props = keys || Object.keys(object); - - for (var i = 0, len = props.length; i < len; i++) { - var prop = props[i]; - - if (!predicate(object[prop])) { - return false; - } - } - - return true; -} - -function autobind(methodNames, instance) { - methodNames.forEach(function (methodName) { - instance[methodName] = instance[methodName].bind(instance); - }); -} - -},{}],8:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -var _util = require('./util'); - -function percentageFromPosition(inputRange, position) { - var length = inputRange.trackClientRect.width; - var sizePerc = position.x / length; - - return sizePerc || 0; -} - -function valueFromPosition(inputRange, position) { - var sizePerc = percentageFromPosition(inputRange, position); - var valueDiff = inputRange.props.maxValue - inputRange.props.minValue; - var value = inputRange.props.minValue + valueDiff * sizePerc; - - return value; -} - -function valuesFromProps(inputRange) { - var _ref = arguments.length <= 1 || arguments[1] === undefined ? inputRange : arguments[1]; - - var props = _ref.props; - return (function () { - if (inputRange.isMultiValue) { - var values = props.value; - - if ((0, _util.isEmpty)(values) || !(0, _util.objectOf)(values, _util.isNumber)) { - values = props.defaultValue; - } - - return Object.create(values); - } - - var value = (0, _util.isNumber)(props.value) ? props.value : props.defaultValue; - - return { - min: props.minValue, - max: value - }; - })(); -} - -function percentageFromValue(inputRange, value) { - var validValue = (0, _util.clamp)(value, inputRange.props.minValue, inputRange.props.maxValue); - var valueDiff = inputRange.props.maxValue - inputRange.props.minValue; - var valuePerc = (validValue - inputRange.props.minValue) / valueDiff; - - return valuePerc || 0; -} - -function percentagesFromValues(inputRange, values) { - var percentages = { - min: percentageFromValue(inputRange, values.min), - max: percentageFromValue(inputRange, values.max) - }; - - return percentages; -} - -function positionFromValue(inputRange, value) { - var length = inputRange.trackClientRect.width; - var valuePerc = percentageFromValue(inputRange, value); - var positionValue = valuePerc * length; - - return { - x: positionValue, - y: 0 - }; -} - -function positionsFromValues(inputRange, values) { - var positions = { - min: positionFromValue(inputRange, values.min), - max: positionFromValue(inputRange, values.max) - }; - - return positions; -} - -function positionFromEvent(inputRange, event) { - var trackClientRect = inputRange.trackClientRect; - var length = trackClientRect.width; - - var _ref2 = event.touches ? event.touches[0] : event; - - var clientX = _ref2.clientX; - - var position = { - x: (0, _util.clamp)(clientX - trackClientRect.left, 0, length), - y: 0 - }; - - return position; -} - -function stepValueFromValue(inputRange, value) { - return Math.round(value / inputRange.props.step) * inputRange.props.step; -} - -exports['default'] = { - percentageFromPosition: percentageFromPosition, - percentageFromValue: percentageFromValue, - percentagesFromValues: percentagesFromValues, - positionFromEvent: positionFromEvent, - positionFromValue: positionFromValue, - positionsFromValues: positionsFromValues, - stepValueFromValue: stepValueFromValue, - valueFromPosition: valueFromPosition, - valuesFromProps: valuesFromProps -}; -module.exports = exports['default']; - -},{"./util":7}],9:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _InputRange = require('./InputRange'); - -var _InputRange2 = _interopRequireDefault(_InputRange); - -exports['default'] = _InputRange2['default']; -module.exports = exports['default']; - -},{"./InputRange":1}]},{},[9])(9) -}); \ No newline at end of file diff --git a/dist/react-input-range.min.css b/dist/react-input-range.min.css deleted file mode 100644 index 0a1060f..0000000 --- a/dist/react-input-range.min.css +++ /dev/null @@ -1 +0,0 @@ -.InputRange-slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#3f51b5;border:1px solid #3f51b5;border-radius:100%;cursor:pointer;display:block;height:1rem;margin-left:-.5rem;margin-top:-.65rem;outline:0;position:absolute;top:50%;transition:transform .3s ease-out,box-shadow .3s ease-out;width:1rem}.InputRange-slider:active{transform:scale(1.3)}.InputRange-slider:focus{box-shadow:0 0 0 5px rgba(63,81,181,.2)}.InputRange.is-disabled .InputRange-slider{background:#ccc;border:1px solid #ccc;box-shadow:none;transform:none}.InputRange-sliderContainer{transition:left .3s ease-out}.InputRange-label{color:#aaa;font-family:"Helvetica Neue",san-serif;font-size:.8rem;white-space:nowrap}.InputRange-label--max,.InputRange-label--min{bottom:-1.4rem;position:absolute}.InputRange-label--min{left:0}.InputRange-label--max{right:0}.InputRange-label--value{position:absolute;top:-1.8rem}.InputRange-labelContainer{left:-50%;position:relative}.InputRange-label--max .InputRange-labelContainer{left:50%}.InputRange-track{background:#eee;border-radius:.3rem;cursor:pointer;display:block;height:.3rem;position:relative;transition:left .3s ease-out,width .3s ease-out}.InputRange.is-disabled .InputRange-track{background:#eee}.InputRange-track--container{left:0;margin-top:-.15rem;position:absolute;right:0;top:50%}.InputRange-track--active{background:#3f51b5}.InputRange{height:1rem;position:relative;width:100%} \ No newline at end of file diff --git a/dist/react-input-range.min.js b/dist/react-input-range.min.js deleted file mode 100644 index 909ad54..0000000 --- a/dist/react-input-range.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.InputRange=e()}}(function(){return function e(t,n,a){function r(u,i){if(!n[u]){if(!t[u]){var l="function"==typeof require&&require;if(!i&&l)return l(u,!0);if(o)return o(u,!0);var s=new Error("Cannot find module '"+u+"'");throw s.code="MODULE_NOT_FOUND",s}var f=n[u]={exports:{}};t[u][0].call(f.exports,function(e){var n=t[u][1][e];return r(n?n:e)},f,f.exports,e,t,n,a)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;u=n.minValue&&t.max<=n.maxValue&&t.min=n.minValue&&t.max<=n.maxValue}function l(e,t){var n=e.props,a=j["default"].valuesFromProps(e);return(0,_.length)(t.min,a.min)>=n.step||(0,_.length)(t.max,a.max)>=n.step}function s(e,t){return i(e,t)&&l(e,t)}function f(e){var t=e.refs.inputRange.ownerDocument;return t}function p(e){var t=e.props;return t.disabled?t.classNames.component+" "+t.classNames.disabled:t.classNames.component}function c(e,t){return t===e.refs.sliderMin?"min":"max"}function d(e){return e.isMultiValue?["min","max"]:["max"]}function h(e,t){var n=j["default"].valuesFromProps(e),a=j["default"].positionsFromValues(e,n);if(e.isMultiValue){var r=(0,_.distanceTo)(t,a.min),o=(0,_.distanceTo)(t,a.max);if(r=t?new Error("`minValue` must be smaller than `maxValue`"):t<=n?new Error("`maxValue` must be larger than `minValue`"):at?new Error("`value` must be within `minValue` and `maxValue`"):void 0:new Error("`value` or `defaultValue` must be a number or an array")}Object.defineProperty(n,"__esModule",{value:!0}),n.maxMinValuePropType=a;var r=e("./util")},{"./util":7}],7:[function(e,t,n){"use strict";function a(e,t,n){return Math.min(Math.max(e,t),n)}function r(){return Object.assign.apply(Object,arguments)}function o(e,t){return e.indexOf(t)>-1}function u(e,t){var n=Object.keys(e),a={};return n.forEach(function(n){o(t,n)||(a[n]=e[n])}),a}function i(e){return e.charAt(0).toUpperCase()+e.slice(1)}function l(e,t){return Math.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2))}function s(e,t){return Math.abs(e-t)}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function c(e){return void 0!==e&&null!==e}function d(e){return!e||(Array.isArray(e)?0===e.length:0===Object.keys(e).length)}function h(e,t){if(!Array.isArray(e))return!1;for(var n=0,a=e.length;n - - + @@ -12,6 +11,6 @@ - + diff --git a/example/js/App.js b/example/js/App.js index fedacae..3556fa1 100644 --- a/example/js/App.js +++ b/example/js/App.js @@ -1,5 +1,5 @@ import React from 'react'; -import InputRange from 'InputRange'; +import InputRange from '../../src/js'; class App extends React.Component { constructor(props) { @@ -22,6 +22,12 @@ class App extends React.Component { max: 10, }, }; + + this.handleValueChange = this.handleValueChange.bind(this); + this.handleValue2Change = this.handleValue2Change.bind(this); + this.handleValue3Change = this.handleValue3Change.bind(this); + this.handleValue4Change = this.handleValue4Change.bind(this); + this.handleValue5Change = this.handleValue5Change.bind(this); } handleValueChange(component, value) { @@ -78,45 +84,45 @@ class App extends React.Component { return (
); diff --git a/example/js/example.js b/example/js/example.js deleted file mode 100644 index 484d5b1..0000000 --- a/example/js/example.js +++ /dev/null @@ -1,7 +0,0 @@ -import ReactDOM from 'react-dom'; -import App from 'App'; - -ReactDOM.render( - , - document.getElementById('app') -); diff --git a/example/js/index.js b/example/js/index.js new file mode 100644 index 0000000..d57cb6a --- /dev/null +++ b/example/js/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import '../../src/scss/index.scss'; +import '../scss/index.scss'; + +ReactDOM.render( + , + document.getElementById('app'), +); diff --git a/example/scss/example.scss b/example/scss/index.scss similarity index 80% rename from example/scss/example.scss rename to example/scss/index.scss index 55d672b..ff30833 100644 --- a/example/scss/example.scss +++ b/example/scss/index.scss @@ -1,5 +1,3 @@ -@import 'react-input-range'; - .form { height: 200px; margin: 0 auto; diff --git a/gulpfile.babel.js b/gulpfile.babel.js deleted file mode 100644 index bb581f5..0000000 --- a/gulpfile.babel.js +++ /dev/null @@ -1,12 +0,0 @@ -// Dependencies -import './tasks/build'; -import './tasks/clean'; -import './tasks/connect'; -import './tasks/default'; -import './tasks/lint'; -import './tasks/release'; -import './tasks/run'; -import './tasks/script'; -import './tasks/style'; -import './tasks/test'; -import './tasks/watch'; diff --git a/karma.conf.js b/karma.conf.js index e8aee15..132b02d 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,55 +1,36 @@ -module.exports = function(config) { +function configureKarma(config) { config.set({ - basePath: '', - - frameworks: ['browserify', 'jasmine'], - - files: [ - 'node_modules/es5-shim/es5-shim.js', - 'node_modules/react/dist/react.js', - 'node_modules/react-dom/dist/react-dom.js', - 'node_modules/lodash/index.js', - 'node_modules/babelify/polyfill.js', - 'src/**/*.js', - 'test/**/*.js' - ], - - exclude: [ - ], - - preprocessors: { - 'src/**/*.js': ['browserify'], - 'test/**/*.js': ['browserify'], - 'node_modules/babelify/polyfill.js': ['browserify'] + basePath: __dirname, + browsers: ['PhantomJS'], + coverageReporter: { + reporters: [ + { type: 'html' }, + { type: 'text' }, + ], }, - - babelPreprocessor: { - options: { - modules: 'ignore' - } + frameworks: ['jasmine'], + files: ['test/index.js'], + preprocessors: { + 'src/index.js': ['coverage'], + 'test/index.js': ['webpack', 'sourcemap'], }, - - browserify: { - debug: true, - extensions: ['.js', '.jsx'], - transform: ['babelify'], - paths: [ - 'src' - ] + reporters: ['mocha', 'coverage'], + webpack: { + devtool: 'inline-source-map', + module: { + loaders: [ + { + exclude: /node_modules/, + loader: 'babel', + query: { + plugins: ['istanbul'], + }, + test: /\.js$/, + }, + ], + }, }, - - reporters: ['progress'], - - port: 9876, - - colors: true, - - logLevel: config.LOG_INFO, - - autoWatch: true, - - browsers: ['PhantomJS'], - - singleRun: false - }) + }); } + +module.exports = configureKarma; diff --git a/package.json b/package.json index 7df6f3f..11361a6 100644 --- a/package.json +++ b/package.json @@ -16,76 +16,68 @@ "type": "git", "url": "https://github.com/davidchin/react-input-range.git" }, - "main": "lib/InputRange/index.js", + "main": "lib/js/index.js", "types": "react-input-range.d.ts", "author": "David Chin", "license": "MIT", "devDependencies": { - "@types/react": "^0.14.55", - "autoprefixer-core": "^5.2.1", - "babel-core": "^5.8.25", - "babel-eslint": "^4.0.5", - "babelify": "^6.1.3", - "browserify": "^11.0.0", - "browserify-shim": "^3.8.10", + "@types/react": "^15.0.1", + "autoprefixer": "^6.6.1", + "babel-cli": "^6.22.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-loader": "^6.2.10", + "babel-plugin-istanbul": "^3.1.2", + "babel-polyfill": "^6.22.0", + "babel-preset-es2015": "^6.22.0", + "babel-preset-es2016": "^6.22.0", + "babel-preset-react": "^6.22.0", "conventional-changelog-cli": "~1.2.0", - "del": "^1.2.0", - "es5-shim": "^4.4.1", - "eslint": "^1.10.2", - "eslint-config-airbnb": "^1.0.2", - "eslint-plugin-react": "^3.10.0", - "gulp": "^3.9.0", - "gulp-babel": "^5.2.1", - "gulp-bump": "^1.0.0", - "gulp-concat": "^2.6.0", - "gulp-connect": "^2.2.0", - "gulp-eslint": "^1.1.1", - "gulp-git": "^1.4.0", - "gulp-minify-css": "^1.2.0", - "gulp-postcss": "^6.0.0", - "gulp-prompt": "^0.1.2", - "gulp-rename": "^1.2.2", - "gulp-sass": "^2.1.0", - "gulp-scss-lint": "^0.3.0", - "gulp-sourcemaps": "^1.5.2", - "gulp-uglify": "^1.2.0", - "gulp-util": "^3.0.6", - "jasmine-core": "^2.3.4", - "karma": "^0.13.8", - "karma-babel-preprocessor": "^5.2.1", - "karma-browserify": "^4.3.0", - "karma-jasmine": "^0.3.6", + "css-loader": "^0.26.1", + "esdoc-importpath-plugin": "^0.1.0", + "eslint": "^3.14.0", + "eslint-config-airbnb": "^14.0.0", + "eslint-loader": "^1.6.1", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^3.0.2", + "eslint-plugin-react": "^6.9.0", + "extract-text-webpack-plugin": "^1.0.1", + "karma": "^1.4.0", + "karma-babel-preprocessor": "^6.0.1", + "karma-coverage": "^1.1.1", + "karma-jasmine": "^1.1.0", + "karma-mocha-reporter": "^2.2.2", "karma-phantomjs-launcher": "^1.0.2", - "lodash": "^3.10.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^2.0.1", + "node-sass": "^4.3.0", + "postcss-loader": "^1.2.2", "react": "^0.14.0", "react-dom": "^0.14.0", - "run-sequence": "^1.1.4", - "semver": "^5.0.3", - "vinyl-buffer": "^1.0.0", - "vinyl-source-stream": "^1.1.0", - "watchify": "^3.3.0" + "sass-lint": "^1.10.2", + "sass-loader": "^4.1.1", + "sasslint-webpack-plugin": "^1.0.4", + "style-loader": "^0.13.1", + "webpack": "^1.14.0", + "webpack-dev-server": "^1.16.2" }, "peerDependencies": { "react": "^0.14.0 || ^15.0.0", "react-dom": "^0.14.0 || ^15.0.0" }, - "browserify": { - "transform": [ - "browserify-shim" - ] - }, - "browserify-shim": { - "react": "global:React", - "react-dom": "global:ReactDOM" - }, "scripts": { - "build": "gulp build", - "build:dist": "gulp build:dist", - "build:lib": "gulp build:lib", + "prebuild": "npm run test && rm -rf lib", + "build": "npm run build:lib && npm run build:scss && npm run build:bundle", + "build:bundle": "NODE_ENV=production webpack", + "build:lib": "NODE_ENV=production babel src --out-dir lib --source-maps", + "build:scss": "NODE_ENV=production node-sass src/scss --recursive --source-map true --output lib/css", "changelog": "conventional-changelog --preset angular --infile CHANGELOG.md --same-file", - "release": "gulp release", - "start": "gulp run", - "test": "gulp test", - "prepublish": "npm run build:lib" + "dev": "webpack-dev-server --inline --config webpack-example.config.js --content-base example", + "lint": "npm run lint:js && npm run lint:scss", + "lint:js": "eslint src", + "lint:scss": "sass-lint --verbose --no-exit", + "prepublish": "npm run build", + "pretest": "npm run lint", + "test": "karma start --single-run" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..655e458 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,9 @@ +const autoprefixer = require('autoprefixer'); + +const postCssConfig = { + plugins: [ + autoprefixer(), + ], +}; + +module.exports = postCssConfig; diff --git a/scss/InputRange.scss b/scss/InputRange.scss deleted file mode 100644 index 8819649..0000000 --- a/scss/InputRange.scss +++ /dev/null @@ -1,11 +0,0 @@ -@import "InputRangeVariables"; -@import "InputRangeSlider"; -@import "InputRangeLabel"; -@import "InputRangeLabelContainer"; -@import "InputRangeTrack"; - -.InputRange { - height: $InputRange-slider-height; - position: relative; - width: 100%; -} diff --git a/src/InputRange/Label.js b/src/InputRange/Label.js deleted file mode 100644 index 43f2622..0000000 --- a/src/InputRange/Label.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @module InputRange/Label - */ - -import React from 'react'; - -/** - * Label React component - * @class - * @extends React.Component - * @param {Object} props - React component props - */ -export default class Label extends React.Component { - /** - * Render method of the component - * @return {string} Component JSX - */ - render() { - const { className, containerClassName } = this.props; - const labelValue = this.props.formatLabel ? - this.props.formatLabel(this.props.children) : - this.props.children; - - return ( - - - { labelValue } - - - ); - } -} - -/** - * Accepted propTypes of Label - * @static {Object} - * @property {Function} children - * @property {Function} className - * @property {Function} containerClassName - * @property {Function} formatLabel - */ -Label.propTypes = { - children: React.PropTypes.node, - className: React.PropTypes.string, - containerClassName: React.PropTypes.string, - formatLabel: React.PropTypes.func, -}; diff --git a/src/InputRange/index.js b/src/InputRange/index.js deleted file mode 100644 index 1efe83a..0000000 --- a/src/InputRange/index.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @module InputRange - */ - -import InputRange from './InputRange'; - -/** - * An object describing the position of a point - * @typedef {Object} Point - * @property {number} x - x value - * @property {number} y - y value - */ - -/** - * An object describing a range of values - * @typedef {Object} Range - * @property {number} min - Min value - * @property {number} max - Max value - */ - -export default InputRange; diff --git a/src/InputRange/InputRange.js b/src/js/InputRange/InputRange.js similarity index 82% rename from src/InputRange/InputRange.js rename to src/js/InputRange/InputRange.js index 226194b..0aa0687 100644 --- a/src/InputRange/InputRange.js +++ b/src/js/InputRange/InputRange.js @@ -1,25 +1,43 @@ -/** - * @module InputRange - */ - import React from 'react'; import Slider from './Slider'; import Track from './Track'; import Label from './Label'; import defaultClassNames from './defaultClassNames'; -import valueTransformer from './valueTransformer'; -import { autobind, captialize, distanceTo, isDefined, isObject, length } from './util'; +import * as valueTransformer from './valueTransformer'; +import { autobind, captialize, distanceTo, isDefined, isObject, length } from '../utils'; import { maxMinValuePropType } from './propTypes'; +/** + * An object describing the position of a point + * @typedef {Object} Point + * @property {number} x - x value + * @property {number} y - y value + */ + +/** + * An object describing a range of values + * @typedef {Object} Range + * @property {number} min - Min value + * @property {number} max - Max value + */ + +/** + * @typedef {Object} ClientRect + * @property {number} height - Height value + * @property {number} left - Left value + * @property {number} top - Top value + * @property {number} width - Width value + */ + /** * A map for storing internal members - * @const {WeakMap} + * @type {WeakMap} */ const internals = new WeakMap(); /** * An object storing keyboard key codes - * @const {Object.} + * @type {Object} */ const KeyCode = { DOWN_ARROW: 40, @@ -30,7 +48,6 @@ const KeyCode = { /** * Check if values are within the max and min range of inputRange - * @private * @param {InputRange} inputRange - React component * @param {Range} values - Min/max value of sliders * @return {boolean} True if within range @@ -123,7 +140,7 @@ function getKeyFromSlider(inputRange, slider) { * Get all slider keys of inputRange * @private * @param {InputRange} inputRange - React component - * @return {Array.} Key names + * @return {string[]} Key names */ function getKeys(inputRange) { if (inputRange.isMultiValue) { @@ -160,16 +177,15 @@ function getKeyByPosition(inputRange, position) { * Get an array of slider HTML for rendering * @private * @param {InputRange} inputRange - React component - * @return {Array.} Array of HTML + * @return {string[]} Array of HTML */ function renderSliders(inputRange) { const { classNames } = inputRange.props; - const sliders = []; const keys = getKeys(inputRange); const values = valueTransformer.valuesFromProps(inputRange); const percentages = valueTransformer.percentagesFromValues(inputRange, values); - for (const key of keys) { + return keys.map((key) => { const value = values[key]; const percentage = percentages[key]; const ref = `slider${captialize(key)}`; @@ -199,40 +215,102 @@ function renderSliders(inputRange) { value={ value } /> ); - sliders.push(slider); - } - - return sliders; + return slider; + }); } /** * Get an array of hidden input HTML for rendering * @private * @param {InputRange} inputRange - React component - * @return {Array.} Array of HTML + * @return {string[]} Array of HTML */ function renderHiddenInputs(inputRange) { - const inputs = []; const keys = getKeys(inputRange); - for (const key of keys) { + return keys.map((key) => { const name = inputRange.isMultiValue ? `${inputRange.props.name}${captialize(key)}` : inputRange.props.name; - const input = ( - + return ( + ); - } - - return inputs; + }); } /** * InputRange React component - * @class - * @extends React.Component - * @param {Object} props - React component props */ export default class InputRange extends React.Component { + /** + * Accepted propTypes of InputRange + * @return {Object} + * @property {Function} ariaLabelledby + * @property {Function} ariaControls + * @property {Function} classNames + * @property {Function} defaultValue + * @property {Function} disabled + * @property {Function} formatLabel + * @property {Function} labelPrefix + * @property {Function} labelSuffix + * @property {Function} maxValue + * @property {Function} minValue + * @property {Function} name + * @property {Function} onChange + * @property {Function} onChangeComplete + * @property {Function} step + * @property {Function} value + */ + static get propTypes() { + return { + ariaLabelledby: React.PropTypes.string, + ariaControls: React.PropTypes.string, + classNames: React.PropTypes.objectOf(React.PropTypes.string), + defaultValue: maxMinValuePropType, + disabled: React.PropTypes.bool, + formatLabel: React.PropTypes.func, + labelPrefix: React.PropTypes.string, + labelSuffix: React.PropTypes.string, + maxValue: maxMinValuePropType, + minValue: maxMinValuePropType, + name: React.PropTypes.string, + onChange: React.PropTypes.func.isRequired, + onChangeComplete: React.PropTypes.func, + step: React.PropTypes.number, + value: maxMinValuePropType, + }; + } + + /** + * Default props of InputRange + * @return {Object} + * @property {Object} defaultClassNames + * @property {Range|number} defaultValue + * @property {boolean} disabled + * @property {string} labelPrefix + * @property {string} labelSuffix + * @property {number} maxValue + * @property {number} minValue + * @property {number} step + * @property {Range|number} value + */ + static get defaultProps() { + return { + classNames: defaultClassNames, + defaultValue: 0, + disabled: false, + labelPrefix: '', + labelSuffix: '', + maxValue: 10, + minValue: 0, + step: 1, + value: null, + }; + } + + /** + * InputRange constructor + * @param {Object} props - React component props + */ constructor(props) { super(props); @@ -258,7 +336,7 @@ export default class InputRange extends React.Component { /** * Return the clientRect of the component's track - * @member {ClientRect} + * @return {ClientRect} */ get trackClientRect() { const { track } = this.refs; @@ -277,7 +355,7 @@ export default class InputRange extends React.Component { /** * Return true if the component accepts a range of values - * @member {boolean} + * @return {boolean} */ get isMultiValue() { return isObject(this.props.value) || @@ -433,7 +511,7 @@ export default class InputRange extends React.Component { /** * Handle any mousedown event received by the track * @param {SyntheticEvent} event - User event - * @param {Slider} slider - React component + * @param {Track} track - React component * @param {Point} position - Mousedown position */ handleTrackMouseDown(event, track, position) { @@ -450,7 +528,6 @@ export default class InputRange extends React.Component { /** * Handle the start of any user-triggered event - * @param {SyntheticEvent} event - User event */ handleInteractionStart() { const _this = internals.get(this); @@ -464,7 +541,6 @@ export default class InputRange extends React.Component { /** * Handle the end of any user-triggered event - * @param {SyntheticEvent} event - User event */ handleInteractionEnd() { const _this = internals.get(this); @@ -591,65 +667,3 @@ export default class InputRange extends React.Component { ); } } - -/** - * Accepted propTypes of InputRange - * @static {Object} - * @property {Function} ariaLabelledby - * @property {Function} ariaControls - * @property {Function} classNames - * @property {Function} defaultValue - * @property {Function} disabled - * @property {Function} formatLabel - * @property {Function} labelPrefix - * @property {Function} labelSuffix - * @property {Function} maxValue - * @property {Function} minValue - * @property {Function} name - * @property {Function} onChange - * @property {Function} onChangeComplete - * @property {Function} step - * @property {Function} value - */ -InputRange.propTypes = { - ariaLabelledby: React.PropTypes.string, - ariaControls: React.PropTypes.string, - classNames: React.PropTypes.objectOf(React.PropTypes.string), - defaultValue: maxMinValuePropType, - disabled: React.PropTypes.bool, - formatLabel: React.PropTypes.func, - labelPrefix: React.PropTypes.string, - labelSuffix: React.PropTypes.string, - maxValue: maxMinValuePropType, - minValue: maxMinValuePropType, - name: React.PropTypes.string, - onChange: React.PropTypes.func.isRequired, - onChangeComplete: React.PropTypes.func, - step: React.PropTypes.number, - value: maxMinValuePropType, -}; - -/** - * Default props of InputRange - * @static {Object} - * @property {Object.} defaultClassNames - * @property {Range|number} defaultValue - * @property {boolean} disabled - * @property {string} labelPrefix - * @property {string} labelSuffix - * @property {number} maxValue - * @property {number} minValue - * @property {number} step - * @property {Range|number} value - */ -InputRange.defaultProps = { - classNames: defaultClassNames, - defaultValue: 0, - disabled: false, - labelPrefix: '', - labelSuffix: '', - maxValue: 10, - minValue: 0, - step: 1, - value: null, -}; diff --git a/src/js/InputRange/Label.js b/src/js/InputRange/Label.js new file mode 100644 index 0000000..dc565a5 --- /dev/null +++ b/src/js/InputRange/Label.js @@ -0,0 +1,32 @@ +import React from 'react'; + +/** + * Label React component + */ +export default function Label(props) { + const { children, className, containerClassName, formatLabel } = props; + const labelValue = formatLabel ? formatLabel(children) : children; + + return ( + + + { labelValue } + + + ); +} + +/** + * Accepted propTypes of Label + * @type {Object} + * @property {Function} children + * @property {Function} className + * @property {Function} containerClassName + * @property {Function} formatLabel + */ +Label.propTypes = { + children: React.PropTypes.node.isRequired, + className: React.PropTypes.string.isRequired, + containerClassName: React.PropTypes.string.isRequired, + formatLabel: React.PropTypes.func, +}; diff --git a/src/InputRange/Slider.js b/src/js/InputRange/Slider.js similarity index 73% rename from src/InputRange/Slider.js rename to src/js/InputRange/Slider.js index a9eea39..0f13329 100644 --- a/src/InputRange/Slider.js +++ b/src/js/InputRange/Slider.js @@ -1,14 +1,9 @@ -/** - * @module InputRange/Slider - */ - import React from 'react'; import Label from './Label'; -import { autobind } from './util'; +import { autobind } from '../utils'; /** * Get the owner document of slider - * @private * @param {Slider} slider - React component * @return {Document} Document */ @@ -36,11 +31,43 @@ function getStyle(slider) { /** * Slider React component - * @class - * @extends React.Component - * @param {Object} props - React component props */ export default class Slider extends React.Component { + /** + * Accepted propTypes of Slider + * @return {Object} + * @property {Function} ariaLabelledby + * @property {Function} ariaControls + * @property {Function} className + * @property {Function} formatLabel + * @property {Function} maxValue + * @property {Function} minValue + * @property {Function} onSliderKeyDown + * @property {Function} onSliderMouseMove + * @property {Function} percentage + * @property {Function} type + * @property {Function} value + */ + static get propTypes() { + return { + ariaLabelledby: React.PropTypes.string, + ariaControls: React.PropTypes.string, + classNames: React.PropTypes.objectOf(React.PropTypes.string).isRequired, + formatLabel: React.PropTypes.func, + maxValue: React.PropTypes.number, + minValue: React.PropTypes.number, + onSliderKeyDown: React.PropTypes.func.isRequired, + onSliderMouseMove: React.PropTypes.func.isRequired, + percentage: React.PropTypes.number.isRequired, + type: React.PropTypes.string.isRequired, + value: React.PropTypes.number.isRequired, + }; + } + + /** + * Slider constructor + * @param {Object} props - React component props + */ constructor(props) { super(props); @@ -67,7 +94,6 @@ export default class Slider extends React.Component { /** * Handle any mousedown event received by the component - * @param {SyntheticEvent} event - User event */ handleMouseDown() { const document = getDocument(this); @@ -79,7 +105,6 @@ export default class Slider extends React.Component { /** * Handle any mouseup event received by the component - * @param {SyntheticEvent} event - User event */ handleMouseUp() { const document = getDocument(this); @@ -120,7 +145,6 @@ export default class Slider extends React.Component { /** * Handle any touchend event received by the component - * @param {SyntheticEvent} event - User event */ handleTouchEnd(event) { const document = getDocument(this); @@ -164,7 +188,7 @@ export default class Slider extends React.Component { aria-controls={ this.props.ariaControls } aria-valuemax={ this.props.maxValue } aria-valuemin={ this.props.minValue } - aria-valuenow={ this.props.formatLabel ? this.props.formatLabel( this.props.value ) : this.props.value } + aria-valuenow={ this.props.value } className={ classNames.slider } draggable="false" href="#" @@ -172,38 +196,8 @@ export default class Slider extends React.Component { onKeyDown={ this.handleKeyDown } onMouseDown={ this.handleMouseDown } onTouchStart={ this.handleTouchStart } - role="slider"> - + role="slider" /> ); } } - -/** - * Accepted propTypes of Slider - * @static {Object} - * @property {Function} ariaLabelledby - * @property {Function} ariaControls - * @property {Function} className - * @property {Function} formatLabel - * @property {Function} maxValue - * @property {Function} minValue - * @property {Function} onSliderKeyDown - * @property {Function} onSliderMouseMove - * @property {Function} percentage - * @property {Function} type - * @property {Function} value - */ -Slider.propTypes = { - ariaLabelledby: React.PropTypes.string, - ariaControls: React.PropTypes.string, - classNames: React.PropTypes.objectOf(React.PropTypes.string), - formatLabel: React.PropTypes.func, - maxValue: React.PropTypes.number, - minValue: React.PropTypes.number, - onSliderKeyDown: React.PropTypes.func.isRequired, - onSliderMouseMove: React.PropTypes.func.isRequired, - percentage: React.PropTypes.number.isRequired, - type: React.PropTypes.string.isRequired, - value: React.PropTypes.number.isRequired, -}; diff --git a/src/InputRange/Track.js b/src/js/InputRange/Track.js similarity index 73% rename from src/InputRange/Track.js rename to src/js/InputRange/Track.js index 80e565a..2ededd7 100644 --- a/src/InputRange/Track.js +++ b/src/js/InputRange/Track.js @@ -1,9 +1,5 @@ -/** - * @module InputRange/Track - */ - import React from 'react'; -import { autobind } from './util'; +import { autobind } from '../utils'; /** * Get the CSS styles for an active track @@ -26,11 +22,29 @@ function getActiveTrackStyle(track) { /** * Track React component - * @class - * @extends React.Component - * @param {Object} props - React component props */ export default class Track extends React.Component { + /** + * Accepted propTypes of Track + * @return {Object} + * @property {Function} children + * @property {Function} classNames + * @property {Function} onTrackMouseDown + * @property {Function} percentages + */ + static get propTypes() { + return { + children: React.PropTypes.node.isRequired, + classNames: React.PropTypes.objectOf(React.PropTypes.string).isRequired, + onTrackMouseDown: React.PropTypes.func.isRequired, + percentages: React.PropTypes.objectOf(React.PropTypes.number).isRequired, + }; + } + + /** + * Track constructor + * @param {Object} props - React component props + */ constructor(props) { super(props); @@ -93,25 +107,9 @@ export default class Track extends React.Component { ref="track">
-
+ className={ classNames.trackActive } /> { this.props.children } ); } } - -/** - * Accepted propTypes of Track - * @static {Object} - * @property {Function} children - * @property {Function} classNames - * @property {Function} onTrackMouseDown - * @property {Function} percentages - */ -Track.propTypes = { - children: React.PropTypes.node, - classNames: React.PropTypes.objectOf(React.PropTypes.string), - onTrackMouseDown: React.PropTypes.func.isRequired, - percentages: React.PropTypes.objectOf(React.PropTypes.number).isRequired, -}; diff --git a/src/InputRange/defaultClassNames.js b/src/js/InputRange/defaultClassNames.js similarity index 90% rename from src/InputRange/defaultClassNames.js rename to src/js/InputRange/defaultClassNames.js index ea9bf69..db9ddaf 100644 --- a/src/InputRange/defaultClassNames.js +++ b/src/js/InputRange/defaultClassNames.js @@ -1,10 +1,6 @@ -/** - * @module InputRange/defaultClassNames - */ - /** * An object containing class names -* @const {Object} +* @type {Object} * @property {string} component * @property {string} labelContainer * @property {string} labelMax @@ -15,7 +11,7 @@ * @property {string} trackActive * @property {string} trackContainer */ -export default { +const defaultClassNames = { component: 'InputRange', labelContainer: 'InputRange-labelContainer', labelMax: 'InputRange-label InputRange-label--max', @@ -27,3 +23,5 @@ export default { trackContainer: 'InputRange-track InputRange-track--container', disabled: 'is-disabled', }; + +export default defaultClassNames; diff --git a/src/InputRange/propTypes.js b/src/js/InputRange/propTypes.js similarity index 92% rename from src/InputRange/propTypes.js rename to src/js/InputRange/propTypes.js index 2dc1936..8278443 100644 --- a/src/InputRange/propTypes.js +++ b/src/js/InputRange/propTypes.js @@ -1,8 +1,4 @@ -/** - * @module InputRange/maxMinValuePropType - */ - -import { isNumber, objectOf } from './util'; +import { isNumber, objectOf } from '../utils'; /** * A prop type accepting a range of numeric values or a single numeric value @@ -39,4 +35,6 @@ export function maxMinValuePropType(props) { if (value < minValue || value > maxValue) { return new Error('`value` must be within `minValue` and `maxValue`'); } + + return undefined; } diff --git a/src/InputRange/valueTransformer.js b/src/js/InputRange/valueTransformer.js similarity index 74% rename from src/InputRange/valueTransformer.js rename to src/js/InputRange/valueTransformer.js index 487baf9..a52fafa 100644 --- a/src/InputRange/valueTransformer.js +++ b/src/js/InputRange/valueTransformer.js @@ -1,17 +1,12 @@ -/** - * @module InputRange/valueTransformer - */ - -import { clamp, isEmpty, isNumber, objectOf } from './util'; +import { clamp, isEmpty, isNumber, objectOf } from '../utils'; /** * Convert position into percentage value - * @static * @param {InputRange} inputRange * @param {Point} position * @return {number} Percentage value */ -function percentageFromPosition(inputRange, position) { +export function percentageFromPosition(inputRange, position) { const length = inputRange.trackClientRect.width; const sizePerc = position.x / length; @@ -20,27 +15,25 @@ function percentageFromPosition(inputRange, position) { /** * Convert position into model value - * @static * @param {InputRange} inputRange * @param {Point} position * @return {number} Model value */ -function valueFromPosition(inputRange, position) { +export function valueFromPosition(inputRange, position) { const sizePerc = percentageFromPosition(inputRange, position); const valueDiff = inputRange.props.maxValue - inputRange.props.minValue; - const value = inputRange.props.minValue + valueDiff * sizePerc; + const value = inputRange.props.minValue + (valueDiff * sizePerc); return value; } /** * Extract values from props - * @static * @param {InputRange} inputRange * @param {Point} [props=inputRange.props] * @return {Range} Range values */ -function valuesFromProps(inputRange, { props } = inputRange) { +export function valuesFromProps(inputRange, { props } = inputRange) { if (inputRange.isMultiValue) { let values = props.value; @@ -61,12 +54,11 @@ function valuesFromProps(inputRange, { props } = inputRange) { /** * Convert value into percentage value - * @static * @param {InputRange} inputRange * @param {number} value * @return {number} Percentage value */ -function percentageFromValue(inputRange, value) { +export function percentageFromValue(inputRange, value) { const validValue = clamp(value, inputRange.props.minValue, inputRange.props.maxValue); const valueDiff = inputRange.props.maxValue - inputRange.props.minValue; const valuePerc = (validValue - inputRange.props.minValue) / valueDiff; @@ -76,12 +68,11 @@ function percentageFromValue(inputRange, value) { /** * Convert values into percentage values - * @static * @param {InputRange} inputRange * @param {Range} values * @return {Range} Percentage values */ -function percentagesFromValues(inputRange, values) { +export function percentagesFromValues(inputRange, values) { const percentages = { min: percentageFromValue(inputRange, values.min), max: percentageFromValue(inputRange, values.max), @@ -92,12 +83,11 @@ function percentagesFromValues(inputRange, values) { /** * Convert value into position - * @static * @param {InputRange} inputRange * @param {number} value * @return {Point} Position */ -function positionFromValue(inputRange, value) { +export function positionFromValue(inputRange, value) { const length = inputRange.trackClientRect.width; const valuePerc = percentageFromValue(inputRange, value); const positionValue = valuePerc * length; @@ -110,12 +100,11 @@ function positionFromValue(inputRange, value) { /** * Convert a range of values into positions - * @static * @param {InputRange} inputRange * @param {Range} values - * @return {Object.} + * @return {Object} */ -function positionsFromValues(inputRange, values) { +export function positionsFromValues(inputRange, values) { const positions = { min: positionFromValue(inputRange, values.min), max: positionFromValue(inputRange, values.max), @@ -126,12 +115,11 @@ function positionsFromValues(inputRange, values) { /** * Extract a position from an event - * @static * @param {InputRange} inputRange * @param {Event} event * @return {Point} */ -function positionFromEvent(inputRange, event) { +export function positionFromEvent(inputRange, event) { const trackClientRect = inputRange.trackClientRect; const length = trackClientRect.width; const { clientX } = event.touches ? event.touches[0] : event; @@ -145,23 +133,10 @@ function positionFromEvent(inputRange, event) { /** * Convert a value into a step value - * @static * @param {InputRange} inputRange * @param {number} value * @return {number} Step value */ -function stepValueFromValue(inputRange, value) { +export function stepValueFromValue(inputRange, value) { return Math.round(value / inputRange.props.step) * inputRange.props.step; } - -export default { - percentageFromPosition, - percentageFromValue, - percentagesFromValues, - positionFromEvent, - positionFromValue, - positionsFromValues, - stepValueFromValue, - valueFromPosition, - valuesFromProps, -}; diff --git a/src/js/index.js b/src/js/index.js new file mode 100644 index 0000000..a2eddd1 --- /dev/null +++ b/src/js/index.js @@ -0,0 +1,3 @@ +import InputRange from './InputRange/InputRange'; + +export default InputRange; diff --git a/src/InputRange/util.js b/src/js/utils/index.js similarity index 88% rename from src/InputRange/util.js rename to src/js/utils/index.js index c1e74a0..1cb4cf4 100644 --- a/src/InputRange/util.js +++ b/src/js/utils/index.js @@ -1,7 +1,3 @@ -/** - * @module InputRange/util - */ - /** * @callback predicateFn * @param {*} value @@ -10,7 +6,6 @@ /** * Clamp a value between a min and max value - * @static * @param {number} value * @param {number} min * @param {number} max @@ -22,18 +17,16 @@ export function clamp(value, min, max) { /** * Extend an Object - * @static * @param {Object} object - Destination object * @param {...Object} sources - Source objects * @return {Object} Destination object, extended with members from sources */ -export function extend() { - return Object.assign.apply(Object, arguments); +export function extend(object, ...sources) { + return Object.assign(object, ...sources); } /** * Check if a value is included in an array - * @static * @param {Array} array * @param {number} value * @return {boolean} @@ -44,9 +37,8 @@ export function includes(array, value) { /** * Return a new object without the specified keys - * @static * @param {Object} obj - * @param {Array.} omitKeys + * @param {string[]} omitKeys * @return {Object} */ export function omit(obj, omitKeys) { @@ -64,7 +56,6 @@ export function omit(obj, omitKeys) { /** * Captialize a string - * @static * @param {string} string * @return {string} */ @@ -74,18 +65,19 @@ export function captialize(string) { /** * Calculate the distance between pointA and pointB - * @static * @param {Point} pointA * @param {Point} pointB * @return {number} Distance */ export function distanceTo(pointA, pointB) { - return Math.sqrt(Math.pow(pointB.x - pointA.x, 2) + Math.pow(pointB.y - pointA.y, 2)); + const xDiff = (pointB.x - pointA.x) ** 2; + const yDiff = (pointB.y - pointA.y) ** 2; + + return Math.sqrt(xDiff + yDiff); } /** * Calculate the absolute difference between two numbers - * @static * @param {number} numA * @param {number} numB * @return {number} @@ -96,7 +88,6 @@ export function length(numA, numB) { /** * Check if a value is a number - * @static * @param {*} value * @return {Boolean} */ @@ -106,7 +97,6 @@ export function isNumber(value) { /** * Check if a value is an object - * @static * @param {*} value * @return {Boolean} */ @@ -116,7 +106,6 @@ export function isObject(value) { /** * Check if a value is defined - * @static * @param {*} value * @return {Boolean} */ @@ -126,7 +115,6 @@ export function isDefined(value) { /** * Check if an object is empty - * @static * @param {Object|Array} obj * @return {Boolean} */ @@ -144,7 +132,6 @@ export function isEmpty(obj) { /** * Check if all items in an array match a predicate - * @static * @param {Array} array * @param {predicateFn} predicate * @return {Boolean} @@ -165,10 +152,9 @@ export function arrayOf(array, predicate) { /** * Check if all items in an object match a predicate - * @static * @param {Object} object * @param {predicateFn} predicate - * @param {Array.} keys + * @param {string[]} keys * @return {Boolean} */ export function objectOf(object, predicate, keys) { @@ -191,11 +177,11 @@ export function objectOf(object, predicate, keys) { /** * Bind all methods of an object to itself - * @static - * @param {Array.} methodNames + * @param {Function[]} methodNames * @param {Object} instance */ export function autobind(methodNames, instance) { + /* eslint-disable no-param-reassign */ methodNames.forEach((methodName) => { instance[methodName] = instance[methodName].bind(instance); }); diff --git a/src/scss/InputRange/InputRange.scss b/src/scss/InputRange/InputRange.scss new file mode 100644 index 0000000..8b66594 --- /dev/null +++ b/src/scss/InputRange/InputRange.scss @@ -0,0 +1,11 @@ +@import 'InputRangeVariables'; +@import 'InputRangeSlider'; +@import 'InputRangeLabel'; +@import 'InputRangeLabelContainer'; +@import 'InputRangeTrack'; + +.InputRange { + height: $InputRange-slider-height; + position: relative; + width: 100%; +} diff --git a/scss/_InputRangeLabel.scss b/src/scss/InputRange/_InputRangeLabel.scss similarity index 100% rename from scss/_InputRangeLabel.scss rename to src/scss/InputRange/_InputRangeLabel.scss diff --git a/scss/_InputRangeLabelContainer.scss b/src/scss/InputRange/_InputRangeLabelContainer.scss similarity index 100% rename from scss/_InputRangeLabelContainer.scss rename to src/scss/InputRange/_InputRangeLabelContainer.scss diff --git a/scss/_InputRangeSlider.scss b/src/scss/InputRange/_InputRangeSlider.scss similarity index 100% rename from scss/_InputRangeSlider.scss rename to src/scss/InputRange/_InputRangeSlider.scss diff --git a/scss/_InputRangeTrack.scss b/src/scss/InputRange/_InputRangeTrack.scss similarity index 92% rename from scss/_InputRangeTrack.scss rename to src/scss/InputRange/_InputRangeTrack.scss index 9eee8d5..7995022 100644 --- a/scss/_InputRangeTrack.scss +++ b/src/scss/InputRange/_InputRangeTrack.scss @@ -5,7 +5,7 @@ display: block; height: $InputRange-track-height; position: relative; - transition: $inputRange-track-transition; + transition: $InputRange-track-transition; .InputRange.is-disabled & { background: $InputRange-track--is-disabled-background; diff --git a/scss/_InputRangeVariables.scss b/src/scss/InputRange/_InputRangeVariables.scss similarity index 95% rename from scss/_InputRangeVariables.scss rename to src/scss/InputRange/_InputRangeVariables.scss index 13eb26a..b9d54ea 100644 --- a/scss/_InputRangeVariables.scss +++ b/src/scss/InputRange/_InputRangeVariables.scss @@ -21,6 +21,6 @@ $InputRange-label-color: $InputRange-neutralColor !default; // InputRange-track $InputRange-track-background: $InputRange-neutralLightColor !default; $InputRange-track-height: 0.3rem !default; -$inputRange-track-transition: left 0.3s ease-out, width 0.3s ease-out !default; +$InputRange-track-transition: left 0.3s ease-out, width 0.3s ease-out !default; $InputRange-track--active-background: $InputRange-primaryColor !default; $InputRange-track--is-disabled-background: $InputRange-neutralLightColor !default; diff --git a/src/scss/index.scss b/src/scss/index.scss new file mode 100644 index 0000000..507979c --- /dev/null +++ b/src/scss/index.scss @@ -0,0 +1 @@ +@import 'InputRange/InputRange'; diff --git a/tasks/build.js b/tasks/build.js deleted file mode 100644 index 812f64a..0000000 --- a/tasks/build.js +++ /dev/null @@ -1,15 +0,0 @@ -import gulp from 'gulp'; - -gulp.task('build', [ - 'script', - 'style', -]); - -gulp.task('build:dist', [ - 'script:dist', - 'style:dist', -]); - -gulp.task('build:lib', [ - 'script:lib', -]); diff --git a/tasks/clean.js b/tasks/clean.js deleted file mode 100644 index 4ccefd4..0000000 --- a/tasks/clean.js +++ /dev/null @@ -1,43 +0,0 @@ -import gulp from 'gulp'; -import del from 'del'; -import config from './config'; - -gulp.task('clean', [ - 'clean:script', - 'clean:style', - 'clean:script:example', - 'clean:style:example', -]); - -gulp.task('clean:dist', [ - 'clean:script:dist', - 'clean:style:dist', -]); - -gulp.task('clean:script', (callback) => { - del(config.clean.script.src, callback); -}); - -gulp.task('clean:style', (callback) => { - del(config.clean.style.src, callback); -}); - -gulp.task('clean:lib', (callback) => { - del(config.clean.lib.src, callback); -}); - -gulp.task('clean:style:example', (callback) => { - del(config.clean.example.style.src, callback); -}); - -gulp.task('clean:script:example', (callback) => { - del(config.clean.example.script.src, callback); -}); - -gulp.task('clean:style:dist', (callback) => { - del(config.clean.dist.style.src, callback); -}); - -gulp.task('clean:script:dist', (callback) => { - del(config.clean.dist.script.src, callback); -}); diff --git a/tasks/config.js b/tasks/config.js deleted file mode 100644 index 4628750..0000000 --- a/tasks/config.js +++ /dev/null @@ -1,229 +0,0 @@ -import path from 'path'; -import fs from 'fs'; - -const cwd = process.cwd(); -const pkgPath = path.resolve('package.json'); -const pkg = JSON.parse(fs.readFileSync(pkgPath)); - -// Base config -const config = { - name: pkg.name, - version: pkg.version, - moduleName: 'InputRange', - src: 'src', - scss: 'scss', - build: 'build', - dist: 'dist', - lib: 'lib', - test: 'test', - tasks: 'tasks', - example: { - js: 'example/js', - scss: 'example/scss', - build: 'example/build', - }, -}; - -// Script config -config.script = { - build: { - paths: [ - config.src, - ], - entries: [ - config.src + '/' + config.moduleName, - ], - external: 'react', - output: pkg.name + '.js', - standalone: config.moduleName, - dest: config.build, - }, - - lib: { - src: config.src + '/**/*.js', - dest: config.lib, - }, - - example: { - paths: [ - config.build, - config.src, - config.example.js, - ], - entries: [ - config.example.js + '/example.js', - ], - noParse: [ - path.join(cwd, config.build, config.name + '.js'), - ], - output: 'example.js', - dest: config.example.build, - debug: true, - }, - - dist: { - src: config.build + '/**/*.js', - dest: config.dist, - rename: { - suffix: '.min', - }, - }, -}; - -// Style config -config.style = { - build: { - src: config.scss + '/**/*.scss', - output: pkg.name + '.css', - dest: config.build, - sass: { - includePaths: [ - config.scss, - ], - }, - }, - - dist: { - src: config.build + '/**/*.css', - dest: config.dist, - rename: { - suffix: '.min', - }, - }, - - example: { - src: config.example.scss + '/**/*.scss', - output: 'example.css', - dest: config.example.build, - sass: { - includePaths: [ - config.build, - config.scss, - config.example.scss, - ], - }, - }, -}; - -// Clean config -config.clean = { - script: { - src: [ - config.build + '/**/*.js*', - ], - }, - - lib: { - src: [ - config.lib + '/**/*', - ], - }, - - style: { - src: [ - config.build + '/**/*.css*', - ], - }, - - example: { - style: { - src: [ - config.example.build + '/**/*.css*', - ], - }, - script: { - src: [ - config.example.build + '/**/*.js*', - ], - }, - }, - - dist: { - style: { - src: [ - config.dist + '/**/*.css*', - ], - }, - script: { - src: [ - config.dist + '/**/*.js*', - ], - }, - }, -}; - -// Connect config -config.connect = { - server: { - root: 'example', - livereload: true, - port: 8080, - }, -}; - -// Watch config -config.watch = { - style: { - src: [ - config.style.build.src, - config.style.example.src, - ], - }, - - script: { - src: [ - config.src + '/**/*.js', - config.example.js + '/**/*.js', - config.test + '/**/*.js', - ], - build: config.script.build, - example: config.script.example, - }, - - task: { - src: [ - config.tasks + '/**/*.js', - ], - }, -}; - -// Lint config -config.lint = { - script: { - src: [ - config.src + '/**/*.js', - config.test + '/**/*.js', - ], - }, - - task: { - src: config.tasks + '/**/*.js', - }, - - style: { - src: config.scss + '/**/*.scss', - bundleExec: true, - }, -}; - -// Test config -config.test = { - unit: { - configFile: cwd + '/karma.conf.js', - autoWatch: false, - singleRun: true, - }, - watch: { - configFile: cwd + '/karma.conf.js', - }, -}; - -// Release config -config.release = { - src: [ - pkgPath, - 'bower.json', - ], -}; - -export default config; diff --git a/tasks/connect.js b/tasks/connect.js deleted file mode 100644 index c5e4c54..0000000 --- a/tasks/connect.js +++ /dev/null @@ -1,7 +0,0 @@ -import gulp from 'gulp'; -import connect from 'gulp-connect'; -import config from './config'; - -gulp.task('connect', () => { - connect.server(config.connect.server); -}); diff --git a/tasks/default.js b/tasks/default.js deleted file mode 100644 index 81b224a..0000000 --- a/tasks/default.js +++ /dev/null @@ -1,5 +0,0 @@ -import gulp from 'gulp'; - -gulp.task('default', [ - 'run', -]); diff --git a/tasks/helpers/script-helper.js b/tasks/helpers/script-helper.js deleted file mode 100644 index 6203917..0000000 --- a/tasks/helpers/script-helper.js +++ /dev/null @@ -1,66 +0,0 @@ -import gulp from 'gulp'; -import gutil from 'gulp-util'; -import browserify from 'browserify'; -import babelify from 'babelify'; -import watchify from 'watchify'; -import source from 'vinyl-source-stream'; -import buffer from 'vinyl-buffer'; -import _ from 'lodash'; - -function bundleScript(bundler, output, dest, cb) { - function onError(error) { - gutil.log(gutil.colors.red('Browserify Error' + error)); - } - - function onEnd() { - if (cb) { - cb(); - } - } - - return bundler.bundle() - .on('error', onError) - .on('end', onEnd) - .pipe(source(output)) - .pipe(buffer()) - .pipe(gulp.dest(dest)); -} - -function compileScript(watch, opts, cb) { - const acceptedOpts = _.pick(opts, 'paths', 'entries', 'noParse', 'debug', 'standalone'); - const browserifyOpts = _.defaults({}, acceptedOpts, watchify.args); - const babelifyOpts = { comments: false }; - - let bundler = browserify(browserifyOpts).transform(babelify.configure(babelifyOpts)); - - if (opts.external) { - bundler.external(opts.external); - } - - if (browserifyOpts.noParse) { - browserifyOpts.noParse = _.map(browserifyOpts.noParse, (path) => { - return require.resolve(path); - }); - } - - if (watch) { - bundler = watchify(bundler); - - gutil.log('Watching ' + gutil.colors.yellow(opts.entries)); - - bundler.on('update', () => { - gutil.log('Bundling ' + gutil.colors.green(opts.output)); - - return bundleScript(bundler, opts.output, opts.dest, cb); - }); - } - - return bundleScript(bundler, opts.output, opts.dest, cb); -} - -const scriptHelper = { - bundleScript, - compileScript, -}; - -export default scriptHelper; diff --git a/tasks/lint.js b/tasks/lint.js deleted file mode 100644 index 5a183ab..0000000 --- a/tasks/lint.js +++ /dev/null @@ -1,33 +0,0 @@ -import gulp from 'gulp'; -import eslint from 'gulp-eslint'; -import scsslint from 'gulp-scss-lint'; -import config from './config'; -import _ from 'lodash'; - -gulp.task('lint', [ - 'lint:script', - 'lint:task', - 'lint:style', -]); - -gulp.task('lint:script', () => { - return gulp.src(config.lint.script.src) - .pipe(eslint()) - .pipe(eslint.format()) - .pipe(eslint.failOnError()); -}); - -gulp.task('lint:task', () => { - return gulp.src(config.lint.task.src) - .pipe(eslint()) - .pipe(eslint.format()) - .pipe(eslint.failOnError()); -}); - -gulp.task('lint:style', () => { - const options = _.omit(config.lint.style, 'src'); - - return gulp.src(config.lint.style.src) - .pipe(scsslint(options)) - .pipe(scsslint.failReporter()); -}); diff --git a/tasks/release.js b/tasks/release.js deleted file mode 100644 index 0dbd888..0000000 --- a/tasks/release.js +++ /dev/null @@ -1,69 +0,0 @@ -import gulp from 'gulp'; -import gutil from 'gulp-util'; -import bump from 'gulp-bump'; -import prompt from 'gulp-prompt'; -import git from 'gulp-git'; -import semver from 'semver'; -import runSequence from 'run-sequence'; -import config from './config'; - -let newVersion = config.version; - -gulp.task('release', (callback) => { - runSequence( - 'releasePrompt', - 'build:dist', - 'releaseBump', - 'releaseCommit', - 'releaseTag', - callback - ); -}); - -gulp.task('releasePrompt', () => { - const promptConfig = { - type: 'list', - name: 'releaseType', - message: 'What\'s the type of this release?', - choices: [ - { - value: 'patch', - name: gutil.colors.yellow('Patch: ' + semver.inc(config.version, 'patch')), - }, - { - value: 'minor', - name: gutil.colors.yellow('Minor: ' + semver.inc(config.version, 'minor')), - }, - { - value: 'major', - name: gutil.colors.yellow('Major: ' + semver.inc(config.version, 'major')), - }, - ], - }; - - return gulp.src('./', { read: false }) - .pipe(prompt.prompt(promptConfig, (response) => { - newVersion = semver.inc(config.version, response.releaseType); - })); -}); - -gulp.task('releaseBump', () => { - return gulp.src(config.release.src) - .pipe(bump({ version: newVersion })) - .pipe(gulp.dest('./')); -}); - -gulp.task('releaseCommit', () => { - const message = `Release v${newVersion}`; - - return gulp.src('./') - .pipe(git.add()) - .pipe(git.commit(message)); -}); - -gulp.task('releaseTag', (callback) => { - const message = `Release v${newVersion}`; - const tag = `v${newVersion}`; - - git.tag(tag, message, callback); -}); diff --git a/tasks/run.js b/tasks/run.js deleted file mode 100644 index 8c93493..0000000 --- a/tasks/run.js +++ /dev/null @@ -1,10 +0,0 @@ -import gulp from 'gulp'; -import runSequence from 'run-sequence'; - -gulp.task('run', (callback) => { - runSequence( - 'build', - ['watch', 'connect'], - callback - ); -}); diff --git a/tasks/script.js b/tasks/script.js deleted file mode 100644 index e4b8fb4..0000000 --- a/tasks/script.js +++ /dev/null @@ -1,34 +0,0 @@ -import gulp from 'gulp'; -import babel from 'gulp-babel'; -import uglify from 'gulp-uglify'; -import rename from 'gulp-rename'; -import config from './config'; -import { compileScript } from './helpers/script-helper'; - -gulp.task('script', [ - 'lint:task', - 'script:build', - 'script:example', -]); - -gulp.task('script:build', ['lint:script', 'test:script', 'clean:script'], () => { - return compileScript(false, config.script.build); -}); - -gulp.task('script:dist', ['script:build', 'clean:script:dist'], () => { - return gulp.src(config.script.dist.src) - .pipe(gulp.dest(config.script.dist.dest)) - .pipe(uglify()) - .pipe(rename(config.script.dist.rename)) - .pipe(gulp.dest(config.script.dist.dest)); -}); - -gulp.task('script:lib', ['lint:script', 'test:script', 'clean:lib'], () => { - return gulp.src(config.script.lib.src) - .pipe(babel()) - .pipe(gulp.dest(config.script.lib.dest)); -}); - -gulp.task('script:example', ['clean:script:example', 'script:build'], () => { - return compileScript(false, config.script.example); -}); diff --git a/tasks/style.js b/tasks/style.js deleted file mode 100644 index 874bddd..0000000 --- a/tasks/style.js +++ /dev/null @@ -1,43 +0,0 @@ -import gulp from 'gulp'; -import sass from 'gulp-sass'; -import minifyCss from 'gulp-minify-css'; -import rename from 'gulp-rename'; -import concat from 'gulp-concat'; -import postcss from 'gulp-postcss'; -import autoprefixer from 'autoprefixer-core'; -import config from './config'; - -const postcssPlugins = [ - autoprefixer({ - browsers: ['last 2 versions'], - }), -]; - -gulp.task('style', [ - 'style:build', - 'style:example', -]); - -gulp.task('style:build', ['lint:style', 'clean:style'], () => { - return gulp.src(config.style.build.src) - .pipe(sass(config.style.build.sass)) - .pipe(postcss(postcssPlugins)) - .pipe(concat(config.style.build.output)) - .pipe(gulp.dest(config.style.build.dest)); -}); - -gulp.task('style:dist', ['style:build', 'clean:style:dist'], () => { - return gulp.src(config.style.dist.src) - .pipe(gulp.dest(config.style.dist.dest)) - .pipe(minifyCss()) - .pipe(rename(config.style.dist.rename)) - .pipe(gulp.dest(config.style.dist.dest)); -}); - -gulp.task('style:example', ['clean:style:example', 'style:build'], () => { - return gulp.src(config.style.example.src) - .pipe(sass(config.style.example.sass)) - .pipe(postcss(postcssPlugins)) - .pipe(concat(config.style.example.output)) - .pipe(gulp.dest(config.style.example.dest)); -}); diff --git a/tasks/test.js b/tasks/test.js deleted file mode 100644 index a7cc059..0000000 --- a/tasks/test.js +++ /dev/null @@ -1,21 +0,0 @@ -import gulp from 'gulp'; -import config from './config'; -import { Server } from 'karma'; - -function startServer(options, done) { - const server = new Server(options, done); - - server.start(); -} - -gulp.task('test', [ - 'test:script', -]); - -gulp.task('test:script', (done) => { - startServer(config.test.unit, done); -}); - -gulp.task('test:script:watch', (done) => { - startServer(config.test.watch, done); -}); diff --git a/tasks/watch.js b/tasks/watch.js deleted file mode 100644 index 06e33be..0000000 --- a/tasks/watch.js +++ /dev/null @@ -1,25 +0,0 @@ -import gulp from 'gulp'; -import config from './config'; -import { compileScript } from './helpers/script-helper'; - -gulp.task('watch', [ - 'watch:script', - 'watch:style', - 'watch:task', - 'test:script:watch', -]); - -gulp.task('watch:script', () => { - compileScript(true, config.watch.script.example); - compileScript(true, config.watch.script.build, () => { - gulp.start('lint:script'); - }); -}); - -gulp.task('watch:style', () => { - gulp.watch(config.watch.style.src, ['style']); -}); - -gulp.task('watch:task', () => { - gulp.watch(config.watch.task.src, ['lint:task']); -}); diff --git a/test/InputRange.spec.js b/test/InputRange/InputRange.spec.js similarity index 98% rename from test/InputRange.spec.js rename to test/InputRange/InputRange.spec.js index d6cef12..4f9299d 100644 --- a/test/InputRange.spec.js +++ b/test/InputRange/InputRange.spec.js @@ -1,8 +1,8 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import InputRange from 'InputRange'; -import valueTransformer from '../src/InputRange/valueTransformer'; -import { renderComponent, rerenderComponent } from './TestUtil'; +import InputRange from '../../src/js/InputRange/InputRange'; +import * as valueTransformer from '../../src/js/InputRange/valueTransformer'; +import { renderComponent, rerenderComponent } from '../TestUtil'; let inputRange; let onChange; diff --git a/test/TestUtil.js b/test/TestUtil.js index aeb7ec8..4be6022 100644 --- a/test/TestUtil.js +++ b/test/TestUtil.js @@ -1,6 +1,6 @@ import ReactDOM from 'react-dom'; -function renderComponent(jsx) { +export function renderComponent(jsx) { let container = document.getElementById('container'); if (container) { @@ -14,7 +14,7 @@ function renderComponent(jsx) { return ReactDOM.render(jsx, container); } -function rerenderComponent(jsx) { +export function rerenderComponent(jsx) { const container = document.getElementById('container'); if (container) { @@ -23,10 +23,3 @@ function rerenderComponent(jsx) { return renderComponent(jsx); } - -const TestUtil = { - renderComponent, - rerenderComponent, -}; - -export default TestUtil; diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..6fadad8 --- /dev/null +++ b/test/index.js @@ -0,0 +1,5 @@ +import 'babel-polyfill'; + +const context = require.context('.', true, /\.spec$/); + +context.keys().forEach(context); diff --git a/webpack-example.config.js b/webpack-example.config.js new file mode 100644 index 0000000..b0689c5 --- /dev/null +++ b/webpack-example.config.js @@ -0,0 +1,43 @@ +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const SasslintPlugin = require('sasslint-webpack-plugin'); +const path = require('path'); + +const webpackExampleConfig = { + context: __dirname, + devtool: 'source-map', + entry: { + example: './example/js/index.js', + }, + output: { + filename: '[name].js', + }, + module: { + loaders: [ + { + exclude: /node_modules/, + loader: 'babel', + test: /\.js$/, + }, + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract('style', 'css!postcss!sass'), + }, + ], + preLoaders: [ + { + exclude: /node_modules/, + loader: 'eslint', + test: /\.js$/, + }, + ], + }, + plugins: [ + new ExtractTextPlugin('[name].css'), + new SasslintPlugin({ + glob: './src/scss/**/*.scss', + ignorePlugins: ['extract-text-webpack-plugin'], + }), + ], +}; + +module.exports = webpackExampleConfig; diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..d799df7 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,41 @@ +const { optimize: { DedupePlugin, UglifyJsPlugin } } = require('webpack'); +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const SasslintPlugin = require('sasslint-webpack-plugin'); + +const webpackConfig = { + context: __dirname, + devtool: 'source-map', + entry: { + 'react-input-range.css': './src/scss/index.scss', + 'react-input-range.js': './src/js/index.js', + 'react-input-range.min.js': './src/js/index.js', + }, + output: { + filename: '[name]', + path: './lib/bundle', + library: 'ReactInputRange', + libraryTarget: 'umd', + }, + module: { + loaders: [ + { + exclude: /node_modules/, + loader: 'babel', + test: /\.js$/, + }, + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract('style', 'css!postcss!sass'), + }, + ], + }, + plugins: [ + new DedupePlugin(), + new ExtractTextPlugin('[name]'), + new UglifyJsPlugin({ + test: /\.min\.js$/, + }), + ], +}; + +module.exports = webpackConfig;