Skip to content

Commit 7916d16

Browse files
committed
feat(rangeInput): add rangeInput widget (#2440)
* chore: add enzyme-to-json as dev dependency * feat(RangeInput): add component * refactor(RangeInput): rename label button to submit * feat(range-input): add widget * feat(stories): add range-input * refactor(utils-test): migrate to Jest expect * feat(utils): add depreacte function * fix(connectRangeSlider): pass all widgetOptions to rendering * fix(connectRangeSlider): refine at boundaries when defined and values are invalid * fix(range-input): pass null values when range is equal to values * refactor(connectRangeSlider): avoid useless variable * feat(connectRange): add connector * refactor(connectRangeSlider): deprecate * refactor(widget): use connectRange instead of connectRangeSlider * refactor(RangeInput): add expect case on state * refactor(range-input): update refine test * refactor(connectRange): parse next value as float * refactor(RangeInput): avoid test on input its handle by the connector * fix(range-input): remove comment * fix(css): remove lint error * refactor(range-input): use Math.pow instead of exponential operator * refactor(range-input): use 0 as default value for precision * chore(stories): update integer only story for floating number in RangeInput * refactor(connectRange): rename range to currentRange * fix(connectRangeSlider): refine at boundaries when defined and values are invalid * refactor(connectRangeSlider): deprecate * feat(connectRange-test): use original implementation inside clearRefinements mock * feat(connectRange): refine only when both value are valid * refactor(connectRange): avoid to pass by state for retrieve current refinement * refactor(range-input): dont rely on null * refactor(connectRange): avoid to use default parameter * refactor(RangeInput): use variable instead of getter for disabled
1 parent 11d78f0 commit 7916d16

File tree

23 files changed

+2667
-348
lines changed

23 files changed

+2667
-348
lines changed

dev/app/init-builtin-widgets.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,114 @@ export default () => {
681681
})
682682
);
683683

684+
storiesOf('RangeInput')
685+
.add(
686+
'default',
687+
wrapWithHits(container => {
688+
window.search.addWidget(
689+
instantsearch.widgets.rangeInput({
690+
container,
691+
attributeName: 'price',
692+
templates: {
693+
header: 'Range input',
694+
},
695+
})
696+
);
697+
})
698+
)
699+
.add(
700+
'disabled',
701+
wrapWithHits(container => {
702+
window.search.addWidget(
703+
instantsearch.widgets.rangeInput({
704+
container,
705+
attributeName: 'price',
706+
min: 500,
707+
max: 0,
708+
templates: {
709+
header: 'Range input',
710+
},
711+
})
712+
);
713+
})
714+
)
715+
.add(
716+
'collapsible',
717+
wrapWithHits(container => {
718+
window.search.addWidget(
719+
instantsearch.widgets.rangeInput({
720+
container,
721+
attributeName: 'price',
722+
collapsible: true,
723+
templates: {
724+
header: 'Range input',
725+
},
726+
})
727+
);
728+
})
729+
)
730+
.add(
731+
'with floating number',
732+
wrapWithHits(container => {
733+
window.search.addWidget(
734+
instantsearch.widgets.rangeInput({
735+
container,
736+
attributeName: 'price',
737+
precision: 2,
738+
templates: {
739+
header: 'Range input',
740+
},
741+
})
742+
);
743+
})
744+
)
745+
.add(
746+
'with min boundary',
747+
wrapWithHits(container => {
748+
window.search.addWidget(
749+
instantsearch.widgets.rangeInput({
750+
container,
751+
attributeName: 'price',
752+
min: 10,
753+
templates: {
754+
header: 'Range input',
755+
},
756+
})
757+
);
758+
})
759+
)
760+
.add(
761+
'with max boundary',
762+
wrapWithHits(container => {
763+
window.search.addWidget(
764+
instantsearch.widgets.rangeInput({
765+
container,
766+
attributeName: 'price',
767+
max: 500,
768+
templates: {
769+
header: 'Range input',
770+
},
771+
})
772+
);
773+
})
774+
)
775+
.add(
776+
'with min & max boundaries',
777+
wrapWithHits(container => {
778+
window.search.addWidget(
779+
instantsearch.widgets.rangeInput({
780+
container,
781+
attributeName: 'price',
782+
min: 10,
783+
max: 500,
784+
templates: {
785+
header: 'Range input',
786+
},
787+
})
788+
);
789+
})
790+
);
791+
684792
storiesOf('RangeSlider')
685793
.add(
686794
'default',

docgen/src/examples/tourism/main.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ body {
6565
width: 33%;
6666

6767
&--reset {
68-
fill: #bfc7d8;
68+
fill: #BFC7D8;
6969
top: calc(50% - 12px / 2);
7070
right: 0;
7171
right: 13px;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"dev-novel": "0.0.4",
6565
"doctoc": "1.3.0",
6666
"enzyme": "2.9.1",
67+
"enzyme-to-json": "2.0.1",
6768
"eslint": "4.7.2",
6869
"eslint-config-algolia": "12.0.0",
6970
"eslint-config-prettier": "2.5.0",
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import React, { Component } from 'react';
2+
import PropTypes from 'prop-types';
3+
import autoHideContainerHOC from '../../decorators/autoHideContainer.js';
4+
import headerFooterHOC from '../../decorators/headerFooter.js';
5+
6+
export class RawRangeInput extends Component {
7+
constructor(props) {
8+
super(props);
9+
10+
this.state = {
11+
min: props.values.min,
12+
max: props.values.max,
13+
};
14+
}
15+
16+
componentWillReceiveProps(nextProps) {
17+
this.setState({
18+
min: nextProps.values.min,
19+
max: nextProps.values.max,
20+
});
21+
}
22+
23+
onChange = name => event => {
24+
this.setState({
25+
[name]: event.currentTarget.value,
26+
});
27+
};
28+
29+
onSubmit = event => {
30+
event.preventDefault();
31+
32+
this.props.refine([this.state.min, this.state.max]);
33+
};
34+
35+
render() {
36+
const { min: minValue, max: maxValue } = this.state;
37+
const { min, max, step, cssClasses, labels } = this.props;
38+
const isDisabled = min >= max;
39+
40+
return (
41+
<form className={cssClasses.form} onSubmit={this.onSubmit}>
42+
<fieldset className={cssClasses.fieldset}>
43+
<label className={cssClasses.labelMin}>
44+
<input
45+
className={cssClasses.inputMin}
46+
type="number"
47+
min={min}
48+
max={max}
49+
step={step}
50+
value={minValue}
51+
onChange={this.onChange('min')}
52+
placeholder={min}
53+
disabled={isDisabled}
54+
/>
55+
</label>
56+
<span className={cssClasses.separator}>{labels.separator}</span>
57+
<label className={cssClasses.labelMax}>
58+
<input
59+
className={cssClasses.inputMax}
60+
type="number"
61+
min={min}
62+
max={max}
63+
step={step}
64+
value={maxValue}
65+
onChange={this.onChange('max')}
66+
placeholder={max}
67+
disabled={isDisabled}
68+
/>
69+
</label>
70+
<button
71+
role="button"
72+
className={cssClasses.submit}
73+
disabled={isDisabled}
74+
>
75+
{labels.submit}
76+
</button>
77+
</fieldset>
78+
</form>
79+
);
80+
}
81+
}
82+
83+
RawRangeInput.propTypes = {
84+
min: PropTypes.number.isRequired,
85+
max: PropTypes.number.isRequired,
86+
step: PropTypes.number.isRequired,
87+
values: PropTypes.shape({
88+
min: PropTypes.number,
89+
max: PropTypes.number,
90+
}).isRequired,
91+
cssClasses: PropTypes.shape({
92+
form: PropTypes.string.isRequired,
93+
fieldset: PropTypes.string.isRequired,
94+
labelMin: PropTypes.string.isRequired,
95+
inputMin: PropTypes.string.isRequired,
96+
separator: PropTypes.string.isRequired,
97+
labelMax: PropTypes.string.isRequired,
98+
inputMax: PropTypes.string.isRequired,
99+
submit: PropTypes.string.isRequired,
100+
}).isRequired,
101+
labels: PropTypes.shape({
102+
separator: PropTypes.string.isRequired,
103+
submit: PropTypes.string.isRequired,
104+
}).isRequired,
105+
refine: PropTypes.func.isRequired,
106+
};
107+
108+
export default autoHideContainerHOC(headerFooterHOC(RawRangeInput));

0 commit comments

Comments
 (0)