diff --git a/README.md b/README.md index 08b4004..80bc15a 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,9 @@ onChange |Function |`onChange` callbac onChangeComplete |Function |`onChangeComplete` callback step |number |Increment/decrement value value |number | Object.<number> |Current value(s) (required) +Track |Function |Override default Track Component +Slider |Function |Override default Slider Component +Label |Function |Override default Label Component ## Development diff --git a/example/js/App.js b/example/js/App.js index fedacae..7446388 100644 --- a/example/js/App.js +++ b/example/js/App.js @@ -24,43 +24,43 @@ class App extends React.Component { }; } - handleValueChange(component, value) { + handleValueChange(value) { this.setState({ value: value || 0, }); } - handleValue2Change(component, value) { + handleValue2Change(value) { this.setState({ value2: value || 0, }); } - handleValue3Change(component, value) { + handleValue3Change(value) { this.setState({ value3: value || 0, }); } - handleValue4Change(component, values) { + handleValue4Change(values) { this.setState({ value4: values, }); } - handleValue5Change(component, values) { + handleValue5Change(values) { this.setState({ value5: values, }); } - handleValue6Change(component, values) { + handleValue6Change(values) { this.setState({ value6: values, }); } - handleChangeComplete(component, value) { + handleChangeComplete(value) { console.log(value); } @@ -78,6 +78,7 @@ class App extends React.Component { return (
} Array of HTML */ function renderSliders(inputRange) { - const { classNames } = inputRange.props; + const { classNames, Slider, Label } = inputRange.props; const sliders = []; const keys = getKeys(inputRange); const values = valueTransformer.valuesFromProps(inputRange); @@ -196,7 +184,8 @@ function renderSliders(inputRange) { percentage={ percentage } ref={ ref } type={ key } - value={ value } /> + value={ value } + Label={ Label } /> ); sliders.push(slider); @@ -211,20 +200,6 @@ function renderSliders(inputRange) { * @param {InputRange} inputRange - React component * @return {Array.} Array of HTML */ -function renderHiddenInputs(inputRange) { - const inputs = []; - const keys = getKeys(inputRange); - - for (const key of keys) { - const name = inputRange.isMultiValue ? `${inputRange.props.name}${captialize(key)}` : inputRange.props.name; - - const input = ( - - ); - } - - return inputs; -} /** * InputRange React component @@ -341,9 +316,9 @@ export default class InputRange extends React.Component { } if (this.isMultiValue) { - this.props.onChange(this, values); + this.props.onChange(values); } else { - this.props.onChange(this, values.max); + this.props.onChange(values.max); } } @@ -474,7 +449,7 @@ export default class InputRange extends React.Component { } if (_this.startValue !== this.props.value) { - this.props.onChangeComplete(this, this.props.value); + this.props.onChangeComplete(this.props.value); } _this.startValue = null; @@ -501,8 +476,6 @@ export default class InputRange extends React.Component { * @param {SyntheticEvent} event - User event */ handleMouseDown(event) { - const document = getDocument(this); - this.handleInteractionStart(event); document.addEventListener('mouseup', this.handleMouseUp); @@ -513,8 +486,6 @@ export default class InputRange extends React.Component { * @param {SyntheticEvent} event - User event */ handleMouseUp(event) { - const document = getDocument(this); - this.handleInteractionEnd(event); document.removeEventListener('mouseup', this.handleMouseUp); @@ -525,8 +496,6 @@ export default class InputRange extends React.Component { * @param {SyntheticEvent} event - User event */ handleTouchStart(event) { - const document = getDocument(this); - this.handleInteractionStart(event); document.addEventListener('touchend', this.handleTouchEnd); @@ -537,8 +506,6 @@ export default class InputRange extends React.Component { * @param {SyntheticEvent} event - User event */ handleTouchEnd(event) { - const document = getDocument(this); - this.handleInteractionEnd(event); document.removeEventListener('touchend', this.handleTouchEnd); @@ -549,7 +516,14 @@ export default class InputRange extends React.Component { * @return {string} Component JSX */ render() { - const { classNames } = this.props; + const { + classNames, + Label, + Track, + children, + showLabel, + renderHiddenInputs, + } = this.props; const componentClassName = getComponentClassName(this); const values = valueTransformer.valuesFromProps(this); const percentages = valueTransformer.percentagesFromValues(this, values); @@ -563,12 +537,14 @@ export default class InputRange extends React.Component { onKeyUp={ this.handleKeyUp } onMouseDown={ this.handleMouseDown } onTouchStart={ this.handleTouchStart }> - + {showLabel && ( + + )} - - - { renderHiddenInputs(this) } + {showLabel && ( + + )} + + { children } + + { renderHiddenInputs && getKeys(this).map((key) => { + const name = this.isMultiValue ? `${this.props.name}${captialize(key)}` : this.props.name; + const value = this.isMultiValue ? this.props.value[key] : this.props.value; + return ; + }) } ); } @@ -595,21 +579,26 @@ export default class InputRange extends React.Component { /** * Accepted propTypes of InputRange * @static {Object} - * @property {Function} ariaLabelledby + * @property {String} ariaLabelledby * @property {Function} ariaControls - * @property {Function} classNames - * @property {Function} defaultValue - * @property {Function} disabled + * @property {Object} classNames + * @property {String|Number} defaultValue + * @property {Boolean} disabled * @property {Function} formatLabel * @property {Function} labelPrefix * @property {Function} labelSuffix - * @property {Function} maxValue - * @property {Function} minValue - * @property {Function} name + * @property {Number} maxValue + * @property {Number} minValue + * @property {String} name * @property {Function} onChange * @property {Function} onChangeComplete * @property {Function} step * @property {Function} value + * @property {Function} Track + * @property {Function} Slider + * @property {Function} Label + * @property {Function} children + * @property {Boolean} showLabel */ InputRange.propTypes = { ariaLabelledby: React.PropTypes.string, @@ -622,11 +611,17 @@ InputRange.propTypes = { labelSuffix: React.PropTypes.string, maxValue: maxMinValuePropType, minValue: maxMinValuePropType, - name: React.PropTypes.string, + name: React.PropTypes.string.isRequired, onChange: React.PropTypes.func.isRequired, onChangeComplete: React.PropTypes.func, step: React.PropTypes.number, value: maxMinValuePropType, + Track: React.PropTypes.func, + Slider: React.PropTypes.func, + Label: React.PropTypes.func, + children: React.PropTypes.any, + showLabel: React.PropTypes.bool, + renderHiddenInputs: React.PropTypes.bool, }; /** @@ -641,6 +636,9 @@ InputRange.propTypes = { * @property {number} minValue * @property {number} step * @property {Range|number} value + * @property {Function} Track + * @property {Function} Slider + * @property {Function} Label */ InputRange.defaultProps = { classNames: defaultClassNames, @@ -652,4 +650,9 @@ InputRange.defaultProps = { minValue: 0, step: 1, value: null, + Track: DefaultTrack, + Slider: DefaultSlider, + Label: DefaultLabel, + showLabel: true, + renderHiddenInputs: true, }; diff --git a/src/InputRange/Slider.js b/src/InputRange/Slider.js index a9eea39..7ab8380 100644 --- a/src/InputRange/Slider.js +++ b/src/InputRange/Slider.js @@ -3,21 +3,9 @@ */ import React from 'react'; -import Label from './Label'; +import { default as DefaultLabel } from './Label'; import { autobind } from './util'; -/** - * Get the owner document of slider - * @private - * @param {Slider} slider - React component - * @return {Document} Document - */ -function getDocument(slider) { - const { slider: { ownerDocument } } = slider.refs; - - return ownerDocument; -} - /** * Get the style of slider based on its props * @private @@ -70,8 +58,6 @@ export default class Slider extends React.Component { * @param {SyntheticEvent} event - User event */ handleMouseDown() { - const document = getDocument(this); - // Event document.addEventListener('mousemove', this.handleMouseMove); document.addEventListener('mouseup', this.handleMouseUp); @@ -82,8 +68,6 @@ export default class Slider extends React.Component { * @param {SyntheticEvent} event - User event */ handleMouseUp() { - const document = getDocument(this); - // Event document.removeEventListener('mousemove', this.handleMouseMove); document.removeEventListener('mouseup', this.handleMouseUp); @@ -102,8 +86,6 @@ export default class Slider extends React.Component { * @param {SyntheticEvent} event - User event */ handleTouchStart(event) { - const document = getDocument(this); - event.preventDefault(); document.addEventListener('touchmove', this.handleTouchMove); @@ -123,8 +105,6 @@ export default class Slider extends React.Component { * @param {SyntheticEvent} event - User event */ handleTouchEnd(event) { - const document = getDocument(this); - event.preventDefault(); document.removeEventListener('touchmove', this.handleTouchMove); @@ -144,7 +124,7 @@ export default class Slider extends React.Component { * @return {string} Component JSX */ render() { - const classNames = this.props.classNames; + const { classNames, Label, children } = this.props; const style = getStyle(this); return ( @@ -174,6 +154,8 @@ export default class Slider extends React.Component { onTouchStart={ this.handleTouchStart } role="slider"> + + { children } ); } @@ -193,6 +175,8 @@ export default class Slider extends React.Component { * @property {Function} percentage * @property {Function} type * @property {Function} value + * @property {Function} Label + * @property {Function} children */ Slider.propTypes = { ariaLabelledby: React.PropTypes.string, @@ -206,4 +190,13 @@ Slider.propTypes = { percentage: React.PropTypes.number.isRequired, type: React.PropTypes.string.isRequired, value: React.PropTypes.number.isRequired, + Label: React.PropTypes.func, + children: React.PropTypes.any, +}; + +/** + * @property {Function} Label + */ +Slider.defaultProps = { + Label: DefaultLabel, }; diff --git a/src/InputRange/index.js b/src/InputRange/index.js index 1efe83a..5951dad 100644 --- a/src/InputRange/index.js +++ b/src/InputRange/index.js @@ -3,6 +3,9 @@ */ import InputRange from './InputRange'; +import Track from './Track'; +import Slider from './Slider'; +import Label from './Label'; /** * An object describing the position of a point @@ -19,3 +22,4 @@ import InputRange from './InputRange'; */ export default InputRange; +export {Track, Slider, Label}; diff --git a/test/InputRange.spec.js b/test/InputRange.spec.js index d6cef12..b80be8f 100644 --- a/test/InputRange.spec.js +++ b/test/InputRange.spec.js @@ -78,7 +78,7 @@ describe('InputRange', () => { it('should call `onChange` callback', () => { inputRange.updateValues(newValues); - expect(onChange).toHaveBeenCalledWith(inputRange, newValues); + expect(onChange).toHaveBeenCalledWith(newValues); }); }); @@ -92,7 +92,7 @@ describe('InputRange', () => { it('should call `onChange` callback', () => { inputRange.updateValues(newValues); - expect(onChange).toHaveBeenCalledWith(inputRange, newValues.max); + expect(onChange).toHaveBeenCalledWith(newValues.max); }); }); }); @@ -484,7 +484,7 @@ describe('InputRange', () => { ); slider.dispatchEvent(mouseUpEvent); - expect(onChangeComplete).toHaveBeenCalledWith(inputRange, value); + expect(onChangeComplete).toHaveBeenCalledWith(value); }); it('should call onChangeComplete if value has changed since the start of interaction when only defaultValue was provided', () => { @@ -501,7 +501,7 @@ describe('InputRange', () => { ); slider.dispatchEvent(mouseUpEvent); - expect(onChangeComplete).toHaveBeenCalledWith(inputRange, value); + expect(onChangeComplete).toHaveBeenCalledWith(value); }); it('should not call onChangeComplete if value has not changed since the start of interaction', () => {