1- import { nextTick , inject , defineComponent } from 'vue' ;
1+ import { nextTick , defineComponent , getCurrentInstance , onMounted , onBeforeUnmount } from 'vue' ;
22import TransitionEvents from './css-animation/Event' ;
33import raf from './raf' ;
4- import { defaultConfigProvider } from '../config-provider' ;
54import { findDOMNode } from './props-util' ;
6- let styleForPesudo ;
5+ import useConfigInject from './hooks/useConfigInject' ;
6+ let styleForPesudo : HTMLStyleElement ;
77
88// Where el is the DOM element you'd like to test for visibility
9- function isHidden ( element ) {
9+ function isHidden ( element : HTMLElement ) {
1010 if ( process . env . NODE_ENV === 'test' ) {
1111 return false ;
1212 }
1313 return ! element || element . offsetParent === null ;
1414}
15- function isNotGrey ( color ) {
15+ function isNotGrey ( color : string ) {
1616 // eslint-disable-next-line no-useless-escape
1717 const match = ( color || '' ) . match ( / r g b a ? \( ( \d * ) , ( \d * ) , ( \d * ) ( , [ \. \d ] * ) ? \) / ) ;
1818 if ( match && match [ 1 ] && match [ 2 ] && match [ 3 ] ) {
@@ -22,40 +22,51 @@ function isNotGrey(color) {
2222}
2323export default defineComponent ( {
2424 name : 'Wave' ,
25- props : [ 'insertExtraNode' ] ,
26- setup ( ) {
27- const configProvider = inject ( 'configProvider' , defaultConfigProvider ) ;
28- return {
29- configProvider,
30- } ;
25+ props : {
26+ insertExtraNode : Boolean ,
3127 } ,
32- mounted ( ) {
33- nextTick ( ( ) => {
34- const node = findDOMNode ( this ) ;
35- if ( node . nodeType !== 1 ) {
28+ setup ( props , { slots, expose } ) {
29+ const instance = getCurrentInstance ( ) ;
30+ const { csp } = useConfigInject ( '' , props ) ;
31+ expose ( {
32+ csp,
33+ } ) ;
34+ let eventIns = null ;
35+ let clickWaveTimeoutId = null ;
36+ let animationStartId = null ;
37+ let animationStart = false ;
38+ let extraNode = null ;
39+ let isUnmounted = false ;
40+ const onTransitionStart = e => {
41+ if ( isUnmounted ) return ;
42+
43+ const node = findDOMNode ( instance ) ;
44+ if ( ! e || e . target !== node ) {
3645 return ;
3746 }
38- this . instance = this . bindAnimationEvent ( node ) ;
39- } ) ;
40- } ,
41- beforeUnmount ( ) {
42- if ( this . instance ) {
43- this . instance . cancel ( ) ;
44- }
45- if ( this . clickWaveTimeoutId ) {
46- clearTimeout ( this . clickWaveTimeoutId ) ;
47- }
48- } ,
49- methods : {
50- onClick ( node , waveColor ) {
47+
48+ if ( ! animationStart ) {
49+ resetEffect ( node ) ;
50+ }
51+ } ;
52+ const onTransitionEnd = ( e : any ) => {
53+ if ( ! e || e . animationName !== 'fadeEffect' ) {
54+ return ;
55+ }
56+ resetEffect ( e . target ) ;
57+ } ;
58+ const getAttributeName = ( ) => {
59+ const { insertExtraNode } = props ;
60+ return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node' ;
61+ } ;
62+ const onClick = ( node : HTMLElement , waveColor : string ) => {
5163 if ( ! node || isHidden ( node ) || node . className . indexOf ( '-leave' ) >= 0 ) {
5264 return ;
5365 }
54- const { insertExtraNode } = this . $props ;
55- this . extraNode = document . createElement ( 'div' ) ;
56- const extraNode = this . extraNode ;
66+ const { insertExtraNode } = props ;
67+ extraNode = document . createElement ( 'div' ) ;
5768 extraNode . className = 'ant-click-animating-node' ;
58- const attributeName = this . getAttributeName ( ) ;
69+ const attributeName = getAttributeName ( ) ;
5970 node . removeAttribute ( attributeName ) ;
6071 node . setAttribute ( attributeName , 'true' ) ;
6172 // Not white or transparent or grey
@@ -69,8 +80,8 @@ export default defineComponent({
6980 waveColor !== 'transparent'
7081 ) {
7182 // Add nonce if CSP exist
72- if ( this . csp && this . csp . nonce ) {
73- styleForPesudo . nonce = this . csp . nonce ;
83+ if ( csp . value ? .nonce ) {
84+ styleForPesudo . nonce = csp . value . nonce ;
7485 }
7586 extraNode . style . borderColor = waveColor ;
7687 styleForPesudo . innerHTML = `
@@ -84,32 +95,26 @@ export default defineComponent({
8495 if ( insertExtraNode ) {
8596 node . appendChild ( extraNode ) ;
8697 }
87- TransitionEvents . addStartEventListener ( node , this . onTransitionStart ) ;
88- TransitionEvents . addEndEventListener ( node , this . onTransitionEnd ) ;
89- } ,
90- onTransitionStart ( e ) {
91- if ( this . _ . isUnmounted ) return ;
92-
93- const node = findDOMNode ( this ) ;
94- if ( ! e || e . target !== node ) {
98+ TransitionEvents . addStartEventListener ( node , onTransitionStart ) ;
99+ TransitionEvents . addEndEventListener ( node , onTransitionEnd ) ;
100+ } ;
101+ const resetEffect = ( node : HTMLElement ) => {
102+ if ( ! node || node === extraNode || ! ( node instanceof Element ) ) {
95103 return ;
96104 }
97-
98- if ( ! this . animationStart ) {
99- this . resetEffect ( node ) ;
105+ const { insertExtraNode } = props ;
106+ const attributeName = getAttributeName ( ) ;
107+ node . setAttribute ( attributeName , 'false' ) ; // edge has bug on `removeAttribute` #14466
108+ if ( styleForPesudo ) {
109+ styleForPesudo . innerHTML = '' ;
100110 }
101- } ,
102- onTransitionEnd ( e ) {
103- if ( ! e || e . animationName !== 'fadeEffect' ) {
104- return ;
111+ if ( insertExtraNode && extraNode && node . contains ( extraNode ) ) {
112+ node . removeChild ( extraNode ) ;
105113 }
106- this . resetEffect ( e . target ) ;
107- } ,
108- getAttributeName ( ) {
109- const { insertExtraNode } = this . $props ;
110- return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node' ;
111- } ,
112- bindAnimationEvent ( node ) {
114+ TransitionEvents . removeStartEventListener ( node , onTransitionStart ) ;
115+ TransitionEvents . removeEndEventListener ( node , onTransitionEnd ) ;
116+ } ;
117+ const bindAnimationEvent = ( node : HTMLElement ) => {
113118 if (
114119 ! node ||
115120 ! node . getAttribute ||
@@ -118,57 +123,51 @@ export default defineComponent({
118123 ) {
119124 return ;
120125 }
121- const onClick = e => {
126+ const newClick = ( e : MouseEvent ) => {
122127 // Fix radio button click twice
123- if ( e . target . tagName === 'INPUT' || isHidden ( e . target ) ) {
128+ if ( ( e . target as any ) . tagName === 'INPUT' || isHidden ( e . target as HTMLElement ) ) {
124129 return ;
125130 }
126- this . resetEffect ( node ) ;
131+ resetEffect ( node ) ;
127132 // Get wave color from target
128133 const waveColor =
129134 getComputedStyle ( node ) . getPropertyValue ( 'border-top-color' ) || // Firefox Compatible
130135 getComputedStyle ( node ) . getPropertyValue ( 'border-color' ) ||
131136 getComputedStyle ( node ) . getPropertyValue ( 'background-color' ) ;
132- this . clickWaveTimeoutId = setTimeout ( ( ) => this . onClick ( node , waveColor ) , 0 ) ;
133- raf . cancel ( this . animationStartId ) ;
134- this . animationStart = true ;
137+ clickWaveTimeoutId = setTimeout ( ( ) => onClick ( node , waveColor ) , 0 ) ;
138+ raf . cancel ( animationStartId ) ;
139+ animationStart = true ;
135140
136141 // Render to trigger transition event cost 3 frames. Let's delay 10 frames to reset this.
137- this . animationStartId = raf ( ( ) => {
138- this . animationStart = false ;
142+ animationStartId = raf ( ( ) => {
143+ animationStart = false ;
139144 } , 10 ) ;
140145 } ;
141- node . addEventListener ( 'click' , onClick , true ) ;
146+ node . addEventListener ( 'click' , newClick , true ) ;
142147 return {
143148 cancel : ( ) => {
144- node . removeEventListener ( 'click' , onClick , true ) ;
149+ node . removeEventListener ( 'click' , newClick , true ) ;
145150 } ,
146151 } ;
147- } ,
148-
149- resetEffect ( node ) {
150- if ( ! node || node === this . extraNode || ! ( node instanceof Element ) ) {
151- return ;
152- }
153- const { insertExtraNode } = this . $props ;
154- const attributeName = this . getAttributeName ( ) ;
155- node . setAttribute ( attributeName , 'false' ) ; // edge has bug on `removeAttribute` #14466
156- if ( styleForPesudo ) {
157- styleForPesudo . innerHTML = '' ;
158- }
159- if ( insertExtraNode && this . extraNode && node . contains ( this . extraNode ) ) {
160- node . removeChild ( this . extraNode ) ;
152+ } ;
153+ onMounted ( ( ) => {
154+ nextTick ( ( ) => {
155+ const node = findDOMNode ( instance ) ;
156+ if ( node . nodeType !== 1 ) {
157+ return ;
158+ }
159+ eventIns = bindAnimationEvent ( node ) ;
160+ } ) ;
161+ } ) ;
162+ onBeforeUnmount ( ( ) => {
163+ if ( eventIns ) {
164+ eventIns . cancel ( ) ;
161165 }
162- TransitionEvents . removeStartEventListener ( node , this . onTransitionStart ) ;
163- TransitionEvents . removeEndEventListener ( node , this . onTransitionEnd ) ;
164- } ,
165- } ,
166-
167- render ( ) {
168- const csp = this . configProvider . csp ;
169- if ( csp ) {
170- this . csp = csp ;
171- }
172- return this . $slots . default ?. ( ) [ 0 ] ;
166+ clearTimeout ( clickWaveTimeoutId ) ;
167+ isUnmounted = true ;
168+ } ) ;
169+ return ( ) => {
170+ return slots . default ?.( ) [ 0 ] ;
171+ } ;
173172 } ,
174173} ) ;
0 commit comments