File tree 6 files changed +93
-7
lines changed
packages/coreui-react/src
6 files changed +93
-7
lines changed Original file line number Diff line number Diff line change @@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
7
7
import { usePopper } from '../../hooks'
8
8
import { fallbackPlacementsPropType , triggerPropType } from '../../props'
9
9
import type { Placements , Triggers } from '../../types'
10
- import { getRTLPlacement } from '../../utils'
10
+ import { getRTLPlacement , getTransitionDurationFromElement } from '../../utils'
11
11
12
12
export interface CPopoverProps extends Omit < HTMLAttributes < HTMLDivElement > , 'title' | 'content' > {
13
13
/**
@@ -164,7 +164,7 @@ export const CPopover: FC<CPopoverProps> = ({
164
164
onExit = { onHide }
165
165
timeout = { {
166
166
enter : 0 ,
167
- exit : 200 ,
167
+ exit : popoverRef . current ? getTransitionDurationFromElement ( popoverRef . current ) + 50 : 200 ,
168
168
} }
169
169
unmountOnExit
170
170
>
Original file line number Diff line number Diff line change @@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
7
7
import { usePopper } from '../../hooks'
8
8
import { fallbackPlacementsPropType , triggerPropType } from '../../props'
9
9
import type { Placements , Triggers } from '../../types'
10
- import { getRTLPlacement } from '../../utils'
10
+ import { getRTLPlacement , getTransitionDurationFromElement } from '../../utils'
11
11
12
12
export interface CTooltipProps extends Omit < HTMLAttributes < HTMLDivElement > , 'content' > {
13
13
/**
@@ -158,7 +158,7 @@ export const CTooltip: FC<CTooltipProps> = ({
158
158
onExit = { onHide }
159
159
timeout = { {
160
160
enter : 0 ,
161
- exit : 200 ,
161
+ exit : tooltipRef . current ? getTransitionDurationFromElement ( tooltipRef . current ) + 50 : 200 ,
162
162
} }
163
163
unmountOnExit
164
164
>
Original file line number Diff line number Diff line change @@ -2,6 +2,8 @@ import { useRef } from 'react'
2
2
import { createPopper } from '@popperjs/core'
3
3
import type { Instance , Options } from '@popperjs/core'
4
4
5
+ import { executeAfterTransition } from '../utils'
6
+
5
7
interface UsePopperOutput {
6
8
popper : Instance | undefined
7
9
initPopper : ( reference : HTMLElement , popper : HTMLElement , options : Partial < Options > ) => void
@@ -10,14 +12,20 @@ interface UsePopperOutput {
10
12
11
13
export const usePopper = ( ) : UsePopperOutput => {
12
14
const _popper = useRef < Instance > ( )
15
+ const el = useRef < HTMLElement > ( )
13
16
14
17
const initPopper = ( reference : HTMLElement , popper : HTMLElement , options : Partial < Options > ) => {
15
18
_popper . current = createPopper ( reference , popper , options )
19
+ el . current = popper
16
20
}
17
21
18
22
const destroyPopper = ( ) => {
19
- if ( _popper . current ) {
20
- _popper . current . destroy ( )
23
+ const popperInstance = _popper . current
24
+
25
+ if ( popperInstance && el . current ) {
26
+ executeAfterTransition ( ( ) => {
27
+ popperInstance . destroy ( )
28
+ } , el . current )
21
29
}
22
30
23
31
_popper . current = undefined
Original file line number Diff line number Diff line change
1
+ import getTransitionDurationFromElement from './getTransitionDurationFromElement'
2
+
3
+ const execute = ( callback : ( ) => void ) => {
4
+ if ( typeof callback === 'function' ) {
5
+ callback ( )
6
+ }
7
+ }
8
+
9
+ const triggerTransitionEnd = ( element : HTMLElement ) => {
10
+ element . dispatchEvent ( new Event ( 'transitionend' ) )
11
+ }
12
+
13
+ const executeAfterTransition = (
14
+ callback : ( ) => void ,
15
+ transitionElement : HTMLElement ,
16
+ waitForTransition = true ,
17
+ ) => {
18
+ if ( ! waitForTransition ) {
19
+ execute ( callback )
20
+ return
21
+ }
22
+
23
+ const durationPadding = 5
24
+ const emulatedDuration = getTransitionDurationFromElement ( transitionElement ) + durationPadding
25
+
26
+ let called = false
27
+
28
+ const handler = ( { target } : { target : any } ) => {
29
+ if ( target !== transitionElement ) {
30
+ return
31
+ }
32
+
33
+ called = true
34
+ transitionElement . removeEventListener ( 'transitionend' , handler )
35
+ execute ( callback )
36
+ }
37
+
38
+ transitionElement . addEventListener ( 'transitionend' , handler )
39
+ setTimeout ( ( ) => {
40
+ if ( ! called ) {
41
+ triggerTransitionEnd ( transitionElement )
42
+ }
43
+ } , emulatedDuration )
44
+ }
45
+
46
+ export default executeAfterTransition
Original file line number Diff line number Diff line change
1
+ const getTransitionDurationFromElement = ( element : HTMLElement ) => {
2
+ if ( ! element ) {
3
+ return 0
4
+ }
5
+
6
+ // Get transition-duration of the element
7
+ let { transitionDuration, transitionDelay } = window . getComputedStyle ( element )
8
+
9
+ const floatTransitionDuration = Number . parseFloat ( transitionDuration )
10
+ const floatTransitionDelay = Number . parseFloat ( transitionDelay )
11
+
12
+ // Return 0 if element or transition duration is not found
13
+ if ( ! floatTransitionDuration && ! floatTransitionDelay ) {
14
+ return 0
15
+ }
16
+
17
+ // If multiple durations are defined, take the first
18
+ transitionDuration = transitionDuration . split ( ',' ) [ 0 ]
19
+ transitionDelay = transitionDelay . split ( ',' ) [ 0 ]
20
+
21
+ return ( Number . parseFloat ( transitionDuration ) + Number . parseFloat ( transitionDelay ) ) * 1000
22
+ }
23
+
24
+ export default getTransitionDurationFromElement
Original file line number Diff line number Diff line change
1
+ import executeAfterTransition from './executeAfterTransition'
1
2
import getRTLPlacement from './getRTLPlacement'
3
+ import getTransitionDurationFromElement from './getTransitionDurationFromElement'
2
4
import isInViewport from './isInViewport'
3
5
import isRTL from './isRTL'
4
6
5
- export { getRTLPlacement , isInViewport , isRTL }
7
+ export {
8
+ executeAfterTransition ,
9
+ getRTLPlacement ,
10
+ getTransitionDurationFromElement ,
11
+ isInViewport ,
12
+ isRTL ,
13
+ }
You can’t perform that action at this time.
0 commit comments