Skip to content

Commit addaf3d

Browse files
authored
refactor: Use rc-util to mini final antd dist size (#49)
* refactor: Use rc-util to min fianl dist size * fix lint * update eslint * rm autoFocus logic
1 parent ae6e547 commit addaf3d

File tree

5 files changed

+116
-116
lines changed

5 files changed

+116
-116
lines changed

.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,7 @@ module.exports = {
88
'prefer-promise-reject-errors': 0,
99
'react/no-array-index-key': 0,
1010
'react/sort-comp': 0,
11+
'import/no-named-as-default': 0,
12+
'import/no-named-as-default-member': 0,
1113
},
1214
};

examples/simple.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import '../assets/index.less';
22
import React from 'react';
3-
import Switch from '../src/index';
3+
import Switch from '../src';
44

55
function onChange(value, event) {
66
// eslint-disable-next-line no-console

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
"coverage": "father test --coverage"
3636
},
3737
"devDependencies": {
38+
"@types/classnames": "^2.2.10",
39+
"@types/jest": "^25.2.2",
3840
"coveralls": "^3.0.6",
3941
"enzyme": "^3.0.0",
4042
"enzyme-adapter-react-16": "^1.0.1",
@@ -52,6 +54,7 @@
5254
"react-dom": "^16.0.0"
5355
},
5456
"dependencies": {
55-
"classnames": "^2.2.1"
57+
"classnames": "^2.2.1",
58+
"rc-util": "^4.20.5"
5659
}
5760
}

src/index.tsx

Lines changed: 81 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,111 @@
11
import * as React from 'react';
22
import classNames from 'classnames';
3+
import useMergedState from 'rc-util/lib/hooks/useMergedState';
4+
import KeyCode from 'rc-util/lib/KeyCode';
35

4-
export type SwitchChangeEventHandler = (checked: boolean, event: MouseEvent) => void;
6+
export type SwitchChangeEventHandler = (
7+
checked: boolean,
8+
event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>,
9+
) => void;
510
export type SwitchClickEventHandler = SwitchChangeEventHandler;
611

7-
interface SwitchProps {
12+
interface SwitchProps
13+
extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange' | 'onClick'> {
814
className?: string;
915
prefixCls?: string;
1016
disabled?: boolean;
1117
checkedChildren?: React.ReactNode;
1218
unCheckedChildren?: React.ReactNode;
1319
onChange?: SwitchChangeEventHandler;
14-
onMouseUp: React.MouseEventHandler<HTMLButtonElement>;
20+
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;
1521
onClick?: SwitchClickEventHandler;
1622
tabIndex?: number;
1723
checked?: boolean;
1824
defaultChecked?: boolean;
19-
autoFocus?: boolean;
2025
loadingIcon: React.ReactNode;
2126
style?: React.CSSProperties;
2227
title?: string;
2328
}
2429

25-
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>((props, ref) => {
26-
const mergedRef = (ref as any) || React.createRef<HTMLButtonElement>();
27-
28-
let initChecked = false;
29-
if ('checked' in props) {
30-
initChecked = !!props.checked;
31-
} else {
32-
initChecked = !!props.defaultChecked;
33-
}
34-
const [checked, setChecked] = React.useState(initChecked);
35-
36-
React.useEffect(() => {
37-
const { autoFocus, disabled } = props;
38-
if (autoFocus && !disabled) {
39-
(mergedRef.current as any).focus();
30+
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
31+
(
32+
{
33+
prefixCls = 'rc-switch',
34+
className,
35+
checked,
36+
defaultChecked,
37+
disabled,
38+
loadingIcon,
39+
checkedChildren,
40+
unCheckedChildren,
41+
onClick,
42+
onChange,
43+
onKeyDown,
44+
...restProps
45+
},
46+
ref,
47+
) => {
48+
const [innerChecked, setInnerChecked] = useMergedState<boolean>(false, {
49+
value: checked,
50+
defaultValue: defaultChecked,
51+
});
52+
53+
function triggerChange(
54+
newChecked: boolean,
55+
event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>,
56+
) {
57+
let mergedChecked = innerChecked;
58+
59+
if (!disabled) {
60+
mergedChecked = newChecked;
61+
setInnerChecked(mergedChecked);
62+
onChange?.(mergedChecked, event);
63+
}
64+
65+
return mergedChecked;
4066
}
41-
}, [props.autoFocus]);
4267

43-
React.useEffect(() => {
44-
if ('checked' in props) {
45-
setChecked(!!props.checked);
68+
function onInternalKeyDown(e: React.KeyboardEvent<HTMLButtonElement>) {
69+
if (e.which === KeyCode.LEFT) {
70+
triggerChange(false, e);
71+
} else if (e.which === KeyCode.RIGHT) {
72+
triggerChange(true, e);
73+
}
74+
onKeyDown?.(e);
4675
}
47-
}, [props.checked]);
4876

49-
const setInternalChecked = (checked, e) => {
50-
const { disabled, onChange } = props;
51-
if (disabled) {
52-
return;
53-
}
54-
if (!('checked' in props)) {
55-
setChecked(checked);
56-
}
57-
if (onChange) {
58-
onChange(checked, e);
77+
function onInternalClick(e: React.MouseEvent<HTMLButtonElement>) {
78+
const ret = triggerChange(!innerChecked, e);
79+
// [Legacy] trigger onClick with value
80+
onClick?.(ret, e);
5981
}
60-
};
6182

62-
const handleClick = e => {
63-
const { onClick } = props;
64-
const newChecked = !checked;
65-
setInternalChecked(newChecked, e);
66-
if (onClick) {
67-
onClick(newChecked, e);
68-
}
69-
};
70-
71-
const handleKeyDown = e => {
72-
if (e.keyCode === 37) {
73-
// Left
74-
setInternalChecked(false, e);
75-
} else if (e.keyCode === 39) {
76-
// Right
77-
setInternalChecked(true, e);
78-
}
79-
};
80-
81-
// Handle auto focus when click switch in Chrome
82-
const handleMouseUp = e => {
83-
(mergedRef.current as any).blur();
84-
if (props.onMouseUp) {
85-
props.onMouseUp(e);
86-
}
87-
};
88-
89-
const {
90-
className,
91-
prefixCls,
92-
disabled,
93-
loadingIcon,
94-
checkedChildren,
95-
unCheckedChildren,
96-
onChange,
97-
...restProps
98-
} = props;
99-
100-
const switchClassName = classNames({
101-
[className]: !!className,
102-
[prefixCls]: true,
103-
[`${prefixCls}-checked`]: checked,
104-
[`${prefixCls}-disabled`]: disabled,
105-
});
106-
107-
return (
108-
<button
109-
{...restProps}
110-
type="button"
111-
role="switch"
112-
aria-checked={checked}
113-
disabled={disabled}
114-
className={switchClassName}
115-
ref={mergedRef}
116-
onKeyDown={handleKeyDown}
117-
onClick={handleClick}
118-
onMouseUp={handleMouseUp}
119-
>
120-
{loadingIcon}
121-
<span className={`${prefixCls}-inner`}>{checked ? checkedChildren : unCheckedChildren}</span>
122-
</button>
123-
);
124-
});
83+
const switchClassName = classNames(prefixCls, className, {
84+
[`${prefixCls}-checked`]: innerChecked,
85+
[`${prefixCls}-disabled`]: disabled,
86+
});
87+
88+
return (
89+
<button
90+
{...restProps}
91+
type="button"
92+
role="switch"
93+
aria-checked={innerChecked}
94+
disabled={disabled}
95+
className={switchClassName}
96+
ref={ref}
97+
onKeyDown={onInternalKeyDown}
98+
onClick={onInternalClick}
99+
>
100+
{loadingIcon}
101+
<span className={`${prefixCls}-inner`}>
102+
{innerChecked ? checkedChildren : unCheckedChildren}
103+
</span>
104+
</button>
105+
);
106+
},
107+
);
125108

126109
Switch.displayName = 'Switch';
127110

128-
Switch.defaultProps = {
129-
prefixCls: 'rc-switch',
130-
checkedChildren: null,
131-
unCheckedChildren: null,
132-
className: '',
133-
defaultChecked: false,
134-
};
135-
136111
export default Switch;

tests/index.spec.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import KeyCode from 'rc-util/lib/KeyCode';
23
// eslint-disable-next-line import/no-extraneous-dependencies
34
import { mount } from 'enzyme';
45
import Switch from '../index';
@@ -24,9 +25,9 @@ describe('rc-switch', () => {
2425
it('should be checked upon right key and unchecked on left key', () => {
2526
const wrapper = createSwitch();
2627
expect(wrapper.exists('.unchecked')).toBeTruthy();
27-
wrapper.simulate('keydown', { keyCode: 39 });
28+
wrapper.simulate('keydown', { which: KeyCode.RIGHT });
2829
expect(wrapper.exists('.checked')).toBeTruthy();
29-
wrapper.simulate('keydown', { keyCode: 37 });
30+
wrapper.simulate('keydown', { which: KeyCode.LEFT });
3031
expect(wrapper.exists('.unchecked')).toBeTruthy();
3132
});
3233

@@ -89,12 +90,22 @@ describe('rc-switch', () => {
8990
expect(handleBlur).toHaveBeenCalled();
9091
});
9192

92-
it('autoFocus', () => {
93-
const container = document.createElement('div');
94-
document.body.appendChild(container);
95-
const handleFocus = jest.fn();
96-
mount(<Switch autoFocus onFocus={handleFocus} />, { attachTo: container });
97-
expect(handleFocus).toHaveBeenCalled();
93+
describe('autoFocus', () => {
94+
it('basic', () => {
95+
const container = document.createElement('div');
96+
document.body.appendChild(container);
97+
const handleFocus = jest.fn();
98+
mount(<Switch autoFocus onFocus={handleFocus} />, { attachTo: container });
99+
expect(handleFocus).toHaveBeenCalled();
100+
});
101+
102+
it('not work when disabled', () => {
103+
const container = document.createElement('div');
104+
document.body.appendChild(container);
105+
const handleFocus = jest.fn();
106+
mount(<Switch autoFocus disabled onFocus={handleFocus} />, { attachTo: container });
107+
expect(handleFocus).not.toHaveBeenCalled();
108+
});
98109
});
99110

100111
it('disabled', () => {
@@ -110,4 +121,13 @@ describe('rc-switch', () => {
110121
wrapper.simulate('mouseup');
111122
expect(onMouseUp).toHaveBeenCalled();
112123
});
124+
125+
it('disabled should click not to change', () => {
126+
const onChange = jest.fn();
127+
const onClick = jest.fn();
128+
const wrapper = createSwitch({ disabled: true, onChange, onClick, checked: true });
129+
130+
wrapper.simulate('click');
131+
expect(onChange).not.toHaveBeenCalled();
132+
});
113133
});

0 commit comments

Comments
 (0)