Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Slider] Remove style-propable mixin and react-dom #3332

Merged
merged 4 commits into from
Feb 15, 2016
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 139 additions & 143 deletions src/slider.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react';
import ReactDOM from 'react-dom';
import StylePropable from './mixins/style-propable';
import Transitions from './styles/transitions';
import FocusRipple from './ripples/focus-ripple';
import getMuiTheme from './styles/getMuiTheme';
Expand Down Expand Up @@ -40,6 +38,122 @@ const valueInRangePropType = (props, propName, componentName) => {
}
};

const getStyles = (props, state) => {
const {
slider,
} = state.muiTheme;

const fillGutter = slider.handleSize / 2;
const disabledGutter = slider.trackSize + slider.handleSizeDisabled / 2;
const calcDisabledSpacing = props.disabled ? ` - ${disabledGutter}px` : '';

const styles = {
root: {
touchCallout: 'none',
userSelect: 'none',
cursor: 'default',
height: slider.handleSizeActive,
position: 'relative',
marginTop: 24,
marginBottom: 48,
},
track: {
position: 'absolute',
top: (slider.handleSizeActive - slider.trackSize) / 2,
left: 0,
width: '100%',
height: slider.trackSize,
},
filledAndRemaining: {
position: 'absolute',
top: 0,
height: '100%',
transition: Transitions.easeOut(null, 'margin'),
},
handle: {
boxSizing: 'border-box',
position: 'absolute',
cursor: 'pointer',
pointerEvents: 'inherit',
top: 0,
left: '0%',
zIndex: 1,
margin: `${(slider.trackSize / 2)}px 0 0 0`,
width: slider.handleSize,
height: slider.handleSize,
backgroundColor: slider.selectionColor,
backgroundClip: 'padding-box',
border: '0px solid transparent',
borderRadius: '50%',
transform: 'translate(-50%, -50%)',
transition:
`${Transitions.easeOut('450ms', 'background')}, ${
Transitions.easeOut('450ms', 'border-color')}, ${
Transitions.easeOut('450ms', 'width')}, ${
Transitions.easeOut('450ms', 'height')}`,
overflow: 'visible',
outline: 'none',
},
handleWhenDisabled: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean with these:
handleWhenDisabled, handledWhenPercentZero,handleWhenPercentZeroAndDisabled`, etc. it would be nice if we could replace all of these wit ha single handle key so that the we didn't need Object.assign call below.

This can probably be solved by ternary for some keys or if there's too much, something like what we did with badge should work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They were already in the code actually. I will try hard to change that, but it will take some time because there are a lot of cases that need to be handled (pun intended 😄)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I know! Not your fault. 😄

of cases that need to be handled (pun intended 😄)

😆

boxSizing: 'content-box',
cursor: 'not-allowed',
backgroundColor: slider.trackColor,
width: slider.handleSizeDisabled,
height: slider.handleSizeDisabled,
border: 'none',
},
handleWhenPercentZero: {
border: `${slider.trackSize}px solid ${slider.handleColorZero}`,
backgroundColor: slider.handleFillColor,
boxShadow: 'none',
},
handleWhenPercentZeroAndDisabled: {
cursor: 'not-allowed',
width: slider.handleSizeDisabled,
height: slider.handleSizeDisabled,
},
handleWhenPercentZeroAndFocused: {
border: `${slider.trackSize}px solid ${slider.trackColorSelected}`,
},
handleWhenActive: {
width: slider.handleSizeActive,
height: slider.handleSizeActive,
},
ripple: {
height: slider.handleSize,
width: slider.handleSize,
overflow: 'visible',
},
rippleWhenPercentZero: {
top: -slider.trackSize,
left: -slider.trackSize,
},
rippleInner: {
height: '300%',
width: '300%',
top: -slider.handleSize,
left: -slider.handleSize,
},
rippleColor: {
fill: state.percent === 0 ? slider.handleColorZero : slider.rippleColor,
},
};
styles.filled = Object.assign({}, styles.filledAndRemaining, {
left: 0,
backgroundColor: (props.disabled) ? slider.trackColor : slider.selectionColor,
marginRight: fillGutter,
width: `calc(${(state.percent * 100)}%${calcDisabledSpacing})`,
});
styles.remaining = Object.assign({}, styles.filledAndRemaining, {
right: 0,
backgroundColor: (state.hovered || state.focused)
&& !props.disabled ? slider.trackColorSelected : slider.trackColor,
marginLeft: fillGutter,
width: `calc(${((1 - state.percent) * 100)}%${calcDisabledSpacing})`,
});

return styles;
};

const Slider = React.createClass({

Expand Down Expand Up @@ -142,10 +256,6 @@ const Slider = React.createClass({
muiTheme: React.PropTypes.object,
},

mixins: [
StylePropable,
],

getDefaultProps() {
return {
disabled: false,
Expand Down Expand Up @@ -192,119 +302,6 @@ const Slider = React.createClass({
}
},

getTheme() {
return this.state.muiTheme.slider;
},

getStyles() {
const fillGutter = this.getTheme().handleSize / 2;
const disabledGutter = this.getTheme().trackSize + this.getTheme().handleSizeDisabled / 2;
const calcDisabledSpacing = this.props.disabled ? ` -${disabledGutter}px` : '';
const styles = {
root: {
touchCallout: 'none',
userSelect: 'none',
cursor: 'default',
height: this.getTheme().handleSizeActive,
position: 'relative',
marginTop: 24,
marginBottom: 48,
},
track: {
position: 'absolute',
top: (this.getTheme().handleSizeActive - this.getTheme().trackSize) / 2,
left: 0,
width: '100%',
height: this.getTheme().trackSize,
},
filledAndRemaining: {
position: 'absolute',
top: 0,
height: '100%',
transition: Transitions.easeOut(null, 'margin'),
},
handle: {
boxSizing: 'border-box',
position: 'absolute',
cursor: 'pointer',
pointerEvents: 'inherit',
top: 0,
left: '0%',
zIndex: 1,
margin: `${(this.getTheme().trackSize / 2)}px 0 0 0`,
width: this.getTheme().handleSize,
height: this.getTheme().handleSize,
backgroundColor: this.getTheme().selectionColor,
backgroundClip: 'padding-box',
border: '0px solid transparent',
borderRadius: '50%',
transform: 'translate(-50%, -50%)',
transition:
`${Transitions.easeOut('450ms', 'background')}, ${
Transitions.easeOut('450ms', 'border-color')}, ${
Transitions.easeOut('450ms', 'width')}, ${
Transitions.easeOut('450ms', 'height')}`,
overflow: 'visible',
},
handleWhenDisabled: {
boxSizing: 'content-box',
cursor: 'not-allowed',
backgroundColor: this.getTheme().trackColor,
width: this.getTheme().handleSizeDisabled,
height: this.getTheme().handleSizeDisabled,
border: 'none',
},
handleWhenPercentZero: {
border: `${this.getTheme().trackSize}px solid ${this.getTheme().handleColorZero}`,
backgroundColor: this.getTheme().handleFillColor,
boxShadow: 'none',
},
handleWhenPercentZeroAndDisabled: {
cursor: 'not-allowed',
width: this.getTheme().handleSizeDisabled,
height: this.getTheme().handleSizeDisabled,
},
handleWhenPercentZeroAndFocused: {
border: `${this.getTheme().trackSize}px solid ${this.getTheme().trackColorSelected}`,
},
handleWhenActive: {
width: this.getTheme().handleSizeActive,
height: this.getTheme().handleSizeActive,
},
ripple: {
height: this.getTheme().handleSize,
width: this.getTheme().handleSize,
overflow: 'visible',
},
rippleWhenPercentZero: {
top: -this.getTheme().trackSize,
left: -this.getTheme().trackSize,
},
rippleInner: {
height: '300%',
width: '300%',
top: -this.getTheme().handleSize,
left: -this.getTheme().handleSize,
},
};
styles.filled = this.mergeStyles(styles.filledAndRemaining, {
left: 0,
backgroundColor: (this.props.disabled) ?
this.getTheme().trackColor :
this.getTheme().selectionColor,
marginRight: fillGutter,
width: `calc(${(this.state.percent * 100)}%${calcDisabledSpacing})`,
});
styles.remaining = this.mergeStyles(styles.filledAndRemaining, {
right: 0,
backgroundColor: this.getTheme().trackColor,
marginLeft: fillGutter,
width: `calc(${((1 - this.state.percent) * 100)}%${calcDisabledSpacing})`,
});

return styles;
},


// Needed to prevent text selection when dragging the slider handler.
// In the future, we should consider use <input type="range"> to avoid
Expand Down Expand Up @@ -437,7 +434,7 @@ const Slider = React.createClass({
},

_getTrackLeft() {
return ReactDOM.findDOMNode(this.refs.track).getBoundingClientRect().left;
return this.refs.track.getBoundingClientRect().left;
},

handleMouseUp(e) {
Expand Down Expand Up @@ -472,7 +469,7 @@ const Slider = React.createClass({
},

_dragX(e, pos) {
const max = ReactDOM.findDOMNode(this.refs.track).clientWidth;
const max = this.refs.track.clientWidth;
if (pos < 0) pos = 0; else if (pos > max) pos = max;
this._updateWithChangeEvent(e, pos / max);
},
Expand All @@ -492,77 +489,76 @@ const Slider = React.createClass({
let percent = this.state.percent;
if (percent > 1) percent = 1; else if (percent < 0) percent = 0;

const styles = this.getStyles();
const sliderStyles = this.mergeStyles(styles.root, this.props.style);
const handleStyles = percent === 0 ? this.mergeStyles(
const styles = getStyles(this.props, this.state);
const sliderStyles = Object.assign({}, styles.root, this.props.style);
const handleStyles = percent === 0 ? Object.assign(
{},
styles.handle,
styles.handleWhenPercentZero,
this.state.active && styles.handleWhenActive,
this.state.focused && {outline: 'none'},
(this.state.hovered || this.state.focused) && !this.props.disabled
&& styles.handleWhenPercentZeroAndFocused,
this.props.disabled && styles.handleWhenPercentZeroAndDisabled
) : this.mergeStyles(
) : Object.assign(
{},
styles.handle,
this.state.active && styles.handleWhenActive,
this.state.focused && {outline: 'none'},
this.props.disabled && styles.handleWhenDisabled,
{
left: `${(percent * 100)}%`,
}
);
const rippleStyle = this.mergeStyles(
const rippleStyle = Object.assign(
{},
styles.ripple,
percent === 0 && styles.rippleWhenPercentZero
);
const remainingStyles = styles.remaining;
if ((this.state.hovered || this.state.focused) && !this.props.disabled) {
remainingStyles.backgroundColor = this.getTheme().trackColorSelected;
}

const rippleShowCondition = (this.state.hovered || this.state.focused) && !this.state.active;
const rippleColor = this.state.percent === 0 ? this.getTheme().handleColorZero : this.getTheme().rippleColor;

let focusRipple;
if (!this.props.disabled && !this.props.disableFocusRipple) {
focusRipple = (
<FocusRipple
ref="focusRipple"
key="focusRipple"
style={this.mergeStyles(rippleStyle)}
style={rippleStyle}
innerStyle={styles.rippleInner}
show={rippleShowCondition}
muiTheme={this.state.muiTheme}
color={rippleColor}
color={styles.rippleColor.fill}
/>
);
}

let handleDragProps = {};

if (!this.props.disabled) {
handleDragProps = {
onTouchStart: this._onHandleTouchStart,
onMouseDown: this._onHandleMouseDown,
};
}

const {
prepareStyles,
} = this.state.muiTheme;

return (
<div {...others } style={this.prepareStyles(this.props.style)}>
<div {...others} style={prepareStyles(Object.assign({}, this.props.style))}>
<span>{this.props.description}</span>
<span>{this.props.error}</span>
<div
style={this.prepareStyles(sliderStyles)}
style={prepareStyles(sliderStyles)}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
onMouseDown={this.handleMouseDown}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onMouseUp={this.handleMouseUp}
>
<div ref="track" style={this.prepareStyles(styles.track)}>
<div style={this.prepareStyles(styles.filled)}></div>
<div style={this.prepareStyles(remainingStyles)}></div>
<div style={this.prepareStyles(handleStyles)} tabIndex={0} {...handleDragProps}>
<div ref="track" style={prepareStyles(styles.track)}>
<div style={prepareStyles(styles.filled)}></div>
<div style={prepareStyles(styles.remaining)}></div>
<div style={prepareStyles(handleStyles)} tabIndex={0} {...handleDragProps}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On L37, we can save an allocation by taking the empty object off.

 let handleDragProps; // = {}; removed

     if (!this.props.disabled) {
       handleDragProps = {
         onTouchStart: this._onHandleTouchStart,
         onMouseDown: this._onHandleMouseDown,
        };
      }

// Or write as
const handleDragProps = !this.props.disabled && {
  onTouchStart: this._onHandleTouchStart,
  onMouseDown: this._onHandleMouseDown,
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can stick with your first approach, since the last one will initialise the variable with false or an object

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

{focusRipple}
</div>
</div>
Expand Down