ant-design-vue/components/_util/wave/index.tsx

97 lines
2.5 KiB
Vue

import {
computed,
defineComponent,
getCurrentInstance,
nextTick,
onBeforeUnmount,
onMounted,
watch,
} from 'vue';
import useConfigInject from '../../config-provider/hooks/useConfigInject';
import isVisible from '../../vc-util/Dom/isVisible';
import classNames from '../classNames';
import { findDOMNode } from '../props-util';
import useStyle from './style';
import useWave from './useWave';
export interface WaveProps {
disabled?: boolean;
}
export default defineComponent({
compatConfig: { MODE: 3 },
name: 'Wave',
props: {
disabled: Boolean,
},
setup(props, { slots }) {
const instance = getCurrentInstance();
const { prefixCls } = useConfigInject('wave', props);
// ============================== Style ===============================
const [, hashId] = useStyle(prefixCls);
// =============================== Wave ===============================
const showWave = useWave(
instance,
computed(() => classNames(prefixCls.value, hashId.value)),
);
let onClick: (e: MouseEvent) => void;
const clear = () => {
const node = findDOMNode(instance);
node.removeEventListener('click', onClick, true);
};
onMounted(() => {
watch(
() => props.disabled,
() => {
clear();
nextTick(() => {
const node = findDOMNode(instance);
if (!node || node.nodeType !== 1 || props.disabled) {
return;
}
// Click handler
const onClick = (e: MouseEvent) => {
// Fix radio button click twice
if (
(e.target as HTMLElement).tagName === 'INPUT' ||
!isVisible(e.target as HTMLElement) ||
// No need wave
!node.getAttribute ||
node.getAttribute('disabled') ||
(node as HTMLInputElement).disabled ||
node.className.includes('disabled') ||
node.className.includes('-leave')
) {
return;
}
showWave();
};
// Bind events
node.addEventListener('click', onClick, true);
});
},
{
immediate: true,
flush: 'post',
},
);
});
onBeforeUnmount(() => {
clear();
});
return () => {
// ============================== Render ==============================
const children = slots.default?.()[0];
return children;
};
},
});