Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ lib
es
yarn.lock
package-lock.json
coverage/
15 changes: 4 additions & 11 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ notifications:
- afc163@gmail.com

node_js:
- 6
- 10

before_install:
- |
Expand All @@ -17,22 +17,15 @@ before_install:
echo "Only docs were updated, stopping build process."
exit
fi
npm install npm@3.x -g
phantomjs --version
script:
- |
if [ "$TEST_TYPE" = test ]; then
npm test
npm test -- --coverage && \
bash <(curl -s https://codecov.io/bash)
else
npm run $TEST_TYPE
fi
env:
matrix:
- TEST_TYPE=lint
- TEST_TYPE=test
- TEST_TYPE=coverage


matrix:
allow_failures:
- env: "TEST_TYPE=saucelabs"
- TEST_TYPE=test
23 changes: 14 additions & 9 deletions examples/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,37 @@ import React from 'react';
import ReactDOM from 'react-dom';
import Switch from 'rc-switch';

function onChange(value) {
console.log(`switch checked: ${value}`); // eslint-disable-line
function onChange(value, event) {
console.log(`switch checked: ${value}`, event); // eslint-disable-line
}

class Demo extends React.Component {
state = {
disabled: false,
}
};

toggle = () => {
const { disabled } = this.state;
this.setState({
disabled: !this.state.disabled,
disabled: !disabled,
});
}
};

render() {
const { disabled } = this.state;
return (
<div style={{ margin: 20 }}>
<Switch
onChange={onChange}
disabled={this.state.disabled}
checkedChildren={'开'}
unCheckedChildren={'关'}
onClick={onChange}
disabled={disabled}
checkedChildren="开"
unCheckedChildren="关"
/>
<div style={{ marginTop: 20 }}>
<button onClick={this.toggle}>toggle disabled</button>
<button type="button" onClick={this.toggle}>
toggle disabled
</button>
</div>
</div>
);
Expand Down
34 changes: 15 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,30 +34,20 @@
"start": "rc-tools run server",
"pub": "rc-tools run pub --babel-runtime",
"lint": "rc-tools run lint",
"test": "jest",
"test": "rc-tools run test",
"prepublish": "rc-tools run guard",
"coverage": "jest --coverage && cat ./coverage/lcov.info | coveralls"
},
"jest": {
"setupFiles": ["./tests/setup.js"],
"collectCoverageFrom": [
"src/**/*"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"transform": {
"\\.jsx?$": "./node_modules/rc-tools/scripts/jestPreprocessor.js"
}
"coverage": "rc-tools run test --coverage",
"pre-commit": "rc-tools run pre-commit",
"lint-staged": "lint-staged"
},
"devDependencies": {
"coveralls": "^2.11.15",
"enzyme": "^3.0.0",
"enzyme-adapter-react-16": "^1.0.1",
"enzyme-to-json": "^3.0.0",
"jest": "^19.0.2",
"lint-staged": "^8.1.0",
"pre-commit": "1.x",
"rc-tools": "6.x",
"rc-tools": "^9.3.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-test-renderer": "^16.0.0"
Expand All @@ -67,11 +57,17 @@
"react-dom": "^16.0.0"
},
"pre-commit": [
"lint"
"lint-staged"
],
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"npm run pre-commit",
"git add"
]
},
"dependencies": {
"babel-runtime": "^6.23.0",
"classnames": "^2.2.1",
"prop-types": "^15.5.6"
"prop-types": "^15.5.6",
"react-lifecycles-compat": "^3.0.4"
}
}
90 changes: 54 additions & 36 deletions src/Switch.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
const classNames = require('classnames');
import { polyfill } from 'react-lifecycles-compat';

function noop() {
}
const classNames = require('classnames');

class Switch extends Component {
constructor(props) {
Expand All @@ -25,50 +24,66 @@ class Switch extends Component {
}
}

componentWillReceiveProps(nextProps) {
static getDerivedStateFromProps(nextProps) {
const newState = {};
const { checked } = nextProps;

if ('checked' in nextProps) {
this.setState({
checked: !!nextProps.checked,
});
newState.checked = !!checked;
}

return newState;
}

setChecked(checked) {
if (this.props.disabled) {
setChecked(checked, e) {
const { disabled, onChange } = this.props;
if (disabled) {
return;
}
if (!('checked' in this.props)) {
this.setState({
checked,
});
}
this.props.onChange(checked);
if (onChange) {
onChange(checked, e);
}
}

toggle = () => {
handleClick = e => {
const { checked } = this.state;
const { onClick } = this.props;
const checked = !this.state.checked;
this.setChecked(checked);
onClick(checked);
}

handleKeyDown = (e) => {
if (e.keyCode === 37) { // Left
this.setChecked(false);
} else if (e.keyCode === 39) { // Right
this.setChecked(true);
const newChecked = !checked;
this.setChecked(newChecked, e);
if (onClick) {
onClick(newChecked, e);
}
}
};

handleKeyDown = e => {
if (e.keyCode === 37) {
// Left
this.setChecked(false, e);
} else if (e.keyCode === 39) {
// Right
this.setChecked(true, e);
}
};

// Handle auto focus when click switch in Chrome
handleMouseUp = (e) => {
handleMouseUp = e => {
const { onMouseUp } = this.props;
if (this.node) {
this.node.blur();
}
if (this.props.onMouseUp) {
this.props.onMouseUp(e);
if (onMouseUp) {
onMouseUp(e);
}
}
};

saveNode = node => {
this.node = node;
};

focus() {
this.node.focus();
Expand All @@ -78,14 +93,17 @@ class Switch extends Component {
this.node.blur();
}

saveNode = (node) => {
this.node = node;
}

render() {
const { className, prefixCls, disabled, loadingIcon,
checkedChildren, unCheckedChildren, ...restProps } = this.props;
const checked = this.state.checked;
const {
className,
prefixCls,
disabled,
loadingIcon,
checkedChildren,
unCheckedChildren,
...restProps
} = this.props;
const { checked } = this.state;
const switchClassName = classNames({
[className]: !!className,
[prefixCls]: true,
Expand All @@ -102,7 +120,7 @@ class Switch extends Component {
className={switchClassName}
ref={this.saveNode}
onKeyDown={this.handleKeyDown}
onClick={this.toggle}
onClick={this.handleClick}
onMouseUp={this.handleMouseUp}
>
{loadingIcon}
Expand Down Expand Up @@ -136,8 +154,8 @@ Switch.defaultProps = {
unCheckedChildren: null,
className: '',
defaultChecked: false,
onChange: noop,
onClick: noop,
};

polyfill(Switch);

export default Switch;
12 changes: 6 additions & 6 deletions tests/index.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-undef */
import Switch from '../index';
import React from 'react';
import { mount } from 'enzyme';
import Switch from '../index';

describe('rc-switch', () => {
let switcher;
Expand All @@ -24,7 +24,7 @@ describe('rc-switch', () => {
});

it('should change from an initial checked state of true to false on click', () => {
const wrapper = mount(<Switch defaultChecked/>);
const wrapper = mount(<Switch defaultChecked />);
expect(wrapper.state().checked).toBe(true);
wrapper.simulate('click');
expect(wrapper.state().checked).toBe(false);
Expand All @@ -34,24 +34,24 @@ describe('rc-switch', () => {
const onClick = jest.fn();
const wrapper = mount(<Switch onClick={onClick} />);
wrapper.simulate('click');
expect(onClick).toBeCalledWith(true);
expect(onClick).toBeCalledWith(true, expect.objectContaining({ type: 'click' }));
expect(onClick.mock.calls.length).toBe(1);
wrapper.simulate('click');
expect(onClick).toBeCalledWith(false);
expect(onClick).toBeCalledWith(false, expect.objectContaining({ type: 'click' }));
expect(onClick.mock.calls.length).toBe(2);
});

it('should not toggle when clicked in a disabled state', () => {
const onChange = jest.fn();
const wrapper = mount(<Switch disabled checked onChange={onChange}/>);
const wrapper = mount(<Switch disabled checked onChange={onChange} />);
expect(wrapper.state().checked).toBe(true);
wrapper.simulate('click');
expect(wrapper.state().checked).toBe(true);
expect(onChange.mock.calls.length).toBe(0);
});

it('should support loading icon node', () => {
const wrapper = mount(<Switch loadingIcon={<span className="extra">loading</span>}/>);
const wrapper = mount(<Switch loadingIcon={<span className="extra">loading</span>} />);
expect(wrapper.find('.extra').text()).toBe('loading');
});

Expand Down
8 changes: 0 additions & 8 deletions tests/setup.js

This file was deleted.