@coreui/react 5.0.0-alpha.0 → 5.0.0-alpha.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/avatar/CAvatar.d.ts +1 -1
- package/dist/components/badge/CBadge.d.ts +1 -1
- package/dist/components/card/CCard.d.ts +1 -1
- package/dist/components/close-button/CCloseButton.d.ts +6 -0
- package/dist/components/dropdown/CDropdown.d.ts +1 -0
- package/dist/components/modal/CModal.d.ts +6 -0
- package/dist/components/nav/CNav.d.ts +1 -1
- package/dist/components/navbar/CNavbar.d.ts +1 -1
- package/dist/components/offcanvas/COffcanvas.d.ts +4 -0
- package/dist/index.es.js +177 -81
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +177 -81
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +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 +2 -2
- package/src/components/avatar/CAvatar.tsx +1 -1
- package/src/components/badge/CBadge.tsx +1 -1
- package/src/components/button/CButton.tsx +1 -1
- package/src/components/button/__tests__/__snapshots__/CButton.spec.tsx.snap +0 -1
- package/src/components/card/CCard.tsx +1 -1
- package/src/components/carousel/CCarousel.tsx +9 -5
- package/src/components/carousel/__tests__/__snapshots__/CCarousel.spec.tsx.snap +9 -5
- package/src/components/close-button/CCloseButton.tsx +9 -1
- package/src/components/dropdown/CDropdown.tsx +43 -1
- package/src/components/dropdown/CDropdownMenu.tsx +1 -1
- package/src/components/dropdown/CDropdownToggle.tsx +3 -12
- package/src/components/modal/CModal.tsx +25 -9
- package/src/components/nav/CNav.tsx +2 -2
- package/src/components/nav/CNavGroup.tsx +9 -2
- package/src/components/nav/__tests__/__snapshots__/CNav.spec.tsx.snap +5 -4
- package/src/components/navbar/CNavbar.tsx +2 -2
- package/src/components/navbar/__tests__/CNavbar.spec.tsx +1 -1
- package/src/components/navbar/__tests__/__snapshots__/CNavbar.spec.tsx.snap +2 -1
- package/src/components/offcanvas/COffcanvas.tsx +8 -1
- package/src/components/popover/CPopover.tsx +2 -2
- package/src/components/progress/__tests__/__snapshots__/CProgress.spec.tsx.snap +10 -5
- package/src/components/progress/__tests__/__snapshots__/CProgressBar.spec.tsx.snap +0 -8
- package/src/components/sidebar/CSidebar.tsx +1 -1
- package/src/components/tooltip/CTooltip.tsx +2 -2
- package/src/components/widgets/CWidgetStatsA.tsx +1 -1
- package/src/components/widgets/CWidgetStatsB.tsx +2 -2
- package/src/components/widgets/CWidgetStatsC.tsx +4 -12
- package/src/components/widgets/CWidgetStatsD.tsx +1 -1
- package/src/components/widgets/CWidgetStatsE.tsx +1 -1
- package/src/components/widgets/CWidgetStatsF.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsA.spec.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsB.spec.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsC.spec.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsD.spec.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsE.spec.tsx +1 -1
- package/src/components/widgets/__tests__/CWidgetStatsF.spec.tsx +1 -1
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsA.spec.tsx.snap +1 -1
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsB.spec.tsx.snap +12 -7
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsC.spec.tsx.snap +14 -9
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsD.spec.tsx.snap +2 -2
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsE.spec.tsx.snap +1 -1
- package/src/components/widgets/__tests__/__snapshots__/CWidgetStatsF.spec.tsx.snap +2 -2
- package/src/hooks/usePopper.ts +10 -2
- package/src/types.ts +14 -7
- package/src/utils/executeAfterTransition.ts +46 -0
- package/src/utils/getTransitionDurationFromElement.ts +24 -0
- package/src/utils/index.ts +9 -1
package/dist/types.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export type Breakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
|
|
2
2
|
export type Colors = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string;
|
|
3
3
|
export type Placements = 'auto' | 'auto-start' | 'auto-end' | 'top-end' | 'top' | 'top-start' | 'bottom-end' | 'bottom' | 'bottom-start' | 'right-start' | 'right' | 'right-end' | 'left-start' | 'left' | 'left-end' | undefined;
|
|
4
4
|
export type Shapes = 'rounded' | 'rounded-top' | 'rounded-end' | 'rounded-bottom' | 'rounded-start' | 'rounded-circle' | 'rounded-pill' | 'rounded-0' | 'rounded-1' | 'rounded-2' | 'rounded-3' | string;
|
|
5
|
-
export type TextColors = Colors | '
|
|
5
|
+
export type TextColors = Colors | 'primary-emphasis' | 'secondary-emphasis' | 'success-emphasis' | 'danger-emphasis' | 'warning-emphasis' | 'info-emphasis' | 'light-emphasis' | 'body' | 'body-emphasis' | 'body-secondary' | 'body-tertiary' | 'black' | 'black-50' | 'white' | 'white-50' | string;
|
|
6
6
|
export type Triggers = 'hover' | 'focus' | 'click';
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
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
|
-
export { getRTLPlacement, isInViewport, isRTL };
|
|
6
|
+
export { executeAfterTransition, getRTLPlacement, getTransitionDurationFromElement, isInViewport, isRTL, };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coreui/react",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.2",
|
|
4
4
|
"description": "UI Components Library for React.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"typescript": "^5.1.6"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@coreui/coreui": "^5.0.0-alpha.
|
|
63
|
+
"@coreui/coreui": "^5.0.0-alpha.2",
|
|
64
64
|
"react": ">=17",
|
|
65
65
|
"react-dom": ">=17"
|
|
66
66
|
}
|
|
@@ -39,7 +39,7 @@ export interface CAvatarProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
39
39
|
/**
|
|
40
40
|
* Sets the text color of the component to one of CoreUI’s themed colors.
|
|
41
41
|
*
|
|
42
|
-
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | '
|
|
42
|
+
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'primary-emphasis' | 'secondary-emphasis' | 'success-emphasis' | 'danger-emphasis' | 'warning-emphasis' | 'info-emphasis' | 'light-emphasis' | 'body' | 'body-emphasis' | 'body-secondary' | 'body-tertiary' | 'black' | 'black-50' | 'white' | 'white-50' | string
|
|
43
43
|
*/
|
|
44
44
|
textColor?: TextColors
|
|
45
45
|
}
|
|
@@ -37,7 +37,7 @@ export interface CBadgeProps extends HTMLAttributes<HTMLDivElement | HTMLSpanEle
|
|
|
37
37
|
/**
|
|
38
38
|
* Sets the text color of the component to one of CoreUI’s themed colors.
|
|
39
39
|
*
|
|
40
|
-
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | '
|
|
40
|
+
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'primary-emphasis' | 'secondary-emphasis' | 'success-emphasis' | 'danger-emphasis' | 'warning-emphasis' | 'info-emphasis' | 'light-emphasis' | 'body' | 'body-emphasis' | 'body-secondary' | 'body-tertiary' | 'black' | 'black-50' | 'white' | 'white-50' | string
|
|
41
41
|
*/
|
|
42
42
|
textColor?: TextColors
|
|
43
43
|
}
|
|
@@ -77,7 +77,7 @@ export const CButton = forwardRef<HTMLButtonElement | HTMLAnchorElement, CButton
|
|
|
77
77
|
return (
|
|
78
78
|
<CLink
|
|
79
79
|
component={rest.href ? 'a' : component}
|
|
80
|
-
|
|
80
|
+
{...(!rest.href && { type: type })}
|
|
81
81
|
className={classNames(
|
|
82
82
|
'btn',
|
|
83
83
|
variant ? `btn-${variant}-${color}` : `btn-${color}`,
|
|
@@ -19,7 +19,7 @@ export interface CCardProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
/**
|
|
20
20
|
* Sets the text color context of the component to one of CoreUI’s themed colors.
|
|
21
21
|
*
|
|
22
|
-
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | '
|
|
22
|
+
* @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'primary-emphasis' | 'secondary-emphasis' | 'success-emphasis' | 'danger-emphasis' | 'warning-emphasis' | 'info-emphasis' | 'light-emphasis' | 'body' | 'body-emphasis' | 'body-secondary' | 'body-tertiary' | 'black' | 'black-50' | 'white' | 'white-50' | string
|
|
23
23
|
*/
|
|
24
24
|
textColor?: string
|
|
25
25
|
}
|
|
@@ -226,11 +226,11 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
226
226
|
className={classNames(
|
|
227
227
|
'carousel slide',
|
|
228
228
|
{
|
|
229
|
-
'carousel-dark': dark,
|
|
230
229
|
'carousel-fade': transition === 'crossfade',
|
|
231
230
|
},
|
|
232
231
|
className,
|
|
233
232
|
)}
|
|
233
|
+
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
234
234
|
onMouseEnter={_pause}
|
|
235
235
|
onMouseLeave={cycle}
|
|
236
236
|
{...(touch && { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove })}
|
|
@@ -244,20 +244,24 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
244
244
|
}}
|
|
245
245
|
>
|
|
246
246
|
{indicators && (
|
|
247
|
-
<
|
|
247
|
+
<div className="carousel-indicators">
|
|
248
248
|
{Array.from({ length: itemsNumber }, (_, i) => i).map((index) => {
|
|
249
249
|
return (
|
|
250
|
-
<
|
|
250
|
+
<button
|
|
251
251
|
key={`indicator${index}`}
|
|
252
252
|
onClick={() => {
|
|
253
253
|
!animating && handleIndicatorClick(index)
|
|
254
254
|
}}
|
|
255
|
-
className={
|
|
255
|
+
className={classNames({
|
|
256
|
+
active: active === index
|
|
257
|
+
})}
|
|
256
258
|
data-coreui-target=""
|
|
259
|
+
{...(active === index && { 'aria-current': true })}
|
|
260
|
+
aria-label={`Slide ${index + 1}`}
|
|
257
261
|
/>
|
|
258
262
|
)
|
|
259
263
|
})}
|
|
260
|
-
</
|
|
264
|
+
</div>
|
|
261
265
|
)}
|
|
262
266
|
<div className="carousel-inner">
|
|
263
267
|
{Children.map(children, (child, index) => {
|
|
@@ -5,22 +5,26 @@ exports[`loads and displays CCarousel component 1`] = `
|
|
|
5
5
|
<div
|
|
6
6
|
class="carousel slide"
|
|
7
7
|
>
|
|
8
|
-
<
|
|
8
|
+
<div
|
|
9
9
|
class="carousel-indicators"
|
|
10
10
|
>
|
|
11
|
-
<
|
|
11
|
+
<button
|
|
12
|
+
aria-current="true"
|
|
13
|
+
aria-label="Slide 1"
|
|
12
14
|
class="active"
|
|
13
15
|
data-coreui-target=""
|
|
14
16
|
/>
|
|
15
|
-
<
|
|
17
|
+
<button
|
|
18
|
+
aria-label="Slide 2"
|
|
16
19
|
class=""
|
|
17
20
|
data-coreui-target=""
|
|
18
21
|
/>
|
|
19
|
-
<
|
|
22
|
+
<button
|
|
23
|
+
aria-label="Slide 3"
|
|
20
24
|
class=""
|
|
21
25
|
data-coreui-target=""
|
|
22
26
|
/>
|
|
23
|
-
</
|
|
27
|
+
</div>
|
|
24
28
|
<div
|
|
25
29
|
class="carousel-inner"
|
|
26
30
|
>
|
|
@@ -7,18 +7,24 @@ export interface CCloseButtonProps extends HTMLAttributes<HTMLButtonElement> {
|
|
|
7
7
|
* A string of all className you want applied to the base component.
|
|
8
8
|
*/
|
|
9
9
|
className?: string
|
|
10
|
+
/**
|
|
11
|
+
* Invert the default color.
|
|
12
|
+
*/
|
|
13
|
+
dark?: boolean
|
|
10
14
|
/**
|
|
11
15
|
* Toggle the disabled state for the component.
|
|
12
16
|
*/
|
|
13
17
|
disabled?: boolean
|
|
14
18
|
/**
|
|
15
19
|
* Change the default color to white.
|
|
20
|
+
*
|
|
21
|
+
* @deprecated 5.0.0
|
|
16
22
|
*/
|
|
17
23
|
white?: boolean
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
|
|
21
|
-
({ className, disabled, white, ...rest }, ref) => {
|
|
27
|
+
({ className, dark, disabled, white, ...rest }, ref) => {
|
|
22
28
|
return (
|
|
23
29
|
<button
|
|
24
30
|
type="button"
|
|
@@ -33,6 +39,7 @@ export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
|
|
|
33
39
|
)}
|
|
34
40
|
aria-label="Close"
|
|
35
41
|
disabled={disabled}
|
|
42
|
+
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
36
43
|
{...rest}
|
|
37
44
|
ref={ref}
|
|
38
45
|
/>
|
|
@@ -42,6 +49,7 @@ export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
|
|
|
42
49
|
|
|
43
50
|
CCloseButton.propTypes = {
|
|
44
51
|
className: PropTypes.string,
|
|
52
|
+
dark: PropTypes.bool,
|
|
45
53
|
disabled: PropTypes.bool,
|
|
46
54
|
white: PropTypes.bool,
|
|
47
55
|
}
|
|
@@ -107,6 +107,28 @@ interface ContextProps extends CDropdownProps {
|
|
|
107
107
|
portal: boolean
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
export const getNextActiveElement = (
|
|
111
|
+
list: HTMLElement[],
|
|
112
|
+
activeElement: HTMLElement,
|
|
113
|
+
shouldGetNext: boolean,
|
|
114
|
+
isCycleAllowed: boolean,
|
|
115
|
+
) => {
|
|
116
|
+
const listLength = list.length
|
|
117
|
+
let index = list.indexOf(activeElement)
|
|
118
|
+
|
|
119
|
+
if (index === -1) {
|
|
120
|
+
return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
index += shouldGetNext ? 1 : -1
|
|
124
|
+
|
|
125
|
+
if (isCycleAllowed) {
|
|
126
|
+
index = (index + listLength) % listLength
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return list[Math.max(0, Math.min(index, listLength - 1))]
|
|
130
|
+
}
|
|
131
|
+
|
|
110
132
|
const getPlacement = (
|
|
111
133
|
placement: Placements,
|
|
112
134
|
direction: CDropdownProps['direction'],
|
|
@@ -207,9 +229,12 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
207
229
|
|
|
208
230
|
useEffect(() => {
|
|
209
231
|
if (_visible && dropdownToggleRef.current && dropdownMenuRef.current) {
|
|
232
|
+
dropdownToggleRef.current.focus()
|
|
210
233
|
popper && initPopper(dropdownToggleRef.current, dropdownMenuRef.current, popperConfig)
|
|
211
234
|
window.addEventListener('mouseup', handleMouseUp)
|
|
212
235
|
window.addEventListener('keyup', handleKeyup)
|
|
236
|
+
dropdownToggleRef.current.addEventListener('keydown', handleKeydown)
|
|
237
|
+
dropdownMenuRef.current.addEventListener('keydown', handleKeydown)
|
|
213
238
|
onShow && onShow()
|
|
214
239
|
}
|
|
215
240
|
|
|
@@ -217,10 +242,28 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
217
242
|
popper && destroyPopper()
|
|
218
243
|
window.removeEventListener('mouseup', handleMouseUp)
|
|
219
244
|
window.removeEventListener('keyup', handleKeyup)
|
|
245
|
+
dropdownToggleRef.current &&
|
|
246
|
+
dropdownToggleRef.current.removeEventListener('keydown', handleKeydown)
|
|
247
|
+
dropdownMenuRef.current &&
|
|
248
|
+
dropdownMenuRef.current.removeEventListener('keydown', handleKeydown)
|
|
220
249
|
onHide && onHide()
|
|
221
250
|
}
|
|
222
251
|
}, [_visible])
|
|
223
252
|
|
|
253
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
254
|
+
if (_visible && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
255
|
+
const target = event.target as HTMLElement
|
|
256
|
+
event.preventDefault()
|
|
257
|
+
const items = [].concat(
|
|
258
|
+
...Element.prototype.querySelectorAll.call(
|
|
259
|
+
dropdownMenuRef.current,
|
|
260
|
+
'.dropdown-item:not(.disabled):not(:disabled)',
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
getNextActiveElement(items, target, event.key === 'ArrowDown', true).focus()
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
224
267
|
const handleKeyup = (event: KeyboardEvent) => {
|
|
225
268
|
if (autoClose === false) {
|
|
226
269
|
return
|
|
@@ -263,7 +306,6 @@ export const CDropdown = forwardRef<HTMLDivElement | HTMLLIElement, CDropdownPro
|
|
|
263
306
|
'dropup dropup-center': direction === 'dropup-center',
|
|
264
307
|
[`${direction}`]:
|
|
265
308
|
direction && direction !== 'center' && direction !== 'dropup-center',
|
|
266
|
-
show: _visible,
|
|
267
309
|
},
|
|
268
310
|
className,
|
|
269
311
|
)}
|
|
@@ -46,7 +46,6 @@ export const CDropdownMenu = forwardRef<HTMLDivElement | HTMLUListElement, CDrop
|
|
|
46
46
|
className={classNames(
|
|
47
47
|
'dropdown-menu',
|
|
48
48
|
{
|
|
49
|
-
'dropdown-menu-dark': dark,
|
|
50
49
|
show: visible,
|
|
51
50
|
},
|
|
52
51
|
alignment && alignmentClassNames(alignment),
|
|
@@ -56,6 +55,7 @@ export const CDropdownMenu = forwardRef<HTMLDivElement | HTMLUListElement, CDrop
|
|
|
56
55
|
role="menu"
|
|
57
56
|
aria-hidden={!visible}
|
|
58
57
|
{...(!popper && { 'data-coreui-popper': 'static' })}
|
|
58
|
+
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
59
59
|
{...rest}
|
|
60
60
|
>
|
|
61
61
|
{Component === 'ul'
|
|
@@ -39,7 +39,7 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
|
39
39
|
trigger = 'click',
|
|
40
40
|
...rest
|
|
41
41
|
}) => {
|
|
42
|
-
const { dropdownToggleRef,
|
|
42
|
+
const { dropdownToggleRef, visible, setVisible } = useContext(CDropdownContext)
|
|
43
43
|
|
|
44
44
|
const triggers = {
|
|
45
45
|
...((trigger === 'click' || trigger.includes('click')) && {
|
|
@@ -59,7 +59,7 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
|
59
59
|
{
|
|
60
60
|
'dropdown-toggle': caret,
|
|
61
61
|
'dropdown-toggle-split': split,
|
|
62
|
-
|
|
62
|
+
show: visible,
|
|
63
63
|
},
|
|
64
64
|
className,
|
|
65
65
|
),
|
|
@@ -67,7 +67,6 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
|
67
67
|
...(!rest.disabled && { ...triggers }),
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// We use any because Toggler can be `a` as well as `button`.
|
|
71
70
|
const Toggler = () => {
|
|
72
71
|
if (custom && React.isValidElement(children)) {
|
|
73
72
|
return (
|
|
@@ -81,16 +80,8 @@ export const CDropdownToggle: FC<CDropdownToggleProps> = ({
|
|
|
81
80
|
)
|
|
82
81
|
}
|
|
83
82
|
|
|
84
|
-
if (variant === 'nav-item') {
|
|
85
|
-
return (
|
|
86
|
-
<a href="#" {...togglerProps} ref={dropdownToggleRef}>
|
|
87
|
-
{children}
|
|
88
|
-
</a>
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
83
|
return (
|
|
93
|
-
<CButton
|
|
84
|
+
<CButton {...togglerProps} tabIndex={0} {...rest} ref={dropdownToggleRef}>
|
|
94
85
|
{children}
|
|
95
86
|
{split && <span className="visually-hidden">Toggle Dropdown</span>}
|
|
96
87
|
</CButton>
|
|
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types'
|
|
|
11
11
|
import classNames from 'classnames'
|
|
12
12
|
import { Transition } from 'react-transition-group'
|
|
13
13
|
|
|
14
|
-
import { CBackdrop } from '../backdrop
|
|
14
|
+
import { CBackdrop } from '../backdrop'
|
|
15
15
|
import { CConditionalPortal } from '../conditional-portal'
|
|
16
16
|
import { CModalContent } from './CModalContent'
|
|
17
17
|
import { CModalDialog } from './CModalDialog'
|
|
@@ -35,6 +35,12 @@ export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
35
35
|
* @ignore
|
|
36
36
|
*/
|
|
37
37
|
duration?: number
|
|
38
|
+
/**
|
|
39
|
+
* Puts the focus on the modal when shown.
|
|
40
|
+
*
|
|
41
|
+
* @since v4.10.0
|
|
42
|
+
*/
|
|
43
|
+
focus?: boolean
|
|
38
44
|
/**
|
|
39
45
|
* Set modal to covers the entire user viewport.
|
|
40
46
|
*/
|
|
@@ -96,6 +102,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
96
102
|
backdrop = true,
|
|
97
103
|
className,
|
|
98
104
|
duration = 150,
|
|
105
|
+
focus = true,
|
|
99
106
|
fullscreen,
|
|
100
107
|
keyboard = true,
|
|
101
108
|
onClose,
|
|
@@ -111,6 +118,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
111
118
|
},
|
|
112
119
|
ref,
|
|
113
120
|
) => {
|
|
121
|
+
const activeElementRef = useRef<HTMLElement | null>(null)
|
|
114
122
|
const modalRef = useRef<HTMLDivElement>(null)
|
|
115
123
|
const modalContentRef = useRef<HTMLDivElement>(null)
|
|
116
124
|
const forkedRef = useForkedRef(ref, modalRef)
|
|
@@ -128,11 +136,16 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
128
136
|
}, [visible])
|
|
129
137
|
|
|
130
138
|
useEffect(() => {
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
if (_visible) {
|
|
140
|
+
activeElementRef.current = document.activeElement as HTMLElement | null
|
|
141
|
+
document.addEventListener('mouseup', handleClickOutside)
|
|
142
|
+
document.addEventListener('keydown', handleKeyDown)
|
|
143
|
+
} else {
|
|
144
|
+
activeElementRef.current?.focus()
|
|
145
|
+
}
|
|
133
146
|
|
|
134
147
|
return () => {
|
|
135
|
-
document.removeEventListener('
|
|
148
|
+
document.removeEventListener('mouseup', handleClickOutside)
|
|
136
149
|
document.removeEventListener('keydown', handleKeyDown)
|
|
137
150
|
}
|
|
138
151
|
}, [_visible])
|
|
@@ -143,6 +156,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
143
156
|
}
|
|
144
157
|
|
|
145
158
|
setVisible(false)
|
|
159
|
+
|
|
146
160
|
return onClose && onClose()
|
|
147
161
|
}
|
|
148
162
|
|
|
@@ -163,7 +177,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
163
177
|
|
|
164
178
|
setTimeout(
|
|
165
179
|
() => {
|
|
166
|
-
modalRef.current?.focus()
|
|
180
|
+
focus && modalRef.current?.focus()
|
|
167
181
|
},
|
|
168
182
|
transition ? duration : 0,
|
|
169
183
|
)
|
|
@@ -225,10 +239,13 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
225
239
|
className,
|
|
226
240
|
)}
|
|
227
241
|
tabIndex={-1}
|
|
228
|
-
|
|
242
|
+
{...(_visible
|
|
243
|
+
? { 'aria-modal': true, role: 'dialog' }
|
|
244
|
+
: { 'aria-hidden': 'true' })}
|
|
229
245
|
style={{
|
|
230
246
|
...(state !== 'exited' && { display: 'block' }),
|
|
231
247
|
}}
|
|
248
|
+
{...rest}
|
|
232
249
|
ref={forkedRef}
|
|
233
250
|
>
|
|
234
251
|
<CModalDialog
|
|
@@ -237,9 +254,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
|
|
|
237
254
|
scrollable={scrollable}
|
|
238
255
|
size={size}
|
|
239
256
|
>
|
|
240
|
-
<CModalContent
|
|
241
|
-
{children}
|
|
242
|
-
</CModalContent>
|
|
257
|
+
<CModalContent ref={modalContentRef}>{children}</CModalContent>
|
|
243
258
|
</CModalDialog>
|
|
244
259
|
</div>
|
|
245
260
|
</CModalContext.Provider>
|
|
@@ -262,6 +277,7 @@ CModal.propTypes = {
|
|
|
262
277
|
children: PropTypes.node,
|
|
263
278
|
className: PropTypes.string,
|
|
264
279
|
duration: PropTypes.number,
|
|
280
|
+
focus: PropTypes.bool,
|
|
265
281
|
fullscreen: PropTypes.oneOfType([
|
|
266
282
|
PropTypes.bool,
|
|
267
283
|
PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']),
|
|
@@ -19,7 +19,7 @@ export interface CNavProps
|
|
|
19
19
|
/**
|
|
20
20
|
* Set the nav variant to tabs or pills.
|
|
21
21
|
*/
|
|
22
|
-
variant?: 'tabs' | '
|
|
22
|
+
variant?: 'pills' | 'tabs' | 'underline'
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export const CNav = forwardRef<HTMLDivElement | HTMLUListElement | HTMLOListElement, CNavProps>(
|
|
@@ -49,7 +49,7 @@ CNav.propTypes = {
|
|
|
49
49
|
className: PropTypes.string,
|
|
50
50
|
component: PropTypes.elementType,
|
|
51
51
|
layout: PropTypes.oneOf(['fill', 'justified']),
|
|
52
|
-
variant: PropTypes.oneOf(['tabs', '
|
|
52
|
+
variant: PropTypes.oneOf(['pills', 'tabs', 'underline']),
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
CNav.displayName = 'CNav'
|
|
@@ -36,6 +36,13 @@ export interface CNavGroupProps {
|
|
|
36
36
|
idx?: string
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const isInVisibleGroup = (el1: string, el2: string) => {
|
|
40
|
+
const array1 = el1.toString().split('.')
|
|
41
|
+
const array2 = el2.toString().split('.')
|
|
42
|
+
|
|
43
|
+
return array2.every((item, index) => item === array1[index])
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
|
|
40
47
|
({ children, className, compact, idx, toggler, visible, ...rest }, ref) => {
|
|
41
48
|
const [height, setHeight] = useState<number | string>()
|
|
@@ -45,12 +52,12 @@ export const CNavGroup = forwardRef<HTMLLIElement, CNavGroupProps>(
|
|
|
45
52
|
|
|
46
53
|
const [_visible, setVisible] = useState(
|
|
47
54
|
Boolean(
|
|
48
|
-
visible || (idx && visibleGroup && visibleGroup
|
|
55
|
+
visible || (idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)),
|
|
49
56
|
),
|
|
50
57
|
)
|
|
51
58
|
|
|
52
59
|
useEffect(() => {
|
|
53
|
-
setVisible(Boolean(idx && visibleGroup && visibleGroup
|
|
60
|
+
setVisible(Boolean(idx && visibleGroup && isInVisibleGroup(visibleGroup, idx)))
|
|
54
61
|
}, [visibleGroup])
|
|
55
62
|
|
|
56
63
|
const handleTogglerOnCLick = (event: React.MouseEvent<HTMLElement>) => {
|
|
@@ -41,13 +41,14 @@ exports[`CNav example 1`] = `
|
|
|
41
41
|
<li
|
|
42
42
|
class="nav-item dropdown"
|
|
43
43
|
>
|
|
44
|
-
<
|
|
44
|
+
<button
|
|
45
45
|
aria-expanded="false"
|
|
46
|
-
class="dropdown-toggle
|
|
47
|
-
|
|
46
|
+
class="btn btn-primary dropdown-toggle"
|
|
47
|
+
tabindex="0"
|
|
48
|
+
type="button"
|
|
48
49
|
>
|
|
49
50
|
A
|
|
50
|
-
</
|
|
51
|
+
</button>
|
|
51
52
|
<ul
|
|
52
53
|
aria-hidden="true"
|
|
53
54
|
class="dropdown-menu"
|
|
@@ -17,7 +17,7 @@ export interface CNavbarProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
17
|
*/
|
|
18
18
|
color?: Colors
|
|
19
19
|
/**
|
|
20
|
-
* Sets if the color of text should be colored for a light or dark
|
|
20
|
+
* Sets if the color of text should be colored for a light or dark background.
|
|
21
21
|
*/
|
|
22
22
|
colorScheme?: 'dark' | 'light'
|
|
23
23
|
/**
|
|
@@ -59,12 +59,12 @@ export const CNavbar = forwardRef<HTMLDivElement, CNavbarProps>(
|
|
|
59
59
|
'navbar',
|
|
60
60
|
{
|
|
61
61
|
[`bg-${color}`]: color,
|
|
62
|
-
[`navbar-${colorScheme}`]: colorScheme,
|
|
63
62
|
[typeof expand === 'boolean' ? 'navbar-expand' : `navbar-expand-${expand}`]: expand,
|
|
64
63
|
},
|
|
65
64
|
placement,
|
|
66
65
|
className,
|
|
67
66
|
)}
|
|
67
|
+
{...(colorScheme && { 'data-coreui-theme': colorScheme })}
|
|
68
68
|
{...rest}
|
|
69
69
|
ref={ref}
|
|
70
70
|
>
|
|
@@ -26,9 +26,9 @@ test('CNavbar customize', async () => {
|
|
|
26
26
|
expect(container.firstChild).toHaveClass('bazinga')
|
|
27
27
|
expect(container.firstChild).toHaveClass('navbar')
|
|
28
28
|
expect(container.firstChild).toHaveClass('bg-warning')
|
|
29
|
-
expect(container.firstChild).toHaveClass('navbar-dark')
|
|
30
29
|
expect(container.firstChild).toHaveClass('navbar-expand-lg')
|
|
31
30
|
expect(container.firstChild).toHaveClass('fixed-bottom')
|
|
31
|
+
expect(container.firstChild).toHaveAttribute('data-coreui-theme', 'dark')
|
|
32
32
|
const arrLength = container.getElementsByClassName('container-xl').length
|
|
33
33
|
expect(arrLength).toBe(1)
|
|
34
34
|
})
|
|
@@ -17,7 +17,8 @@ exports[`CNavbar customize - container and expand are boolean 1`] = `
|
|
|
17
17
|
exports[`CNavbar customize 1`] = `
|
|
18
18
|
<div>
|
|
19
19
|
<h3
|
|
20
|
-
class="navbar bg-warning navbar-
|
|
20
|
+
class="navbar bg-warning navbar-expand-lg fixed-bottom bazinga"
|
|
21
|
+
data-coreui-theme="dark"
|
|
21
22
|
>
|
|
22
23
|
<div
|
|
23
24
|
class="container-xl"
|
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { Transition } from 'react-transition-group'
|
|
5
5
|
|
|
6
|
-
import { CBackdrop } from '../backdrop
|
|
6
|
+
import { CBackdrop } from '../backdrop'
|
|
7
7
|
import { CConditionalPortal } from '../conditional-portal'
|
|
8
8
|
|
|
9
9
|
import { useForkedRef } from '../../hooks'
|
|
@@ -17,6 +17,10 @@ export interface COffcanvasProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
17
17
|
* A string of all className you want applied to the base component.
|
|
18
18
|
*/
|
|
19
19
|
className?: string
|
|
20
|
+
/**
|
|
21
|
+
* Sets a darker color scheme.
|
|
22
|
+
*/
|
|
23
|
+
dark?: boolean
|
|
20
24
|
/**
|
|
21
25
|
* Closes the offcanvas when escape key is pressed.
|
|
22
26
|
*/
|
|
@@ -59,6 +63,7 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
59
63
|
children,
|
|
60
64
|
backdrop = true,
|
|
61
65
|
className,
|
|
66
|
+
dark,
|
|
62
67
|
keyboard = true,
|
|
63
68
|
onHide,
|
|
64
69
|
onShow,
|
|
@@ -135,6 +140,7 @@ export const COffcanvas = forwardRef<HTMLDivElement, COffcanvasProps>(
|
|
|
135
140
|
role="dialog"
|
|
136
141
|
tabIndex={-1}
|
|
137
142
|
onKeyDown={handleKeyDown}
|
|
143
|
+
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
138
144
|
{...rest}
|
|
139
145
|
ref={forkedRef}
|
|
140
146
|
>
|
|
@@ -161,6 +167,7 @@ COffcanvas.propTypes = {
|
|
|
161
167
|
backdrop: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf<'static'>(['static'])]),
|
|
162
168
|
children: PropTypes.node,
|
|
163
169
|
className: PropTypes.string,
|
|
170
|
+
dark: PropTypes.bool,
|
|
164
171
|
keyboard: PropTypes.bool,
|
|
165
172
|
onHide: PropTypes.func,
|
|
166
173
|
onShow: PropTypes.func,
|
|
@@ -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
|
>
|