@coreui/react 4.9.0-beta.0 → 4.9.0-beta.2
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/dropdown/CDropdown.d.ts +8 -1
- package/dist/components/dropdown/CDropdownMenu.d.ts +3 -4
- package/dist/components/dropdown copy/CDropdown.d.ts +89 -0
- package/dist/components/dropdown copy/CDropdownDivider.d.ts +8 -0
- package/dist/components/dropdown copy/CDropdownHeader.d.ts +12 -0
- package/dist/components/dropdown copy/CDropdownItem.d.ts +13 -0
- package/dist/components/dropdown copy/CDropdownItemPlain.d.ts +12 -0
- package/dist/components/dropdown copy/CDropdownMenu.d.ts +13 -0
- package/dist/components/dropdown copy/CDropdownToggle.d.ts +24 -0
- package/dist/components/dropdown copy/index.d.ts +8 -0
- package/dist/components/popover/CPopover.d.ts +22 -1
- package/dist/components/progress/CProgress.d.ts +6 -0
- package/dist/components/progress/CProgressStacked.d.ts +12 -0
- package/dist/components/progress/index.d.ts +2 -1
- package/dist/components/tooltip/CTooltip.d.ts +22 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/useColorModes.d.ts +4 -2
- package/dist/hooks/usePopper.d.ts +8 -0
- package/dist/index.es.js +1527 -1915
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1312 -1716
- package/dist/index.js.map +1 -1
- package/dist/props.d.ts +1 -0
- package/dist/utils/getRTLPlacement.d.ts +3 -0
- package/dist/utils/index.d.ts +2 -1
- package/package.json +5 -5
- package/src/components/dropdown/CDropdown.tsx +130 -45
- package/src/components/dropdown/CDropdownMenu.tsx +41 -138
- package/src/components/dropdown/CDropdownToggle.tsx +6 -15
- package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +0 -1
- package/src/components/popover/CPopover.tsx +76 -51
- package/src/components/popover/__tests__/__snapshots__/CPopover.spec.tsx.snap +0 -21
- package/src/components/progress/CProgress.tsx +43 -8
- package/src/components/progress/CProgressBar.tsx +5 -6
- package/src/components/progress/CProgressStacked.tsx +39 -0
- package/src/components/progress/index.ts +2 -1
- package/src/components/tooltip/CTooltip.tsx +77 -52
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useColorModes.ts +23 -11
- package/src/hooks/usePopper.ts +31 -0
- package/src/props.ts +5 -0
- package/src/utils/getRTLPlacement.ts +18 -0
- package/src/utils/index.ts +2 -1
|
@@ -3,13 +3,19 @@ import { createPortal } from 'react-dom'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
5
|
import { Transition } from 'react-transition-group'
|
|
6
|
-
import { createPopper, Instance, Placement } from '@popperjs/core'
|
|
7
6
|
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
7
|
+
import { usePopper } from '../../hooks'
|
|
8
|
+
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
|
+
import type { Placements, Triggers } from '../../types'
|
|
10
|
+
import { getRTLPlacement } from '../../utils'
|
|
11
11
|
|
|
12
12
|
export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title' | 'content'> {
|
|
13
|
+
/**
|
|
14
|
+
* Apply a CSS fade transition to the popover.
|
|
15
|
+
*
|
|
16
|
+
* @since 4.9.0-beta.2
|
|
17
|
+
*/
|
|
18
|
+
animation?: boolean
|
|
13
19
|
/**
|
|
14
20
|
* A string of all className you want applied to the component.
|
|
15
21
|
*/
|
|
@@ -22,6 +28,18 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
|
|
|
22
28
|
* Offset of the popover relative to its target.
|
|
23
29
|
*/
|
|
24
30
|
offset?: [number, number]
|
|
31
|
+
/**
|
|
32
|
+
* The delay for displaying and hiding the popover (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
|
|
33
|
+
*
|
|
34
|
+
* @since 4.9.0-beta.2
|
|
35
|
+
*/
|
|
36
|
+
delay?: number | { show: number; hide: number }
|
|
37
|
+
/**
|
|
38
|
+
* Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
|
|
39
|
+
*
|
|
40
|
+
* @since 4.9.0-beta.2
|
|
41
|
+
*/
|
|
42
|
+
fallbackPlacements?: Placements | Placements[]
|
|
25
43
|
/**
|
|
26
44
|
* Callback fired when the component requests to be hidden.
|
|
27
45
|
*/
|
|
@@ -50,24 +68,13 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
|
|
|
50
68
|
visible?: boolean
|
|
51
69
|
}
|
|
52
70
|
|
|
53
|
-
const getPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
|
|
54
|
-
switch (placement) {
|
|
55
|
-
case 'right': {
|
|
56
|
-
return isRTL(element) ? 'left' : 'right'
|
|
57
|
-
}
|
|
58
|
-
case 'left': {
|
|
59
|
-
return isRTL(element) ? 'right' : 'left'
|
|
60
|
-
}
|
|
61
|
-
default: {
|
|
62
|
-
return placement as Placement
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
71
|
export const CPopover: FC<CPopoverProps> = ({
|
|
68
72
|
children,
|
|
73
|
+
animation = true,
|
|
69
74
|
className,
|
|
70
75
|
content,
|
|
76
|
+
delay = 0,
|
|
77
|
+
fallbackPlacements = ['top', 'right', 'bottom', 'left'],
|
|
71
78
|
offset = [0, 8],
|
|
72
79
|
onHide,
|
|
73
80
|
onShow,
|
|
@@ -79,16 +86,42 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
79
86
|
}) => {
|
|
80
87
|
const popoverRef = useRef(null)
|
|
81
88
|
const togglerRef = useRef(null)
|
|
82
|
-
const
|
|
89
|
+
const { initPopper, destroyPopper } = usePopper()
|
|
83
90
|
const [_visible, setVisible] = useState(visible)
|
|
84
91
|
|
|
92
|
+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
|
|
93
|
+
|
|
94
|
+
const popperConfig = {
|
|
95
|
+
modifiers: [
|
|
96
|
+
{
|
|
97
|
+
name: 'arrow',
|
|
98
|
+
options: {
|
|
99
|
+
element: '.popover-arrow',
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'flip',
|
|
104
|
+
options: {
|
|
105
|
+
fallbackPlacements: fallbackPlacements,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'offset',
|
|
110
|
+
options: {
|
|
111
|
+
offset: offset,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
placement: getRTLPlacement(placement, togglerRef.current),
|
|
116
|
+
}
|
|
117
|
+
|
|
85
118
|
useEffect(() => {
|
|
86
119
|
setVisible(visible)
|
|
87
120
|
}, [visible])
|
|
88
121
|
|
|
89
122
|
useEffect(() => {
|
|
90
|
-
if (_visible) {
|
|
91
|
-
initPopper()
|
|
123
|
+
if (_visible && togglerRef.current && popoverRef.current) {
|
|
124
|
+
initPopper(togglerRef.current, popoverRef.current, popperConfig)
|
|
92
125
|
}
|
|
93
126
|
|
|
94
127
|
return () => {
|
|
@@ -96,28 +129,13 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
96
129
|
}
|
|
97
130
|
}, [_visible])
|
|
98
131
|
|
|
99
|
-
const
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
{
|
|
104
|
-
name: 'offset',
|
|
105
|
-
options: {
|
|
106
|
-
offset: offset,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
placement: getPlacement(placement, togglerRef.current),
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const destroyPopper = () => {
|
|
116
|
-
if (popper.current) {
|
|
117
|
-
popper.current.destroy()
|
|
132
|
+
const toggleVisible = (visible: boolean) => {
|
|
133
|
+
if (visible) {
|
|
134
|
+
setTimeout(() => setVisible(true), _delay.show)
|
|
135
|
+
return
|
|
118
136
|
}
|
|
119
137
|
|
|
120
|
-
|
|
138
|
+
setTimeout(() => setVisible(false), _delay.hide)
|
|
121
139
|
}
|
|
122
140
|
|
|
123
141
|
return (
|
|
@@ -125,15 +143,15 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
125
143
|
{React.cloneElement(children as React.ReactElement<any>, {
|
|
126
144
|
ref: togglerRef,
|
|
127
145
|
...((trigger === 'click' || trigger.includes('click')) && {
|
|
128
|
-
onClick: () =>
|
|
146
|
+
onClick: () => toggleVisible(!_visible),
|
|
129
147
|
}),
|
|
130
148
|
...((trigger === 'focus' || trigger.includes('focus')) && {
|
|
131
|
-
onFocus: () =>
|
|
132
|
-
onBlur: () =>
|
|
149
|
+
onFocus: () => toggleVisible(true),
|
|
150
|
+
onBlur: () => toggleVisible(false),
|
|
133
151
|
}),
|
|
134
152
|
...((trigger === 'hover' || trigger.includes('hover')) && {
|
|
135
|
-
onMouseEnter: () =>
|
|
136
|
-
onMouseLeave: () =>
|
|
153
|
+
onMouseEnter: () => toggleVisible(true),
|
|
154
|
+
onMouseLeave: () => toggleVisible(false),
|
|
137
155
|
}),
|
|
138
156
|
})}
|
|
139
157
|
{typeof window !== 'undefined' &&
|
|
@@ -154,11 +172,9 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
154
172
|
<div
|
|
155
173
|
className={classNames(
|
|
156
174
|
'popover',
|
|
157
|
-
|
|
158
|
-
.replace('left', 'start')
|
|
159
|
-
.replace('right', 'end')}`,
|
|
160
|
-
'fade',
|
|
175
|
+
'bs-popover-auto',
|
|
161
176
|
{
|
|
177
|
+
fade: animation,
|
|
162
178
|
show: state === 'entered',
|
|
163
179
|
},
|
|
164
180
|
className,
|
|
@@ -167,7 +183,7 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
167
183
|
role="tooltip"
|
|
168
184
|
{...rest}
|
|
169
185
|
>
|
|
170
|
-
<div
|
|
186
|
+
<div className="popover-arrow"></div>
|
|
171
187
|
<div className="popover-header">{title}</div>
|
|
172
188
|
<div className="popover-body">{content}</div>
|
|
173
189
|
</div>
|
|
@@ -180,9 +196,18 @@ export const CPopover: FC<CPopoverProps> = ({
|
|
|
180
196
|
}
|
|
181
197
|
|
|
182
198
|
CPopover.propTypes = {
|
|
199
|
+
animation: PropTypes.bool,
|
|
183
200
|
children: PropTypes.node,
|
|
184
201
|
className: PropTypes.string,
|
|
185
202
|
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
203
|
+
delay: PropTypes.oneOfType([
|
|
204
|
+
PropTypes.number,
|
|
205
|
+
PropTypes.shape({
|
|
206
|
+
show: PropTypes.number.isRequired,
|
|
207
|
+
hide: PropTypes.number.isRequired,
|
|
208
|
+
}),
|
|
209
|
+
]),
|
|
210
|
+
fallbackPlacements: fallbackPlacementsPropType,
|
|
186
211
|
offset: PropTypes.any, // TODO: find good proptype
|
|
187
212
|
onHide: PropTypes.func,
|
|
188
213
|
onShow: PropTypes.func,
|
|
@@ -8,27 +8,6 @@ exports[`CPopover customize 1`] = `
|
|
|
8
8
|
>
|
|
9
9
|
Test
|
|
10
10
|
</button>
|
|
11
|
-
<div
|
|
12
|
-
class="popover bs-popover-end fade"
|
|
13
|
-
role="tooltip"
|
|
14
|
-
style="position: absolute; left: 0px; top: 0px; margin: 0px;"
|
|
15
|
-
>
|
|
16
|
-
<div
|
|
17
|
-
class="popover-arrow"
|
|
18
|
-
data-popper-arrow="true"
|
|
19
|
-
style="position: absolute;"
|
|
20
|
-
/>
|
|
21
|
-
<div
|
|
22
|
-
class="popover-header"
|
|
23
|
-
>
|
|
24
|
-
title
|
|
25
|
-
</div>
|
|
26
|
-
<div
|
|
27
|
-
class="popover-body"
|
|
28
|
-
>
|
|
29
|
-
content
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
11
|
</body>
|
|
33
12
|
`;
|
|
34
13
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { forwardRef, HTMLAttributes } from 'react'
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, useContext } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
+
import { CProgressStackedContext } from './CProgressStacked'
|
|
5
6
|
import { CProgressBar, CProgressBarProps } from './CProgressBar'
|
|
6
7
|
|
|
7
8
|
export interface CProgressProps
|
|
@@ -15,6 +16,12 @@ export interface CProgressProps
|
|
|
15
16
|
* Sets the height of the component. If you set that value the inner `<CProgressBar>` will automatically resize accordingly.
|
|
16
17
|
*/
|
|
17
18
|
height?: number
|
|
19
|
+
/**
|
|
20
|
+
* A string of all className you want applied to the <CProgressBar/> component.
|
|
21
|
+
*
|
|
22
|
+
* @since 4.9.0
|
|
23
|
+
*/
|
|
24
|
+
progressBarClassName?: string
|
|
18
25
|
/**
|
|
19
26
|
* Makes progress bar thinner.
|
|
20
27
|
*/
|
|
@@ -29,9 +36,10 @@ export interface CProgressProps
|
|
|
29
36
|
white?: boolean
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
// TODO: update markup and add '.progress-stacked' in v5
|
|
33
39
|
export const CProgress = forwardRef<HTMLDivElement, CProgressProps>(
|
|
34
|
-
({ children, className, height, thin, value
|
|
40
|
+
({ children, className, height, progressBarClassName, thin, value, white, ...rest }, ref) => {
|
|
41
|
+
const { stacked } = useContext(CProgressStackedContext)
|
|
42
|
+
|
|
35
43
|
return (
|
|
36
44
|
<div
|
|
37
45
|
className={classNames(
|
|
@@ -42,15 +50,41 @@ export const CProgress = forwardRef<HTMLDivElement, CProgressProps>(
|
|
|
42
50
|
},
|
|
43
51
|
className,
|
|
44
52
|
)}
|
|
45
|
-
|
|
53
|
+
{...(value !== undefined && {
|
|
54
|
+
role: 'progressbar',
|
|
55
|
+
'aria-valuenow': value,
|
|
56
|
+
'aria-valuemin': 0,
|
|
57
|
+
'aria-valuemax': 100,
|
|
58
|
+
})}
|
|
59
|
+
style={{
|
|
60
|
+
...(height ? { height: `${height}px` } : {}),
|
|
61
|
+
...(stacked ? { width: `${value}%` } : {}),
|
|
62
|
+
}}
|
|
46
63
|
ref={ref}
|
|
47
64
|
>
|
|
48
|
-
{
|
|
49
|
-
|
|
65
|
+
{React.Children.toArray(children).some(
|
|
66
|
+
// @ts-expect-error displayName is set in the CProgressBar component
|
|
67
|
+
(child) => child.type && child.type.displayName === 'CProgressBar',
|
|
68
|
+
) ? (
|
|
69
|
+
React.Children.map(children, (child) => {
|
|
70
|
+
// @ts-expect-error displayName is set in the CProgressBar component
|
|
71
|
+
if (React.isValidElement(child) && child.type.displayName === 'CProgressBar') {
|
|
72
|
+
return React.cloneElement(child, {
|
|
73
|
+
...(value && { value: value }),
|
|
74
|
+
...rest,
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return
|
|
79
|
+
})
|
|
80
|
+
) : (
|
|
81
|
+
<CProgressBar
|
|
82
|
+
{...(progressBarClassName && { className: progressBarClassName })}
|
|
83
|
+
value={value}
|
|
84
|
+
{...rest}
|
|
85
|
+
>
|
|
50
86
|
{children}
|
|
51
87
|
</CProgressBar>
|
|
52
|
-
) : (
|
|
53
|
-
children
|
|
54
88
|
)}
|
|
55
89
|
</div>
|
|
56
90
|
)
|
|
@@ -61,6 +95,7 @@ CProgress.propTypes = {
|
|
|
61
95
|
children: PropTypes.node,
|
|
62
96
|
className: PropTypes.string,
|
|
63
97
|
height: PropTypes.number,
|
|
98
|
+
progressBarClassName: PropTypes.string,
|
|
64
99
|
thin: PropTypes.bool,
|
|
65
100
|
value: PropTypes.number,
|
|
66
101
|
white: PropTypes.bool,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React, { forwardRef, HTMLAttributes } from 'react'
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, useContext } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
+
import { CProgressStackedContext } from './CProgressStacked'
|
|
5
6
|
import { colorPropType } from '../../props'
|
|
6
7
|
import type { Colors } from '../../types'
|
|
7
8
|
|
|
@@ -32,6 +33,8 @@ export interface CProgressBarProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
32
33
|
|
|
33
34
|
export const CProgressBar = forwardRef<HTMLDivElement, CProgressBarProps>(
|
|
34
35
|
({ children, animated, className, color, value = 0, variant, ...rest }, ref) => {
|
|
36
|
+
const { stacked } = useContext(CProgressStackedContext)
|
|
37
|
+
|
|
35
38
|
return (
|
|
36
39
|
<div
|
|
37
40
|
className={classNames(
|
|
@@ -43,11 +46,7 @@ export const CProgressBar = forwardRef<HTMLDivElement, CProgressBarProps>(
|
|
|
43
46
|
},
|
|
44
47
|
className,
|
|
45
48
|
)}
|
|
46
|
-
|
|
47
|
-
style={{ width: `${value}%` }}
|
|
48
|
-
aria-valuenow={value}
|
|
49
|
-
aria-valuemin={0}
|
|
50
|
-
aria-valuemax={100}
|
|
49
|
+
{...(!stacked && { style: { width: `${value}%` } })}
|
|
51
50
|
{...rest}
|
|
52
51
|
ref={ref}
|
|
53
52
|
>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { createContext, forwardRef, HTMLAttributes } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import classNames from 'classnames'
|
|
4
|
+
|
|
5
|
+
export interface CProgressStackedProps extends HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/**
|
|
7
|
+
* A string of all className you want applied to the component.
|
|
8
|
+
*/
|
|
9
|
+
className?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CProgressStackedContextProps {
|
|
13
|
+
stacked?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const CProgressStackedContext = createContext({} as CProgressStackedContextProps)
|
|
17
|
+
|
|
18
|
+
export const CProgressStacked = forwardRef<HTMLDivElement, CProgressStackedProps>(
|
|
19
|
+
({ children, className, ...rest }, ref) => {
|
|
20
|
+
return (
|
|
21
|
+
<div className={classNames('progress-stacked', className)} ref={ref} {...rest}>
|
|
22
|
+
<CProgressStackedContext.Provider
|
|
23
|
+
value={{
|
|
24
|
+
stacked: true,
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</CProgressStackedContext.Provider>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
CProgressStacked.propTypes = {
|
|
35
|
+
children: PropTypes.node,
|
|
36
|
+
className: PropTypes.string,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
CProgressStacked.displayName = 'CProgressStacked'
|
|
@@ -3,13 +3,19 @@ import { createPortal } from 'react-dom'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
5
|
import { Transition } from 'react-transition-group'
|
|
6
|
-
import { createPopper, Instance, Placement } from '@popperjs/core'
|
|
7
6
|
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
7
|
+
import { usePopper } from '../../hooks'
|
|
8
|
+
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
|
+
import type { Placements, Triggers } from '../../types'
|
|
10
|
+
import { getRTLPlacement } from '../../utils'
|
|
11
11
|
|
|
12
12
|
export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'content'> {
|
|
13
|
+
/**
|
|
14
|
+
* Apply a CSS fade transition to the tooltip.
|
|
15
|
+
*
|
|
16
|
+
* @since 4.9.0-beta.2
|
|
17
|
+
*/
|
|
18
|
+
animation?: boolean
|
|
13
19
|
/**
|
|
14
20
|
* A string of all className you want applied to the component.
|
|
15
21
|
*/
|
|
@@ -18,6 +24,18 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
|
|
|
18
24
|
* Content node for your component.
|
|
19
25
|
*/
|
|
20
26
|
content: ReactNode | string
|
|
27
|
+
/**
|
|
28
|
+
* The delay for displaying and hiding the tooltip (in milliseconds). When a numerical value is provided, the delay applies to both the hide and show actions. The object structure for specifying the delay is as follows: delay: `{ 'show': 500, 'hide': 100 }`.
|
|
29
|
+
*
|
|
30
|
+
* @since 4.9.0-beta.2
|
|
31
|
+
*/
|
|
32
|
+
delay?: number | { show: number; hide: number }
|
|
33
|
+
/**
|
|
34
|
+
* Specify the desired order of fallback placements by providing a list of placements as an array. The placements should be prioritized based on preference.
|
|
35
|
+
*
|
|
36
|
+
* @since 4.9.0-beta.2
|
|
37
|
+
*/
|
|
38
|
+
fallbackPlacements?: Placements | Placements[]
|
|
21
39
|
/**
|
|
22
40
|
* Offset of the tooltip relative to its target.
|
|
23
41
|
*/
|
|
@@ -46,44 +64,59 @@ export interface CTooltipProps extends Omit<HTMLAttributes<HTMLDivElement>, 'con
|
|
|
46
64
|
visible?: boolean
|
|
47
65
|
}
|
|
48
66
|
|
|
49
|
-
const getPlacement = (placement: string, element: HTMLDivElement | null): Placement => {
|
|
50
|
-
switch (placement) {
|
|
51
|
-
case 'right': {
|
|
52
|
-
return isRTL(element) ? 'left' : 'right'
|
|
53
|
-
}
|
|
54
|
-
case 'left': {
|
|
55
|
-
return isRTL(element) ? 'right' : 'left'
|
|
56
|
-
}
|
|
57
|
-
default: {
|
|
58
|
-
return placement as Placement
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
67
|
export const CTooltip: FC<CTooltipProps> = ({
|
|
64
68
|
children,
|
|
69
|
+
animation = true,
|
|
65
70
|
className,
|
|
66
71
|
content,
|
|
72
|
+
delay = 0,
|
|
73
|
+
fallbackPlacements = ['top', 'right', 'bottom', 'left'],
|
|
67
74
|
offset = [0, 6],
|
|
68
75
|
onHide,
|
|
69
76
|
onShow,
|
|
70
77
|
placement = 'top',
|
|
71
|
-
trigger = 'hover',
|
|
78
|
+
trigger = ['hover', 'focus'],
|
|
72
79
|
visible,
|
|
73
80
|
...rest
|
|
74
81
|
}) => {
|
|
75
82
|
const tooltipRef = useRef(null)
|
|
76
83
|
const togglerRef = useRef(null)
|
|
77
|
-
const
|
|
84
|
+
const { initPopper, destroyPopper } = usePopper()
|
|
78
85
|
const [_visible, setVisible] = useState(visible)
|
|
79
86
|
|
|
87
|
+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
|
|
88
|
+
|
|
89
|
+
const popperConfig = {
|
|
90
|
+
modifiers: [
|
|
91
|
+
{
|
|
92
|
+
name: 'arrow',
|
|
93
|
+
options: {
|
|
94
|
+
element: '.tooltip-arrow',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'flip',
|
|
99
|
+
options: {
|
|
100
|
+
fallbackPlacements: fallbackPlacements,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'offset',
|
|
105
|
+
options: {
|
|
106
|
+
offset: offset,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
placement: getRTLPlacement(placement, togglerRef.current),
|
|
111
|
+
}
|
|
112
|
+
|
|
80
113
|
useEffect(() => {
|
|
81
114
|
setVisible(visible)
|
|
82
115
|
}, [visible])
|
|
83
116
|
|
|
84
117
|
useEffect(() => {
|
|
85
|
-
if (_visible) {
|
|
86
|
-
initPopper()
|
|
118
|
+
if (_visible && togglerRef.current && tooltipRef.current) {
|
|
119
|
+
initPopper(togglerRef.current, tooltipRef.current, popperConfig)
|
|
87
120
|
}
|
|
88
121
|
|
|
89
122
|
return () => {
|
|
@@ -91,28 +124,13 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
91
124
|
}
|
|
92
125
|
}, [_visible])
|
|
93
126
|
|
|
94
|
-
const
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{
|
|
99
|
-
name: 'offset',
|
|
100
|
-
options: {
|
|
101
|
-
offset: offset,
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
],
|
|
105
|
-
placement: getPlacement(placement, togglerRef.current),
|
|
106
|
-
})
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const destroyPopper = () => {
|
|
111
|
-
if (popper.current) {
|
|
112
|
-
popper.current.destroy()
|
|
127
|
+
const toggleVisible = (visible: boolean) => {
|
|
128
|
+
if (visible) {
|
|
129
|
+
setTimeout(() => setVisible(true), _delay.show)
|
|
130
|
+
return
|
|
113
131
|
}
|
|
114
132
|
|
|
115
|
-
|
|
133
|
+
setTimeout(() => setVisible(false), _delay.hide)
|
|
116
134
|
}
|
|
117
135
|
|
|
118
136
|
return (
|
|
@@ -120,15 +138,15 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
120
138
|
{React.cloneElement(children as React.ReactElement<any>, {
|
|
121
139
|
ref: togglerRef,
|
|
122
140
|
...((trigger === 'click' || trigger.includes('click')) && {
|
|
123
|
-
onClick: () =>
|
|
141
|
+
onClick: () => toggleVisible(!_visible),
|
|
124
142
|
}),
|
|
125
143
|
...((trigger === 'focus' || trigger.includes('focus')) && {
|
|
126
|
-
onFocus: () =>
|
|
127
|
-
onBlur: () =>
|
|
144
|
+
onFocus: () => toggleVisible(true),
|
|
145
|
+
onBlur: () => toggleVisible(false),
|
|
128
146
|
}),
|
|
129
147
|
...((trigger === 'hover' || trigger.includes('hover')) && {
|
|
130
|
-
onMouseEnter: () =>
|
|
131
|
-
onMouseLeave: () =>
|
|
148
|
+
onMouseEnter: () => toggleVisible(true),
|
|
149
|
+
onMouseLeave: () => toggleVisible(false),
|
|
132
150
|
}),
|
|
133
151
|
})}
|
|
134
152
|
{typeof window !== 'undefined' &&
|
|
@@ -148,11 +166,9 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
148
166
|
<div
|
|
149
167
|
className={classNames(
|
|
150
168
|
'tooltip',
|
|
151
|
-
|
|
152
|
-
.replace('left', 'start')
|
|
153
|
-
.replace('right', 'end')}`,
|
|
154
|
-
'fade',
|
|
169
|
+
'bs-tooltip-auto',
|
|
155
170
|
{
|
|
171
|
+
fade: animation,
|
|
156
172
|
show: state === 'entered',
|
|
157
173
|
},
|
|
158
174
|
className,
|
|
@@ -161,7 +177,7 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
161
177
|
role="tooltip"
|
|
162
178
|
{...rest}
|
|
163
179
|
>
|
|
164
|
-
<div
|
|
180
|
+
<div className="tooltip-arrow"></div>
|
|
165
181
|
<div className="tooltip-inner">{content}</div>
|
|
166
182
|
</div>
|
|
167
183
|
)}
|
|
@@ -173,8 +189,17 @@ export const CTooltip: FC<CTooltipProps> = ({
|
|
|
173
189
|
}
|
|
174
190
|
|
|
175
191
|
CTooltip.propTypes = {
|
|
192
|
+
animation: PropTypes.bool,
|
|
176
193
|
children: PropTypes.node,
|
|
177
194
|
content: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
195
|
+
delay: PropTypes.oneOfType([
|
|
196
|
+
PropTypes.number,
|
|
197
|
+
PropTypes.shape({
|
|
198
|
+
show: PropTypes.number.isRequired,
|
|
199
|
+
hide: PropTypes.number.isRequired,
|
|
200
|
+
}),
|
|
201
|
+
]),
|
|
202
|
+
fallbackPlacements: fallbackPlacementsPropType,
|
|
178
203
|
offset: PropTypes.any, // TODO: find good proptype
|
|
179
204
|
onHide: PropTypes.func,
|
|
180
205
|
onShow: PropTypes.func,
|
package/src/hooks/index.ts
CHANGED