mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-03 04:27:41 +08:00
refactor: switch #3885
This commit is contained in:
parent
67b9da71eb
commit
4a7fcf95f5
@ -1,7 +1,7 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Switch should has click wave effect 1`] = `
|
||||
<button class="ant-switch ant-switch-checked" type="button" role="switch" aria-checked="true">
|
||||
<button type="button" role="switch" aria-checked="true" class="ant-switch ant-switch-checked">
|
||||
<!----><span class="ant-switch-inner"><!----></span>
|
||||
</button>
|
||||
`;
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { defineComponent, inject, onBeforeMount, ref, ExtractPropTypes, computed } from 'vue';
|
||||
import {
|
||||
defineComponent,
|
||||
inject,
|
||||
onBeforeMount,
|
||||
ref,
|
||||
ExtractPropTypes,
|
||||
computed,
|
||||
onMounted,
|
||||
nextTick,
|
||||
} from 'vue';
|
||||
import LoadingOutlined from '@ant-design/icons-vue/LoadingOutlined';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import VcSwitch from '../vc-switch';
|
||||
import KeyCode from '../_util/KeyCode';
|
||||
import Wave from '../_util/wave';
|
||||
import { defaultConfigProvider } from '../config-provider';
|
||||
import warning from '../_util/warning';
|
||||
@ -18,7 +27,7 @@ const switchProps = {
|
||||
checkedChildren: PropTypes.any,
|
||||
unCheckedChildren: PropTypes.any,
|
||||
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
// defaultChecked: PropTypes.looseBool,
|
||||
defaultChecked: PropTypes.looseBool,
|
||||
autofocus: PropTypes.looseBool,
|
||||
loading: PropTypes.looseBool,
|
||||
checked: PropTypes.looseBool,
|
||||
@ -31,10 +40,24 @@ const Switch = defineComponent({
|
||||
__ANT_SWITCH: true,
|
||||
inheritAttrs: false,
|
||||
props: switchProps,
|
||||
setup(props: SwitchProps, { attrs, slots, expose }) {
|
||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||
const refSwitchNode = ref();
|
||||
emits: ['update:checked', 'mouseup', 'change', 'click', 'keydown'],
|
||||
setup(props: SwitchProps, { attrs, slots, expose, emit }) {
|
||||
onBeforeMount(() => {
|
||||
warning(
|
||||
!('defaultChecked' in attrs),
|
||||
'Switch',
|
||||
`'defaultChecked' is deprecated, please use 'v-model:checked'`,
|
||||
);
|
||||
warning(
|
||||
!('value' in attrs),
|
||||
'Switch',
|
||||
'`value` is not validate prop, do you mean `checked`?',
|
||||
);
|
||||
});
|
||||
|
||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
||||
const { getPrefixCls } = configProvider;
|
||||
const refSwitchNode = ref();
|
||||
const focus = () => {
|
||||
refSwitchNode.value?.focus();
|
||||
};
|
||||
@ -44,42 +67,85 @@ const Switch = defineComponent({
|
||||
|
||||
expose({ focus, blur });
|
||||
|
||||
onBeforeMount(() => {
|
||||
if ('defaultChecked' in attrs) {
|
||||
console.warn(
|
||||
`[antdv: Switch]: 'defaultChecked' will be obsolete, please use 'v-model:checked'`,
|
||||
);
|
||||
}
|
||||
warning(
|
||||
!('value' in attrs),
|
||||
'Switch',
|
||||
'`value` is not validate prop, do you mean `checked`?',
|
||||
);
|
||||
});
|
||||
const { getPrefixCls } = configProvider;
|
||||
const prefixCls = computed(() => {
|
||||
return getPrefixCls('switch', props.prefixCls);
|
||||
});
|
||||
const checked = computed(() => {
|
||||
return 'checked' in props ? !!props.checked : !!props.defaultChecked;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (props.autofocus && !props.disabled) {
|
||||
refSwitchNode.value.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const setChecked = (check: boolean, e: MouseEvent | KeyboardEvent) => {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
emit('update:checked', check);
|
||||
emit('change', check, e);
|
||||
};
|
||||
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
focus();
|
||||
const newChecked = !checked.value;
|
||||
setChecked(newChecked, e);
|
||||
emit('click', newChecked, e);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.keyCode === KeyCode.LEFT) {
|
||||
setChecked(false, e);
|
||||
} else if (e.keyCode === KeyCode.RIGHT) {
|
||||
setChecked(true, e);
|
||||
}
|
||||
emit('keydown', e);
|
||||
};
|
||||
|
||||
const handleMouseUp = (e: MouseEvent) => {
|
||||
refSwitchNode.value?.blur();
|
||||
emit('mouseup', e);
|
||||
};
|
||||
return () => (
|
||||
<Wave insertExtraNode>
|
||||
<VcSwitch
|
||||
{...Omit(props, ['prefixCls', 'size', 'loading', 'disabled'])}
|
||||
<button
|
||||
{...Omit(props, [
|
||||
'prefixCls',
|
||||
'checkedChildren',
|
||||
'unCheckedChildren',
|
||||
'checked',
|
||||
'autofocus',
|
||||
'defaultChecked',
|
||||
])}
|
||||
{...attrs}
|
||||
checked={props.checked}
|
||||
prefixCls={prefixCls.value}
|
||||
loadingIcon={
|
||||
props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null
|
||||
}
|
||||
checkedChildren={getPropsSlot(slots, props, 'checkedChildren')}
|
||||
unCheckedChildren={getPropsSlot(slots, props, 'unCheckedChildren')}
|
||||
onKeydown={handleKeyDown}
|
||||
onClick={handleClick}
|
||||
onMouseup={handleMouseUp}
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={checked.value}
|
||||
disabled={props.disabled || props.loading}
|
||||
class={{
|
||||
[attrs.class as string]: attrs.class,
|
||||
[prefixCls.value]: true,
|
||||
[`${prefixCls.value}-small`]: props.size === 'small',
|
||||
[`${prefixCls.value}-loading`]: props.loading,
|
||||
[`${prefixCls.value}-checked`]: checked.value,
|
||||
[`${prefixCls.value}-disabled`]: props.disabled,
|
||||
}}
|
||||
ref={refSwitchNode}
|
||||
/>
|
||||
>
|
||||
{props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null}
|
||||
<span class={`${prefixCls.value}-inner`}>
|
||||
{checked.value
|
||||
? getPropsSlot(slots, props, 'checkedChildren')
|
||||
: getPropsSlot(slots, props, 'unCheckedChildren')}
|
||||
</span>
|
||||
</button>
|
||||
</Wave>
|
||||
);
|
||||
},
|
||||
|
@ -1,117 +0,0 @@
|
||||
@switchPrefixCls: rc-switch;
|
||||
|
||||
@duration: 0.3s;
|
||||
|
||||
.@{switchPrefixCls} {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 44px;
|
||||
height: 22px;
|
||||
line-height: 20px;
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
border-radius: 20px 20px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #ccc;
|
||||
cursor: pointer;
|
||||
transition: all @duration cubic-bezier(0.35, 0, 0.25, 1);
|
||||
|
||||
&-inner {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
left: 2px;
|
||||
top: 1px;
|
||||
border-radius: 50% 50%;
|
||||
background-color: #fff;
|
||||
content: ' ';
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
|
||||
transform: scale(1);
|
||||
transition: left @duration cubic-bezier(0.35, 0, 0.25, 1);
|
||||
animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
|
||||
animation-duration: @duration;
|
||||
animation-name: rcSwitchOff;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
transform: scale(1.1);
|
||||
animation-name: rcSwitchOn;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px tint(#2db7f5, 80%);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&-checked {
|
||||
border: 1px solid #87d068;
|
||||
background-color: #87d068;
|
||||
|
||||
.@{switchPrefixCls}-inner {
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled {
|
||||
cursor: no-drop;
|
||||
background: #ccc;
|
||||
border-color: #ccc;
|
||||
|
||||
&:after {
|
||||
background: #9e9e9e;
|
||||
animation-name: none;
|
||||
cursor: no-drop;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
transform: scale(1);
|
||||
animation-name: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-label {
|
||||
display: inline-block;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
padding-left: 10px;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
pointer-events: none;
|
||||
user-select: text;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rcSwitchOn {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rcSwitchOff {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
// base rc-switch 1.9.0
|
||||
import Switch from './src/Switch';
|
||||
|
||||
export default Switch;
|
@ -1,16 +0,0 @@
|
||||
import PropTypes from '../../_util/vue-types';
|
||||
|
||||
export const switchPropTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
disabled: PropTypes.looseBool.def(false),
|
||||
checkedChildren: PropTypes.any,
|
||||
unCheckedChildren: PropTypes.any,
|
||||
// onChange: PropTypes.func,
|
||||
// onMouseUp: PropTypes.func,
|
||||
// onClick: PropTypes.func,
|
||||
tabindex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
checked: PropTypes.looseBool,
|
||||
defaultChecked: PropTypes.looseBool.def(false),
|
||||
autofocus: PropTypes.looseBool.def(false),
|
||||
loadingIcon: PropTypes.any,
|
||||
};
|
@ -1,99 +0,0 @@
|
||||
import { switchPropTypes } from './PropTypes';
|
||||
import Omit from 'omit.js';
|
||||
import { defineComponent, nextTick, onMounted, ref } from 'vue';
|
||||
import KeyCode from '../../_util/KeyCode';
|
||||
import { getPropsSlot } from '../../_util/props-util';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VcSwitch',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
...switchPropTypes,
|
||||
prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
|
||||
},
|
||||
emits: ['update:checked', 'mouseup', 'change', 'click'],
|
||||
setup(props, { attrs, slots, emit, expose }) {
|
||||
const checked = ref('checked' in props ? !!props.checked : !!props.defaultChecked);
|
||||
|
||||
const refSwitchNode = ref();
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (props.autofocus && !props.disabled) {
|
||||
refSwitchNode.value.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const setChecked = (check: boolean, e: MouseEvent | KeyboardEvent) => {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
checked.value = !checked.value;
|
||||
emit('update:checked', checked);
|
||||
emit('change', check, e);
|
||||
};
|
||||
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
setChecked(checked.value, e);
|
||||
emit('click', checked.value, e);
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.keyCode === KeyCode.LEFT) {
|
||||
setChecked(false, e);
|
||||
} else if (e.keyCode === KeyCode.RIGHT) {
|
||||
setChecked(true, e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = (e: MouseEvent) => {
|
||||
refSwitchNode.value?.blur();
|
||||
emit('mouseup', e);
|
||||
};
|
||||
|
||||
const focus = () => {
|
||||
refSwitchNode.value?.focus();
|
||||
};
|
||||
const blur = () => {
|
||||
refSwitchNode.value?.blur();
|
||||
};
|
||||
|
||||
expose({ focus, blur });
|
||||
|
||||
return () => (
|
||||
<button
|
||||
{...Omit(props, [
|
||||
'prefixCls',
|
||||
'checkedChildren',
|
||||
'unCheckedChildren',
|
||||
'checked',
|
||||
'autofocus',
|
||||
'defaultChecked',
|
||||
])}
|
||||
{...attrs}
|
||||
onKeydown={handleKeyDown}
|
||||
onClick={handleClick}
|
||||
onMouseup={handleMouseUp}
|
||||
type="button"
|
||||
role="switch"
|
||||
aria-checked={checked.value}
|
||||
disabled={props.disabled}
|
||||
class={{
|
||||
[attrs.class as string]: attrs.class,
|
||||
[props.prefixCls]: true,
|
||||
[`${props.prefixCls}-checked`]: checked.value,
|
||||
[`${props.prefixCls}-disabled`]: props.disabled,
|
||||
}}
|
||||
ref={refSwitchNode}
|
||||
>
|
||||
{props.loadingIcon}
|
||||
<span class={`${props.prefixCls}-inner`}>
|
||||
{checked.value
|
||||
? getPropsSlot(slots, props, 'checkedChildren')
|
||||
: getPropsSlot(slots, props, 'unCheckedChildren')}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
},
|
||||
});
|
2
v2-doc
2
v2-doc
@ -1 +1 @@
|
||||
Subproject commit 496ff9154658d1ff28917f0bea6adfcb0cd05d43
|
||||
Subproject commit 31d85319dcc0438b3c80957c99f57b931b047c11
|
Loading…
Reference in New Issue
Block a user