-
Notifications
You must be signed in to change notification settings - Fork 78
Expand file tree
/
Copy pathindex.tsx
More file actions
111 lines (99 loc) · 2.93 KB
/
index.tsx
File metadata and controls
111 lines (99 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import classNames from 'classnames';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import * as React from 'react';
export type SwitchChangeEventHandler = (
checked: boolean,
event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>,
) => void;
export type SwitchClickEventHandler = SwitchChangeEventHandler;
interface SwitchProps
extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange' | 'onClick'> {
className?: string;
prefixCls?: string;
disabled?: boolean;
checkedChildren?: React.ReactNode;
unCheckedChildren?: React.ReactNode;
onChange?: SwitchChangeEventHandler;
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;
onClick?: SwitchClickEventHandler;
tabIndex?: number;
checked?: boolean;
defaultChecked?: boolean;
loadingIcon?: React.ReactNode;
style?: React.CSSProperties;
title?: string;
}
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;
}
function onInternalKeyDown(e: React.KeyboardEvent<HTMLButtonElement>) {
if (e.key === 'ArrowLeft') {
triggerChange(false, e);
} else if (e.key === 'ArrowRight') {
triggerChange(true, e);
}
onKeyDown?.(e);
}
function onInternalClick(e: React.MouseEvent<HTMLButtonElement>) {
const ret = triggerChange(!innerChecked, e);
// [Legacy] trigger onClick with value
onClick?.(ret, e);
}
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`}>
<span className={`${prefixCls}-inner-checked`}>{checkedChildren}</span>
<span className={`${prefixCls}-inner-unchecked`}>{unCheckedChildren}</span>
</span>
</button>
);
},
);
Switch.displayName = 'Switch';
export default Switch;