commit
fe5f0f8071
|
@ -251,24 +251,3 @@
|
|||
transition-timing-function: $animation-curve-default;
|
||||
transition-duration: $duration;
|
||||
}
|
||||
|
||||
// The frames are this way to prevent a flicker in Safari
|
||||
// See https://goo.gl/5luFDk
|
||||
@mixin ripple-loading($name, $width, $height, $opacity: 0.3) {
|
||||
@keyframes #{$name} {
|
||||
0% {
|
||||
opacity: $opacity;
|
||||
transform: translate3d(-50%, -50%, 0) scale(0);
|
||||
}
|
||||
|
||||
95% {
|
||||
opacity: 0;
|
||||
transform: translate3d(-50%, -50%, 0) scale(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translate3d(-50%, -50%, 0) scale(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ class Button extends React.Component {
|
|||
mini: React.PropTypes.bool,
|
||||
primary: React.PropTypes.bool,
|
||||
raised: React.PropTypes.bool,
|
||||
ripple: React.PropTypes.bool,
|
||||
type: React.PropTypes.string
|
||||
};
|
||||
|
||||
|
@ -30,13 +29,7 @@ class Button extends React.Component {
|
|||
floating: false,
|
||||
mini: false,
|
||||
primary: false,
|
||||
raised: false,
|
||||
ripple: true
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (this.refs.ripple) this.refs.ripple.start(event);
|
||||
if (this.props.onMouseDown) this.props.onMouseDown(event);
|
||||
raised: false
|
||||
};
|
||||
|
||||
handleMouseUp = () => {
|
||||
|
@ -45,7 +38,7 @@ class Button extends React.Component {
|
|||
|
||||
render () {
|
||||
const { accent, children, className, flat, floating, href, icon,
|
||||
inverse, label, mini, primary, raised, ripple, ...others} = this.props;
|
||||
inverse, label, mini, primary, raised, ...others} = this.props;
|
||||
const element = href ? 'a' : 'button';
|
||||
const level = primary ? 'primary' : accent ? 'accent' : 'neutral';
|
||||
const shape = flat ? 'flat' : raised ? 'raised' : floating ? 'floating' : 'flat';
|
||||
|
@ -61,13 +54,11 @@ class Button extends React.Component {
|
|||
ref: 'button',
|
||||
className: classes,
|
||||
disabled: this.props.disabled,
|
||||
onMouseDown: this.handleMouseDown,
|
||||
onMouseUp: this.handleMouseUp,
|
||||
'data-react-toolbox': 'button'
|
||||
};
|
||||
|
||||
return React.createElement(element, props,
|
||||
ripple ? <Ripple ref='ripple' /> : null,
|
||||
icon ? <FontIcon className={style.icon} value={icon}/> : null,
|
||||
label,
|
||||
children
|
||||
|
@ -75,4 +66,4 @@ class Button extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default Button;
|
||||
export default Ripple({centered: false})(Button);
|
||||
|
|
|
@ -4,7 +4,7 @@ import FontIcon from '../font_icon';
|
|||
import Ripple from '../ripple';
|
||||
import style from './style';
|
||||
|
||||
class Button extends React.Component {
|
||||
class IconButton extends React.Component {
|
||||
static propTypes = {
|
||||
accent: React.PropTypes.bool,
|
||||
children: React.PropTypes.node,
|
||||
|
@ -14,20 +14,13 @@ class Button extends React.Component {
|
|||
icon: React.PropTypes.string,
|
||||
inverse: React.PropTypes.bool,
|
||||
primary: React.PropTypes.bool,
|
||||
ripple: React.PropTypes.bool,
|
||||
type: React.PropTypes.string
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
accent: false,
|
||||
className: '',
|
||||
primary: false,
|
||||
ripple: true
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (this.refs.ripple) this.refs.ripple.start(event);
|
||||
if (this.props.onMouseDown) this.props.onMouseDown(event);
|
||||
primary: false
|
||||
};
|
||||
|
||||
handleMouseUp = () => {
|
||||
|
@ -35,7 +28,7 @@ class Button extends React.Component {
|
|||
};
|
||||
|
||||
render () {
|
||||
const {accent, children, className, href, icon, inverse, primary, ripple, ...others} = this.props;
|
||||
const {accent, children, className, href, icon, inverse, primary, ...others} = this.props;
|
||||
const element = href ? 'a' : 'button';
|
||||
const level = primary ? 'primary' : accent ? 'accent' : 'neutral';
|
||||
const classes = ClassNames([style.toggle, style[level]], {[style.inverse]: inverse}, className);
|
||||
|
@ -46,16 +39,15 @@ class Button extends React.Component {
|
|||
ref: 'button',
|
||||
className: classes,
|
||||
disabled: this.props.disabled,
|
||||
onMouseDown: this.handleMouseDown,
|
||||
onMouseUp: this.handleMouseUp,
|
||||
'data-react-toolbox': 'button'
|
||||
};
|
||||
|
||||
return React.createElement(element, props,
|
||||
ripple ? <Ripple ref='ripple' centered /> : null,
|
||||
icon ? <FontIcon className={style.icon} value={icon}/> : children
|
||||
icon ? <FontIcon className={style.icon} value={icon}/> : null,
|
||||
children
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Button;
|
||||
export default Ripple({centered: true})(IconButton);
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import React from 'react';
|
||||
import ClassNames from 'classnames';
|
||||
import Ripple from '../ripple';
|
||||
import style from './style';
|
||||
|
||||
const Check = ({checked, children, onMouseDown}) => {
|
||||
const className = ClassNames(style.check, {
|
||||
[style.checked]: checked
|
||||
});
|
||||
|
||||
return <div data-role='checkbox' onMouseDown={onMouseDown} className={className}>{children}</div>;
|
||||
};
|
||||
|
||||
export default Ripple({
|
||||
className: style.ripple,
|
||||
spread: 2.6,
|
||||
centered: true
|
||||
})(Check);
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import ClassNames from 'classnames';
|
||||
import Ripple from '../ripple';
|
||||
import events from '../utils/events';
|
||||
import Check from './Check';
|
||||
import style from './style';
|
||||
|
||||
class Checkbox extends React.Component {
|
||||
|
@ -22,21 +21,10 @@ class Checkbox extends React.Component {
|
|||
disabled: false
|
||||
};
|
||||
|
||||
handleClick = (event) => {
|
||||
events.pauseEvent(event);
|
||||
handleToggle = (event) => {
|
||||
if (event.pageX !== 0 && event.pageY !== 0) this.blur();
|
||||
if (!this.props.disabled && this.props.onChange) {
|
||||
const value = !this.refs.input.checked;
|
||||
this.props.onChange(value, event);
|
||||
}
|
||||
};
|
||||
|
||||
handleInputClick = (event) => {
|
||||
events.pauseEvent(event);
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (!this.props.disabled) {
|
||||
this.refs.ripple.start(event);
|
||||
this.props.onChange(!this.props.checked, event);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -49,30 +37,22 @@ class Checkbox extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
const fieldClassName = ClassNames(style.field, {
|
||||
const { onChange, ...others } = this.props;
|
||||
const className = ClassNames(style.field, {
|
||||
[style.disabled]: this.props.disabled
|
||||
}, this.props.className);
|
||||
|
||||
const checkboxClassName = ClassNames(style.check, {
|
||||
[style.checked]: this.props.checked
|
||||
});
|
||||
|
||||
return (
|
||||
<label
|
||||
data-react-toolbox='checkbox'
|
||||
className={fieldClassName}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<label data-react-toolbox='checkbox' className={className}>
|
||||
<input
|
||||
ref='input'
|
||||
{...this.props}
|
||||
{...others}
|
||||
className={style.input}
|
||||
onClick={this.handleInputClick}
|
||||
onClick={this.handleToggle}
|
||||
readOnly
|
||||
ref='input'
|
||||
type='checkbox'
|
||||
/>
|
||||
<span data-role='checkbox' className={checkboxClassName} onMouseDown={this.handleMouseDown}>
|
||||
<Ripple ref='ripple' data-role='ripple' className={style.ripple} spread={3} centered />
|
||||
</span>
|
||||
<Check checked={this.props.checked} disabled={this.props.disabled}/>
|
||||
{this.props.label ? <span data-role='label' className={style.text}>{this.props.label}</span> : null}
|
||||
</label>
|
||||
);
|
||||
|
|
|
@ -21,7 +21,6 @@ $calendar-primary-contrast-color: $calendar-primary-contrast !default;
|
|||
$calendar-primary-hover-color: rgba($calendar-primary, 0.21) !default;
|
||||
$calendar-arrows-color: $palette-grey-600 !default;
|
||||
$calendar-arrows-font-size: 2 * $unit;
|
||||
$calendar-arrows-ripple-duration: 450ms;
|
||||
$calendar-year-font-size: 2.4;
|
||||
$calendar-day-font-size: 1.3 * $unit;
|
||||
$calendar-day-disable-opacity: 0.25;
|
||||
|
|
|
@ -91,8 +91,3 @@
|
|||
.month {
|
||||
background-color: $calendar-primary-contrast-color;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
opacity: .5;
|
||||
transition-duration: $calendar-arrows-ripple-duration;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ class ListItem extends React.Component {
|
|||
static propTypes = {
|
||||
avatar: React.PropTypes.string,
|
||||
caption: React.PropTypes.string.isRequired,
|
||||
children: React.PropTypes.any,
|
||||
className: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
leftIcon: React.PropTypes.string,
|
||||
|
@ -32,12 +33,6 @@ class ListItem extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (this.refs.ripple && !this.props.disabled) {
|
||||
this.refs.ripple.start(event);
|
||||
}
|
||||
};
|
||||
|
||||
renderContent () {
|
||||
const className = ClassNames(style.item, {
|
||||
[style.withLegend]: this.props.legend,
|
||||
|
@ -50,7 +45,6 @@ class ListItem extends React.Component {
|
|||
{this.props.leftIcon ? <FontIcon className={`${style.icon} ${style.left}`} value={this.props.leftIcon} /> : null}
|
||||
{this.props.avatar ? <img className={style.avatar} src={this.props.avatar} /> : null}
|
||||
<ListItemContent caption={this.props.caption} legend={this.props.legend} />
|
||||
{this.props.ripple ? <Ripple ref='ripple' className={style.ripple} spread={2} /> : null}
|
||||
{this.props.rightIcon ? <FontIcon className={`${style.icon} ${style.right}`} value={this.props.rightIcon} /> : null}
|
||||
</span>
|
||||
);
|
||||
|
@ -58,11 +52,15 @@ class ListItem extends React.Component {
|
|||
|
||||
render () {
|
||||
return (
|
||||
<li className={style['list-item']} onClick={this.handleClick} onMouseDown={this.handleMouseDown}>
|
||||
<li className={style.listItem} onClick={this.handleClick} onMouseDown={this.props.onMouseDown}>
|
||||
{this.props.to ? <a href={this.props.to}>{this.renderContent()}</a> : this.renderContent()}
|
||||
{this.props.children}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ListItem;
|
||||
export default Ripple({
|
||||
className: style.ripple,
|
||||
centered: false
|
||||
})(ListItem);
|
||||
|
|
|
@ -32,11 +32,16 @@
|
|||
.list + & {
|
||||
margin-top: - $list-vertical-padding;
|
||||
}
|
||||
.list-item ~ & {
|
||||
.listItem ~ & {
|
||||
margin: $list-vertical-padding 0;
|
||||
}
|
||||
}
|
||||
|
||||
.listItem {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
@ -79,7 +84,7 @@
|
|||
}
|
||||
|
||||
.ripple {
|
||||
opacity: .1;
|
||||
color: $color-text-secondary;
|
||||
}
|
||||
|
||||
.text {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import React from 'react';
|
||||
import FontIcon from '../font_icon';
|
||||
import ClassNames from 'classnames';
|
||||
import Ripple from '../ripple';
|
||||
import style from './style.menu_item';
|
||||
|
||||
class MenuItem extends React.Component {
|
||||
static propTypes = {
|
||||
caption: React.PropTypes.string.isRequired,
|
||||
children: React.PropTypes.any,
|
||||
className: React.PropTypes.string,
|
||||
disabled: React.PropTypes.bool,
|
||||
icon: React.PropTypes.string,
|
||||
onClick: React.PropTypes.func,
|
||||
ripple: React.PropTypes.bool,
|
||||
selected: React.PropTypes.bool,
|
||||
shortcut: React.PropTypes.string
|
||||
};
|
||||
|
@ -18,7 +19,6 @@ class MenuItem extends React.Component {
|
|||
static defaultProps = {
|
||||
className: '',
|
||||
disabled: false,
|
||||
ripple: false,
|
||||
selected: false
|
||||
};
|
||||
|
||||
|
@ -28,32 +28,24 @@ class MenuItem extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (this.props.ripple && !this.props.disabled) {
|
||||
this.refs.ripple.start(event);
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
let className = style.root;
|
||||
if (this.props.selected) className += ` ${style.selected}`;
|
||||
if (this.props.disabled) className += ` ${style.disabled}`;
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
const {icon, caption, children, shortcut, selected, disabled, ...others} = this.props;
|
||||
const className = ClassNames(style.root, {
|
||||
[style.selected]: selected,
|
||||
[style.disabled]: disabled
|
||||
}, this.props.className);
|
||||
|
||||
return (
|
||||
<li
|
||||
data-react-toolbox='menu-item'
|
||||
className={className}
|
||||
onClick={this.handleClick}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
>
|
||||
{this.props.icon ? <FontIcon value={this.props.icon} className={style.icon}/> : null}
|
||||
<span className={style.caption}>{this.props.caption}</span>
|
||||
{this.props.shortcut ? <small className={style.shortcut}>{this.props.shortcut}</small> : null}
|
||||
{this.props.ripple ? <Ripple ref='ripple' className={style.ripple} spread={2.5} /> : null}
|
||||
<li {...others} data-react-toolbox='menu-item' className={className} onClick={this.handleClick}>
|
||||
{icon ? <FontIcon value={icon} className={style.icon}/> : null}
|
||||
<span className={style.caption}>{caption}</span>
|
||||
{shortcut ? <small className={style.shortcut}>{shortcut}</small> : null}
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MenuItem;
|
||||
export default Ripple({
|
||||
className: style.ripple
|
||||
})(MenuItem);
|
||||
|
|
|
@ -38,5 +38,5 @@
|
|||
}
|
||||
|
||||
.ripple {
|
||||
opacity: .1;
|
||||
color: $color-text-secondary;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import Ripple from '../ripple';
|
||||
import style from './style';
|
||||
|
||||
const Radio = ({checked, children, onMouseDown}) => {
|
||||
const className = style[checked ? 'radio-checked' : 'radio'];
|
||||
return <div data-role='radio' onMouseDown={onMouseDown} className={className}>{children}</div>;
|
||||
};
|
||||
|
||||
export default Ripple({
|
||||
className: style.ripple,
|
||||
spread: 2.6,
|
||||
centered: true
|
||||
})(Radio);
|
|
@ -1,8 +1,7 @@
|
|||
import React from 'react';
|
||||
import ClassNames from 'classnames';
|
||||
import Ripple from '../ripple';
|
||||
import Radio from './Radio';
|
||||
import style from './style';
|
||||
import events from '../utils/events';
|
||||
|
||||
class RadioButton extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -23,23 +22,10 @@ class RadioButton extends React.Component {
|
|||
disabled: false
|
||||
};
|
||||
|
||||
handleChange = (event) => {
|
||||
if (!this.props.checked && this.props.onChange) {
|
||||
this.props.onChange(event, this);
|
||||
}
|
||||
};
|
||||
|
||||
handleClick = (event) => {
|
||||
events.pauseEvent(event);
|
||||
if (!this.props.disabled) this.handleChange(event);
|
||||
};
|
||||
|
||||
handleInputClick = (event) => {
|
||||
events.pauseEvent(event);
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (!this.props.disabled) this.refs.ripple.start(event);
|
||||
const {checked, disabled, onChange} = this.props;
|
||||
if (event.pageX !== 0 && event.pageY !== 0) this.blur();
|
||||
if (!disabled && !checked && onChange) onChange(event, this);
|
||||
};
|
||||
|
||||
blur () {
|
||||
|
@ -51,22 +37,20 @@ class RadioButton extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
const labelClassName = ClassNames(style[this.props.disabled ? 'disabled' : 'field'], this.props.className);
|
||||
const radioClassName = style[this.props.checked ? 'radio-checked' : 'radio'];
|
||||
const className = ClassNames(style[this.props.disabled ? 'disabled' : 'field'], this.props.className);
|
||||
const { onChange, ...others } = this.props;
|
||||
|
||||
return (
|
||||
<label className={labelClassName} onClick={this.handleClick}>
|
||||
<label className={className}>
|
||||
<input
|
||||
{...this.props}
|
||||
ref='input'
|
||||
{...others}
|
||||
className={style.input}
|
||||
onChange={this.handleChange}
|
||||
onClick={this.handleInputClick}
|
||||
onClick={this.handleClick}
|
||||
readOnly
|
||||
ref='input'
|
||||
type='radio'
|
||||
/>
|
||||
<span role='radio' className={radioClassName} onMouseDown={this.handleMouseDown}>
|
||||
<Ripple ref='ripple' role='ripple' className={style.ripple} spread={3} centered />
|
||||
</span>
|
||||
<Radio checked={this.props.checked} disabled={this.props.disabled}/>
|
||||
{this.props.label ? <span className={style.text}>{this.props.label}</span> : null}
|
||||
</label>
|
||||
);
|
||||
|
|
|
@ -28,15 +28,12 @@
|
|||
margin: 0;
|
||||
border: 0;
|
||||
opacity: 0;
|
||||
|
||||
appearance: none;
|
||||
&:focus:not(&:active) {
|
||||
+ .radio {
|
||||
box-shadow: 0 0 0 $unit $radio-focus-color;
|
||||
}
|
||||
+ .radio-checked {
|
||||
box-shadow: 0 0 0 $unit $radio-checked-focus-color;
|
||||
}
|
||||
&:focus ~ .radio {
|
||||
box-shadow: 0 0 0 $unit $radio-focus-color;
|
||||
}
|
||||
&:focus ~ .radio-checked {
|
||||
box-shadow: 0 0 0 $unit $radio-checked-focus-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,84 +1,122 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ClassNames from 'classnames';
|
||||
import prefixer from '../utils/prefixer';
|
||||
import style from './style';
|
||||
import prefixer from '../utils/prefixer';
|
||||
|
||||
class Ripple extends React.Component {
|
||||
static propTypes = {
|
||||
centered: React.PropTypes.bool,
|
||||
className: React.PropTypes.string,
|
||||
loading: React.PropTypes.bool,
|
||||
spread: React.PropTypes.number
|
||||
};
|
||||
const defaults = {
|
||||
centered: false,
|
||||
className: '',
|
||||
spread: 2
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
centered: false,
|
||||
className: '',
|
||||
loading: false,
|
||||
spread: 2
|
||||
};
|
||||
const Ripple = (options = {}) => {
|
||||
const {
|
||||
centered: defaultCentered,
|
||||
className: defaultClassName,
|
||||
spread: defaultSpread
|
||||
} = {...defaults, ...options};
|
||||
|
||||
state = {
|
||||
active: false,
|
||||
left: null,
|
||||
restarting: false,
|
||||
top: null,
|
||||
width: null
|
||||
};
|
||||
return ComposedComponent => {
|
||||
return class RippledComponent extends React.Component {
|
||||
static propTypes = {
|
||||
children: React.PropTypes.any,
|
||||
disabled: React.PropTypes.bool,
|
||||
ripple: React.PropTypes.bool,
|
||||
rippleCentered: React.PropTypes.bool,
|
||||
rippleClassName: React.PropTypes.string,
|
||||
rippleSpread: React.PropTypes.number
|
||||
};
|
||||
|
||||
handleEnd = () => {
|
||||
document.removeEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
this.setState({active: false});
|
||||
};
|
||||
static defaultProps = {
|
||||
disabled: false,
|
||||
ripple: true,
|
||||
rippleCentered: defaultCentered,
|
||||
rippleClassName: defaultClassName,
|
||||
rippleSpread: defaultSpread
|
||||
};
|
||||
|
||||
start = ({pageX, pageY}, touch = false) => {
|
||||
if (!this._isTouchRippleReceivingMouseEvent(touch)) {
|
||||
this.touch = touch;
|
||||
document.addEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
const {top, left, width} = this._getDescriptor(pageX, pageY);
|
||||
this.setState({active: false, restarting: true, top, left, width}, () => {
|
||||
this.refs.ripple.offsetWidth; //eslint-disable-line no-unused-expressions
|
||||
this.setState({active: true, restarting: false});
|
||||
});
|
||||
}
|
||||
};
|
||||
state = {
|
||||
active: false,
|
||||
left: null,
|
||||
restarting: false,
|
||||
top: null,
|
||||
width: null
|
||||
};
|
||||
|
||||
_isTouchRippleReceivingMouseEvent (touch) {
|
||||
return this.touch && !touch;
|
||||
}
|
||||
handleEnd = () => {
|
||||
document.removeEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
this.setState({active: false});
|
||||
};
|
||||
|
||||
_getDescriptor (pageX, pageY) {
|
||||
const {left, top, height, width} = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
||||
return {
|
||||
left: this.props.centered ? 0 : pageX - left - width / 2 - window.scrollX,
|
||||
top: this.props.centered ? 0 : pageY - top - height / 2 - window.scrollY,
|
||||
width: width * this.props.spread
|
||||
start = ({pageX, pageY}, touch = false) => {
|
||||
if (!this._isTouchRippleReceivingMouseEvent(touch)) {
|
||||
this.touch = touch;
|
||||
document.addEventListener(this.touch ? 'touchend' : 'mouseup', this.handleEnd);
|
||||
const {top, left, width} = this._getDescriptor(pageX, pageY);
|
||||
this.setState({active: false, restarting: true, top, left, width}, () => {
|
||||
this.refs.ripple.offsetWidth; //eslint-disable-line no-unused-expressions
|
||||
this.setState({active: true, restarting: false});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_isTouchRippleReceivingMouseEvent (touch) {
|
||||
return this.touch && !touch;
|
||||
}
|
||||
|
||||
_getDescriptor (pageX, pageY) {
|
||||
const {left, top, height, width} = ReactDOM.findDOMNode(this).getBoundingClientRect();
|
||||
const {rippleCentered: centered, rippleSpread: spread} = this.props;
|
||||
return {
|
||||
left: centered ? 0 : pageX - left - width / 2 - window.scrollX,
|
||||
top: centered ? 0 : pageY - top - height / 2 - window.scrollY,
|
||||
width: width * spread
|
||||
};
|
||||
}
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (!this.props.disabled) this.start(event);
|
||||
if (this.props.onMouseDown) this.props.onMouseDown(event);
|
||||
};
|
||||
|
||||
render () {
|
||||
if (!this.props.ripple) {
|
||||
return <ComposedComponent {...this.props} />;
|
||||
} else {
|
||||
const {
|
||||
children,
|
||||
ripple,
|
||||
rippleClassName: className,
|
||||
rippleCentered: centered,
|
||||
rippleSpread: spread,
|
||||
...other
|
||||
} = this.props;
|
||||
|
||||
const rippleClassName = ClassNames(style.normal, {
|
||||
[style.active]: this.state.active,
|
||||
[style.restarting]: this.state.restarting
|
||||
}, className);
|
||||
|
||||
const { left, top, width } = this.state;
|
||||
const scale = this.state.restarting ? 0 : 1;
|
||||
const rippleStyle = prefixer({
|
||||
transform: `translate3d(${-width / 2 + left}px, ${-width / 2 + top}px, 0) scale(${scale})`
|
||||
}, {width, height: width});
|
||||
|
||||
|
||||
return (
|
||||
<ComposedComponent {...other} onMouseDown={this.handleMouseDown}>
|
||||
{children ? children : null}
|
||||
<span data-react-toolbox='ripple' className={style.wrapper}>
|
||||
<span ref='ripple' role='ripple' className={rippleClassName} style={rippleStyle} />
|
||||
</span>
|
||||
</ComposedComponent>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render () {
|
||||
const { left, top, width } = this.state;
|
||||
const scale = this.state.restarting ? 0 : 1;
|
||||
let rippleStyle = {width, height: width};
|
||||
|
||||
if (!this.props.loading) {
|
||||
rippleStyle = prefixer({
|
||||
transform: `translate3d(${-width / 2 + left}px, ${-width / 2 + top}px, 0) scale(${scale})`
|
||||
}, rippleStyle);
|
||||
}
|
||||
|
||||
const className = ClassNames(style[this.props.loading ? 'loading' : 'normal'], {
|
||||
[style.active]: this.state.active,
|
||||
[style.restarting]: this.state.restarting
|
||||
}, this.props.className);
|
||||
|
||||
return (
|
||||
<span data-react-toolbox='ripple' className={style.wrapper}>
|
||||
<span ref='ripple' role='ripple' className={className} style={rippleStyle} />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default Ripple;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
$ripple-duration: 1.2s;
|
||||
$ripple-final-opacity: .3;
|
||||
$ripple-size: 15 * $unit;
|
||||
$ripple-duration: 800ms !default;
|
||||
$ripple-final-opacity: .3 !default;
|
||||
$ripple-size: 15 * $unit !default;
|
||||
|
|
|
@ -38,15 +38,3 @@
|
|||
transition-property: opacity, transform;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
@extend %ripple;
|
||||
@include ripple-loading(ripple, $ripple-size, $ripple-size);
|
||||
width: $ripple-size;
|
||||
height: $ripple-size;
|
||||
opacity: $ripple-final-opacity;
|
||||
animation-name: ripple;
|
||||
animation-duration: $ripple-duration;
|
||||
animation-timing-function: $animation-curve-linear-out-slow-in;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import Ripple from '../ripple';
|
||||
import Thumb from './Thumb';
|
||||
import style from './style';
|
||||
import events from '../utils/events';
|
||||
|
||||
class Switch extends React.Component {
|
||||
static propTypes = {
|
||||
|
@ -21,22 +20,13 @@ class Switch extends React.Component {
|
|||
disabled: false
|
||||
};
|
||||
|
||||
handleChange = (event) => {
|
||||
events.pauseEvent(event);
|
||||
if (this.props.onChange && !this.props.disabled) {
|
||||
const value = !this.refs.input.checked;
|
||||
this.props.onChange(value, event);
|
||||
handleToggle = (event) => {
|
||||
if (event.pageX !== 0 && event.pageY !== 0) this.blur();
|
||||
if (!this.props.disabled && this.props.onChange) {
|
||||
this.props.onChange(!this.props.checked, event);
|
||||
}
|
||||
};
|
||||
|
||||
handleInputClick = (event) => {
|
||||
events.pauseEvent(event);
|
||||
};
|
||||
|
||||
handleMouseDown = (event) => {
|
||||
if (!this.props.disabled) this.refs.ripple.start(event);
|
||||
};
|
||||
|
||||
blur () {
|
||||
this.refs.input.blur();
|
||||
}
|
||||
|
@ -46,29 +36,24 @@ class Switch extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
let labelClassName = style[this.props.disabled ? 'disabled' : 'field'];
|
||||
let className = style[this.props.disabled ? 'disabled' : 'field'];
|
||||
const switchClassName = style[this.props.checked ? 'on' : 'off'];
|
||||
if (this.props.className) labelClassName += ` ${this.props.className}`;
|
||||
const { onChange, ...others } = this.props;
|
||||
if (this.props.className) className += ` ${this.props.className}`;
|
||||
|
||||
return (
|
||||
<label
|
||||
data-react-toolbox='checkbox'
|
||||
className={labelClassName}
|
||||
onClick={this.handleChange}
|
||||
>
|
||||
<label data-react-toolbox='checkbox' className={className}>
|
||||
<input
|
||||
{...this.props}
|
||||
ref='input'
|
||||
{...others}
|
||||
checked={this.props.checked}
|
||||
className={style.input}
|
||||
onChange={this.handleChange}
|
||||
onClick={this.handleInputClick}
|
||||
onClick={this.handleToggle}
|
||||
readOnly
|
||||
ref='input'
|
||||
type='checkbox'
|
||||
/>
|
||||
<span role='switch' className={switchClassName}>
|
||||
<span role='thumb' className={style.thumb} onMouseDown={this.handleMouseDown}>
|
||||
<Ripple ref='ripple' role='ripple' className={style.ripple} spread={2.4} centered />
|
||||
</span>
|
||||
<Thumb disabled={this.props.disabled} />
|
||||
</span>
|
||||
{this.props.label ? <span className={style.text}>{this.props.label}</span> : null}
|
||||
</label>
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import React from 'react';
|
||||
import Ripple from '../ripple';
|
||||
import style from './style';
|
||||
|
||||
const Check = ({children, onMouseDown}) => (
|
||||
<span role='thumb' className={style.thumb} onMouseDown={onMouseDown}>{children}</span>
|
||||
);
|
||||
|
||||
export default Ripple({
|
||||
className: style.ripple,
|
||||
spread: 2.6,
|
||||
centered: true
|
||||
})(Check);
|
|
@ -109,7 +109,7 @@
|
|||
.text {
|
||||
color: $switch-disabled-text-color;
|
||||
}
|
||||
.switch-on, .switch-off {
|
||||
.on, .off {
|
||||
cursor: auto;
|
||||
background: $switch-disabled-track-color;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue