Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
5 changed files
with
116 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,136 +1,111 @@ | ||
import * as React from 'react'; | ||
import classNames from 'classnames'; | ||
import useMergedState from 'rc-util/lib/hooks/useMergedState'; | ||
import KeyCode from 'rc-util/lib/KeyCode'; | ||
|
||
export type SwitchChangeEventHandler = (checked: boolean, event: MouseEvent) => void; | ||
export type SwitchChangeEventHandler = ( | ||
checked: boolean, | ||
event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>, | ||
) => void; | ||
export type SwitchClickEventHandler = SwitchChangeEventHandler; | ||
|
||
interface SwitchProps { | ||
interface SwitchProps | ||
extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange' | 'onClick'> { | ||
className?: string; | ||
prefixCls?: string; | ||
disabled?: boolean; | ||
checkedChildren?: React.ReactNode; | ||
unCheckedChildren?: React.ReactNode; | ||
onChange?: SwitchChangeEventHandler; | ||
onMouseUp: React.MouseEventHandler<HTMLButtonElement>; | ||
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>; | ||
onClick?: SwitchClickEventHandler; | ||
tabIndex?: number; | ||
checked?: boolean; | ||
defaultChecked?: boolean; | ||
autoFocus?: boolean; | ||
loadingIcon: React.ReactNode; | ||
style?: React.CSSProperties; | ||
title?: string; | ||
} | ||
|
||
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>((props, ref) => { | ||
const mergedRef = (ref as any) || React.createRef<HTMLButtonElement>(); | ||
|
||
let initChecked = false; | ||
if ('checked' in props) { | ||
initChecked = !!props.checked; | ||
} else { | ||
initChecked = !!props.defaultChecked; | ||
} | ||
const [checked, setChecked] = React.useState(initChecked); | ||
|
||
React.useEffect(() => { | ||
const { autoFocus, disabled } = props; | ||
if (autoFocus && !disabled) { | ||
(mergedRef.current as any).focus(); | ||
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>( | ||
( | ||
{ | ||
prefixCls = 'rc-switch', | ||
className, | ||
checked, | ||
defaultChecked, | ||
disabled, | ||
loadingIcon, | ||
checkedChildren, | ||
unCheckedChildren, | ||
onClick, | ||
onChange, | ||
onKeyDown, | ||
...restProps | ||
}, | ||
ref, | ||
) => { | ||
const [innerChecked, setInnerChecked] = useMergedState<boolean>(false, { | ||
value: checked, | ||
defaultValue: defaultChecked, | ||
}); | ||
|
||
function triggerChange( | ||
newChecked: boolean, | ||
event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>, | ||
) { | ||
let mergedChecked = innerChecked; | ||
|
||
if (!disabled) { | ||
mergedChecked = newChecked; | ||
setInnerChecked(mergedChecked); | ||
onChange?.(mergedChecked, event); | ||
} | ||
|
||
return mergedChecked; | ||
} | ||
}, [props.autoFocus]); | ||
|
||
React.useEffect(() => { | ||
if ('checked' in props) { | ||
setChecked(!!props.checked); | ||
function onInternalKeyDown(e: React.KeyboardEvent<HTMLButtonElement>) { | ||
if (e.which === KeyCode.LEFT) { | ||
triggerChange(false, e); | ||
} else if (e.which === KeyCode.RIGHT) { | ||
triggerChange(true, e); | ||
} | ||
onKeyDown?.(e); | ||
} | ||
}, [props.checked]); | ||
|
||
const setInternalChecked = (checked, e) => { | ||
const { disabled, onChange } = props; | ||
if (disabled) { | ||
return; | ||
} | ||
if (!('checked' in props)) { | ||
setChecked(checked); | ||
} | ||
if (onChange) { | ||
onChange(checked, e); | ||
function onInternalClick(e: React.MouseEvent<HTMLButtonElement>) { | ||
const ret = triggerChange(!innerChecked, e); | ||
// [Legacy] trigger onClick with value | ||
onClick?.(ret, e); | ||
} | ||
}; | ||
|
||
const handleClick = e => { | ||
const { onClick } = props; | ||
const newChecked = !checked; | ||
setInternalChecked(newChecked, e); | ||
if (onClick) { | ||
onClick(newChecked, e); | ||
} | ||
}; | ||
|
||
const handleKeyDown = e => { | ||
if (e.keyCode === 37) { | ||
// Left | ||
setInternalChecked(false, e); | ||
} else if (e.keyCode === 39) { | ||
// Right | ||
setInternalChecked(true, e); | ||
} | ||
}; | ||
|
||
// Handle auto focus when click switch in Chrome | ||
const handleMouseUp = e => { | ||
(mergedRef.current as any).blur(); | ||
if (props.onMouseUp) { | ||
props.onMouseUp(e); | ||
} | ||
}; | ||
|
||
const { | ||
className, | ||
prefixCls, | ||
disabled, | ||
loadingIcon, | ||
checkedChildren, | ||
unCheckedChildren, | ||
onChange, | ||
...restProps | ||
} = props; | ||
|
||
const switchClassName = classNames({ | ||
[className]: !!className, | ||
[prefixCls]: true, | ||
[`${prefixCls}-checked`]: checked, | ||
[`${prefixCls}-disabled`]: disabled, | ||
}); | ||
|
||
return ( | ||
<button | ||
{...restProps} | ||
type="button" | ||
role="switch" | ||
aria-checked={checked} | ||
disabled={disabled} | ||
className={switchClassName} | ||
ref={mergedRef} | ||
onKeyDown={handleKeyDown} | ||
onClick={handleClick} | ||
onMouseUp={handleMouseUp} | ||
> | ||
{loadingIcon} | ||
<span className={`${prefixCls}-inner`}>{checked ? checkedChildren : unCheckedChildren}</span> | ||
</button> | ||
); | ||
}); | ||
const switchClassName = classNames(prefixCls, className, { | ||
[`${prefixCls}-checked`]: innerChecked, | ||
[`${prefixCls}-disabled`]: disabled, | ||
}); | ||
|
||
return ( | ||
<button | ||
{...restProps} | ||
type="button" | ||
role="switch" | ||
aria-checked={innerChecked} | ||
disabled={disabled} | ||
className={switchClassName} | ||
ref={ref} | ||
onKeyDown={onInternalKeyDown} | ||
onClick={onInternalClick} | ||
> | ||
{loadingIcon} | ||
<span className={`${prefixCls}-inner`}> | ||
{innerChecked ? checkedChildren : unCheckedChildren} | ||
</span> | ||
</button> | ||
); | ||
}, | ||
); | ||
|
||
Switch.displayName = 'Switch'; | ||
|
||
Switch.defaultProps = { | ||
prefixCls: 'rc-switch', | ||
checkedChildren: null, | ||
unCheckedChildren: null, | ||
className: '', | ||
defaultChecked: false, | ||
}; | ||
|
||
export default Switch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters