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, wave } = useConfigInject('wave', props); // ============================== Style =============================== const [, hashId] = useStyle(prefixCls); // =============================== Wave =============================== const showWave = useWave( computed(() => classNames(prefixCls.value, hashId.value)), wave, ); let onClick: (e: MouseEvent) => void; const clear = () => { const node = findDOMNode(instance) as HTMLElement; node.removeEventListener('click', onClick, true); }; onMounted(() => { watch( () => props.disabled, () => { clear(); nextTick(() => { const node: HTMLElement = findDOMNode(instance); node?.removeEventListener('click', onClick, true); if (!node || node.nodeType !== 1 || props.disabled) { return; } // Click handler 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; }; }, });