@coreui/react 4.9.2 → 4.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/components/modal/CModal.d.ts +6 -0
- package/dist/components/popover/CPopover.d.ts +2 -2
- package/dist/components/tooltip/CTooltip copy.d.ts +60 -0
- package/dist/components/tooltip/CTooltip.d.ts +2 -2
- package/dist/index.es.js +122 -50
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +122 -50
- package/dist/index.js.map +1 -1
- package/dist/utils/executeAfterTransition.d.ts +2 -0
- package/dist/utils/getTransitionDurationFromElement.d.ts +2 -0
- package/dist/utils/index.d.ts +3 -1
- package/package.json +1 -1
- package/src/components/modal/CModal.tsx +20 -6
- package/src/components/offcanvas/COffcanvas.tsx +1 -1
- package/src/components/popover/CPopover.tsx +127 -118
- package/src/components/sidebar/CSidebar.tsx +1 -1
- package/src/components/tooltip/CTooltip.tsx +132 -115
- package/src/hooks/usePopper.ts +10 -2
- package/src/utils/executeAfterTransition.ts +46 -0
- package/src/utils/getTransitionDurationFromElement.ts +24 -0
- package/src/utils/index.ts +9 -1
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
HTMLAttributes,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useRef,
|
|
6
|
+
useEffect,
|
|
7
|
+
useState,
|
|
8
|
+
} from 'react'
|
|
2
9
|
import { createPortal } from 'react-dom'
|
|
3
10
|
import classNames from 'classnames'
|
|
4
11
|
import PropTypes from 'prop-types'
|
|
5
12
|
import { Transition } from 'react-transition-group'
|
|
6
13
|
|
|
7
|
-
import { usePopper } from '../../hooks'
|
|
14
|
+
import { useForkedRef, usePopper } from '../../hooks'
|
|
8
15
|
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
16
|
import type { Placements, Triggers } from '../../types'
|
|
10
|
-
import { getRTLPlacement } from '../../utils'
|
|
17
|
+
import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
|
|
11
18
|
|
|
12
19
|
export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {
|
|
13
20
|
/**
|
|
@@ -64,129 +71,139 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
|
|
|
64
71
|
visible?: boolean
|
|
65
72
|
}
|
|
66
73
|
|
|
67
|
-
export const CTooltip
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
export const CTooltip = forwardRef<HTMLDivElement, CTooltipProps>(
|
|
75
|
+
(
|
|
76
|
+
{
|
|
77
|
+
children,
|
|
78
|
+
animation = true,
|
|
79
|
+
className,
|
|
80
|
+
content,
|
|
81
|
+
delay = 0,
|
|
82
|
+
fallbackPlacements = ['top', 'right', 'bottom', 'left'],
|
|
83
|
+
offset = [0, 6],
|
|
84
|
+
onHide,
|
|
85
|
+
onShow,
|
|
86
|
+
placement = 'top',
|
|
87
|
+
trigger = ['hover', 'focus'],
|
|
88
|
+
visible,
|
|
89
|
+
...rest
|
|
90
|
+
},
|
|
91
|
+
ref,
|
|
92
|
+
) => {
|
|
93
|
+
const tooltipRef = useRef(null)
|
|
94
|
+
const togglerRef = useRef(null)
|
|
95
|
+
const forkedRef = useForkedRef(ref, tooltipRef)
|
|
86
96
|
|
|
87
|
-
|
|
97
|
+
const { initPopper, destroyPopper } = usePopper()
|
|
98
|
+
const [_visible, setVisible] = useState(visible)
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
|
|
101
|
+
|
|
102
|
+
const popperConfig = {
|
|
103
|
+
modifiers: [
|
|
104
|
+
{
|
|
105
|
+
name: 'arrow',
|
|
106
|
+
options: {
|
|
107
|
+
element: '.tooltip-arrow',
|
|
108
|
+
},
|
|
95
109
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
110
|
+
{
|
|
111
|
+
name: 'flip',
|
|
112
|
+
options: {
|
|
113
|
+
fallbackPlacements: fallbackPlacements,
|
|
114
|
+
},
|
|
101
115
|
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
116
|
+
{
|
|
117
|
+
name: 'offset',
|
|
118
|
+
options: {
|
|
119
|
+
offset: offset,
|
|
120
|
+
},
|
|
107
121
|
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
122
|
+
],
|
|
123
|
+
placement: getRTLPlacement(placement, togglerRef.current),
|
|
124
|
+
}
|
|
112
125
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
setVisible(visible)
|
|
128
|
+
}, [visible])
|
|
116
129
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (_visible && togglerRef.current && tooltipRef.current) {
|
|
132
|
+
initPopper(togglerRef.current, tooltipRef.current, popperConfig)
|
|
133
|
+
}
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
135
|
+
return () => {
|
|
136
|
+
destroyPopper()
|
|
137
|
+
}
|
|
138
|
+
}, [_visible])
|
|
126
139
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
const toggleVisible = (visible: boolean) => {
|
|
141
|
+
if (visible) {
|
|
142
|
+
setTimeout(() => setVisible(true), _delay.show)
|
|
143
|
+
return
|
|
144
|
+
}
|
|
132
145
|
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
setTimeout(() => setVisible(false), _delay.hide)
|
|
147
|
+
}
|
|
135
148
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
{
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
149
|
+
return (
|
|
150
|
+
<>
|
|
151
|
+
{React.cloneElement(children as React.ReactElement<any>, {
|
|
152
|
+
ref: togglerRef,
|
|
153
|
+
...((trigger === 'click' || trigger.includes('click')) && {
|
|
154
|
+
onClick: () => toggleVisible(!_visible),
|
|
155
|
+
}),
|
|
156
|
+
...((trigger === 'focus' || trigger.includes('focus')) && {
|
|
157
|
+
onFocus: () => toggleVisible(true),
|
|
158
|
+
onBlur: () => toggleVisible(false),
|
|
159
|
+
}),
|
|
160
|
+
...((trigger === 'hover' || trigger.includes('hover')) && {
|
|
161
|
+
onMouseEnter: () => toggleVisible(true),
|
|
162
|
+
onMouseLeave: () => toggleVisible(false),
|
|
163
|
+
}),
|
|
164
|
+
})}
|
|
165
|
+
{typeof window !== 'undefined' &&
|
|
166
|
+
createPortal(
|
|
167
|
+
<Transition
|
|
168
|
+
in={_visible}
|
|
169
|
+
mountOnEnter
|
|
170
|
+
nodeRef={tooltipRef}
|
|
171
|
+
onEnter={onShow}
|
|
172
|
+
onExit={onHide}
|
|
173
|
+
timeout={{
|
|
174
|
+
enter: 0,
|
|
175
|
+
exit: tooltipRef.current
|
|
176
|
+
? getTransitionDurationFromElement(tooltipRef.current) + 50
|
|
177
|
+
: 200,
|
|
178
|
+
}}
|
|
179
|
+
unmountOnExit
|
|
180
|
+
>
|
|
181
|
+
{(state) => (
|
|
182
|
+
<div
|
|
183
|
+
className={classNames(
|
|
184
|
+
'tooltip',
|
|
185
|
+
'bs-tooltip-auto',
|
|
186
|
+
{
|
|
187
|
+
fade: animation,
|
|
188
|
+
show: state === 'entered',
|
|
189
|
+
},
|
|
190
|
+
className,
|
|
191
|
+
)}
|
|
192
|
+
ref={forkedRef}
|
|
193
|
+
role="tooltip"
|
|
194
|
+
{...rest}
|
|
195
|
+
>
|
|
196
|
+
<div className="tooltip-arrow"></div>
|
|
197
|
+
<div className="tooltip-inner">{content}</div>
|
|
198
|
+
</div>
|
|
199
|
+
)}
|
|
200
|
+
</Transition>,
|
|
201
|
+
document.body,
|
|
202
|
+
)}
|
|
203
|
+
</>
|
|
204
|
+
)
|
|
205
|
+
},
|
|
206
|
+
)
|
|
190
207
|
|
|
191
208
|
CTooltip.propTypes = {
|
|
192
209
|
animation: PropTypes.bool,
|
package/src/hooks/usePopper.ts
CHANGED
|
@@ -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
|
-
|
|
20
|
-
|
|
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
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
|
@@ -0,0 +1,24 @@
|
|
|
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
|
package/src/utils/index.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
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 {
|
|
7
|
+
export {
|
|
8
|
+
executeAfterTransition,
|
|
9
|
+
getRTLPlacement,
|
|
10
|
+
getTransitionDurationFromElement,
|
|
11
|
+
isInViewport,
|
|
12
|
+
isRTL,
|
|
13
|
+
}
|