File tree Expand file tree Collapse file tree 6 files changed +93
-7
lines changed
packages/coreui-react/src Expand file tree Collapse file tree 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'
77import { usePopper } from '../../hooks'
88import { fallbackPlacementsPropType , triggerPropType } from '../../props'
99import type { Placements , Triggers } from '../../types'
10- import { getRTLPlacement } from '../../utils'
10+ import { getRTLPlacement , getTransitionDurationFromElement } from '../../utils'
1111
1212export interface CPopoverProps extends Omit < HTMLAttributes < HTMLDivElement > , 'title' | 'content' > {
1313 /**
@@ -164,7 +164,7 @@ export const CPopover: FC<CPopoverProps> = ({
164164 onExit = { onHide }
165165 timeout = { {
166166 enter : 0 ,
167- exit : 200 ,
167+ exit : popoverRef . current ? getTransitionDurationFromElement ( popoverRef . current ) + 50 : 200 ,
168168 } }
169169 unmountOnExit
170170 >
Original file line number Diff line number Diff line change @@ -7,7 +7,7 @@ import { Transition } from 'react-transition-group'
77import { usePopper } from '../../hooks'
88import { fallbackPlacementsPropType , triggerPropType } from '../../props'
99import type { Placements , Triggers } from '../../types'
10- import { getRTLPlacement } from '../../utils'
10+ import { getRTLPlacement , getTransitionDurationFromElement } from '../../utils'
1111
1212export interface CTooltipProps extends Omit < HTMLAttributes < HTMLDivElement > , 'content' > {
1313 /**
@@ -158,7 +158,7 @@ export const CTooltip: FC<CTooltipProps> = ({
158158 onExit = { onHide }
159159 timeout = { {
160160 enter : 0 ,
161- exit : 200 ,
161+ exit : tooltipRef . current ? getTransitionDurationFromElement ( tooltipRef . current ) + 50 : 200 ,
162162 } }
163163 unmountOnExit
164164 >
Original file line number Diff line number Diff line change @@ -2,6 +2,8 @@ import { useRef } from 'react'
22import { createPopper } from '@popperjs/core'
33import type { Instance , Options } from '@popperjs/core'
44
5+ import { executeAfterTransition } from '../utils'
6+
57interface UsePopperOutput {
68 popper : Instance | undefined
79 initPopper : ( reference : HTMLElement , popper : HTMLElement , options : Partial < Options > ) => void
@@ -10,14 +12,20 @@ interface UsePopperOutput {
1012
1113export const usePopper = ( ) : UsePopperOutput => {
1214 const _popper = useRef < Instance > ( )
15+ const el = useRef < HTMLElement > ( )
1316
1417 const initPopper = ( reference : HTMLElement , popper : HTMLElement , options : Partial < Options > ) => {
1518 _popper . current = createPopper ( reference , popper , options )
19+ el . current = popper
1620 }
1721
1822 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 )
2129 }
2230
2331 _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'
12import getRTLPlacement from './getRTLPlacement'
3+ import getTransitionDurationFromElement from './getTransitionDurationFromElement'
24import isInViewport from './isInViewport'
35import isRTL from './isRTL'
46
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