@coreui/react-pro 5.25.0 → 5.26.0
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/dist/cjs/components/card/CCardImage.js.map +1 -1
- package/dist/cjs/components/carousel/CCarousel.js +44 -33
- package/dist/cjs/components/carousel/CCarousel.js.map +1 -1
- package/dist/cjs/components/carousel/CCarouselItem.js +19 -28
- package/dist/cjs/components/carousel/CCarouselItem.js.map +1 -1
- package/dist/cjs/components/chip/CChip.d.ts +12 -0
- package/dist/cjs/components/chip/CChip.js +16 -63
- package/dist/cjs/components/chip/CChip.js.map +1 -1
- package/dist/cjs/components/chip/const.d.ts +1 -0
- package/dist/cjs/components/chip/const.js +8 -0
- package/dist/cjs/components/chip/const.js.map +1 -0
- package/dist/cjs/components/chip-set/CChipSet.d.ts +73 -0
- package/dist/cjs/components/chip-set/CChipSet.js +66 -0
- package/dist/cjs/components/chip-set/CChipSet.js.map +1 -0
- package/dist/cjs/components/chip-set/index.d.ts +2 -0
- package/dist/cjs/components/chip-set/useChipSet.d.ts +48 -0
- package/dist/cjs/components/chip-set/useChipSet.js +163 -0
- package/dist/cjs/components/chip-set/useChipSet.js.map +1 -0
- package/dist/cjs/components/chip-set/utils.d.ts +7 -0
- package/dist/cjs/components/chip-set/utils.js +18 -0
- package/dist/cjs/components/chip-set/utils.js.map +1 -0
- package/dist/cjs/components/collapse/CCollapse.js +14 -6
- package/dist/cjs/components/collapse/CCollapse.js.map +1 -1
- package/dist/cjs/components/conditional-portal/CConditionalPortal.js +3 -1
- package/dist/cjs/components/conditional-portal/CConditionalPortal.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdown.js +22 -29
- package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/cjs/components/form/CChipInput.d.ts +14 -2
- package/dist/cjs/components/form/CChipInput.js +77 -49
- package/dist/cjs/components/form/CChipInput.js.map +1 -1
- package/dist/cjs/components/form/CFormCheck.js.map +1 -1
- package/dist/cjs/components/form/CFormInput.js.map +1 -1
- package/dist/cjs/components/form/CFormSelect.js.map +1 -1
- package/dist/cjs/components/form/CFormTextarea.js.map +1 -1
- package/dist/cjs/components/form/CInputGroupText.js.map +1 -1
- package/dist/cjs/components/grid/CContainer.js +3 -1
- package/dist/cjs/components/grid/CContainer.js.map +1 -1
- package/dist/cjs/components/header/CHeaderBrand.js.map +1 -1
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/link/CLink.js +4 -2
- package/dist/cjs/components/link/CLink.js.map +1 -1
- package/dist/cjs/components/list-group/CListGroupItem.js.map +1 -1
- package/dist/cjs/components/modal/CModal.js +14 -2
- package/dist/cjs/components/modal/CModal.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelect.d.ts +73 -1
- package/dist/cjs/components/multi-select/CMultiSelect.js +157 -18
- package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectOptions.d.ts +3 -0
- package/dist/cjs/components/multi-select/CMultiSelectOptions.js +45 -2
- package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectSelection.d.ts +1 -0
- package/dist/cjs/components/multi-select/CMultiSelectSelection.js +4 -3
- package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
- package/dist/cjs/components/multi-select/types.d.ts +12 -0
- package/dist/cjs/components/multi-select/utils.js +1 -4
- package/dist/cjs/components/multi-select/utils.js.map +1 -1
- package/dist/cjs/components/nav/CNav.js.map +1 -1
- package/dist/cjs/components/nav/CNavGroup.d.ts +10 -5
- package/dist/cjs/components/nav/CNavGroup.js +83 -24
- package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
- package/dist/cjs/components/nav/CNavGroupContext.d.ts +25 -0
- package/dist/cjs/components/nav/CNavGroupContext.js +13 -0
- package/dist/cjs/components/nav/CNavGroupContext.js.map +1 -0
- package/dist/cjs/components/nav/CNavLink.d.ts +1 -5
- package/dist/cjs/components/nav/CNavLink.js +21 -8
- package/dist/cjs/components/nav/CNavLink.js.map +1 -1
- package/dist/cjs/components/popover/CPopover.js +57 -9
- package/dist/cjs/components/popover/CPopover.js.map +1 -1
- package/dist/cjs/components/progress/CProgress.js.map +1 -1
- package/dist/cjs/components/rating/CRating.d.ts +1 -1
- package/dist/cjs/components/rating/CRating.js.map +1 -1
- package/dist/cjs/components/sidebar/CSidebar.js +40 -23
- package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
- package/dist/cjs/components/sidebar/CSidebarNav.js +6 -35
- package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/cjs/components/table/CTableDataCell.js.map +1 -1
- package/dist/cjs/components/table/types.d.ts +2 -1
- package/dist/cjs/components/table/utils.js +4 -4
- package/dist/cjs/components/table/utils.js.map +1 -1
- package/dist/cjs/components/tabs/CTabPanel.js +3 -1
- package/dist/cjs/components/tabs/CTabPanel.js.map +1 -1
- package/dist/cjs/components/tooltip/CTooltip.js +57 -9
- package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
- package/dist/cjs/helpers/polymorphicComponent.d.ts +1 -2
- package/dist/cjs/hooks/useForkedRef.d.ts +1 -1
- package/dist/cjs/hooks/useForkedRef.js +6 -3
- package/dist/cjs/hooks/useForkedRef.js.map +1 -1
- package/dist/cjs/hooks/usePopper.js +8 -6
- package/dist/cjs/hooks/usePopper.js.map +1 -1
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
- package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +3 -3
- package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
- package/dist/cjs/utils/executeAfterTransition.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +2 -1
- package/dist/cjs/utils/swipe.d.ts +26 -0
- package/dist/cjs/utils/swipe.js +94 -0
- package/dist/cjs/utils/swipe.js.map +1 -0
- package/dist/esm/components/card/CCardImage.js.map +1 -1
- package/dist/esm/components/carousel/CCarousel.js +44 -33
- package/dist/esm/components/carousel/CCarousel.js.map +1 -1
- package/dist/esm/components/carousel/CCarouselItem.js +19 -28
- package/dist/esm/components/carousel/CCarouselItem.js.map +1 -1
- package/dist/esm/components/chip/CChip.d.ts +12 -0
- package/dist/esm/components/chip/CChip.js +16 -63
- package/dist/esm/components/chip/CChip.js.map +1 -1
- package/dist/esm/components/chip/const.d.ts +1 -0
- package/dist/esm/components/chip/const.js +6 -0
- package/dist/esm/components/chip/const.js.map +1 -0
- package/dist/esm/components/chip-set/CChipSet.d.ts +73 -0
- package/dist/esm/components/chip-set/CChipSet.js +64 -0
- package/dist/esm/components/chip-set/CChipSet.js.map +1 -0
- package/dist/esm/components/chip-set/index.d.ts +2 -0
- package/dist/esm/components/chip-set/useChipSet.d.ts +48 -0
- package/dist/esm/components/chip-set/useChipSet.js +161 -0
- package/dist/esm/components/chip-set/useChipSet.js.map +1 -0
- package/dist/esm/components/chip-set/utils.d.ts +7 -0
- package/dist/esm/components/chip-set/utils.js +16 -0
- package/dist/esm/components/chip-set/utils.js.map +1 -0
- package/dist/esm/components/collapse/CCollapse.js +14 -6
- package/dist/esm/components/collapse/CCollapse.js.map +1 -1
- package/dist/esm/components/conditional-portal/CConditionalPortal.js +3 -1
- package/dist/esm/components/conditional-portal/CConditionalPortal.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdown.js +22 -29
- package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/esm/components/form/CChipInput.d.ts +14 -2
- package/dist/esm/components/form/CChipInput.js +78 -50
- package/dist/esm/components/form/CChipInput.js.map +1 -1
- package/dist/esm/components/form/CFormCheck.js.map +1 -1
- package/dist/esm/components/form/CFormInput.js.map +1 -1
- package/dist/esm/components/form/CFormSelect.js.map +1 -1
- package/dist/esm/components/form/CFormTextarea.js.map +1 -1
- package/dist/esm/components/form/CInputGroupText.js.map +1 -1
- package/dist/esm/components/grid/CContainer.js +3 -1
- package/dist/esm/components/grid/CContainer.js.map +1 -1
- package/dist/esm/components/header/CHeaderBrand.js.map +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/link/CLink.js +4 -2
- package/dist/esm/components/link/CLink.js.map +1 -1
- package/dist/esm/components/list-group/CListGroupItem.js.map +1 -1
- package/dist/esm/components/modal/CModal.js +14 -2
- package/dist/esm/components/modal/CModal.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelect.d.ts +73 -1
- package/dist/esm/components/multi-select/CMultiSelect.js +158 -19
- package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js +1 -1
- package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectOptions.d.ts +3 -0
- package/dist/esm/components/multi-select/CMultiSelectOptions.js +45 -2
- package/dist/esm/components/multi-select/CMultiSelectOptions.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectSelection.d.ts +1 -0
- package/dist/esm/components/multi-select/CMultiSelectSelection.js +4 -3
- package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
- package/dist/esm/components/multi-select/types.d.ts +12 -0
- package/dist/esm/components/multi-select/utils.js +1 -4
- package/dist/esm/components/multi-select/utils.js.map +1 -1
- package/dist/esm/components/nav/CNav.js.map +1 -1
- package/dist/esm/components/nav/CNavGroup.d.ts +10 -5
- package/dist/esm/components/nav/CNavGroup.js +84 -25
- package/dist/esm/components/nav/CNavGroup.js.map +1 -1
- package/dist/esm/components/nav/CNavGroupContext.d.ts +25 -0
- package/dist/esm/components/nav/CNavGroupContext.js +11 -0
- package/dist/esm/components/nav/CNavGroupContext.js.map +1 -0
- package/dist/esm/components/nav/CNavLink.d.ts +1 -5
- package/dist/esm/components/nav/CNavLink.js +21 -8
- package/dist/esm/components/nav/CNavLink.js.map +1 -1
- package/dist/esm/components/popover/CPopover.js +57 -9
- package/dist/esm/components/popover/CPopover.js.map +1 -1
- package/dist/esm/components/progress/CProgress.js.map +1 -1
- package/dist/esm/components/rating/CRating.d.ts +1 -1
- package/dist/esm/components/rating/CRating.js.map +1 -1
- package/dist/esm/components/sidebar/CSidebar.js +40 -23
- package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
- package/dist/esm/components/sidebar/CSidebarNav.js +7 -36
- package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/esm/components/table/CTableDataCell.js.map +1 -1
- package/dist/esm/components/table/types.d.ts +2 -1
- package/dist/esm/components/table/utils.js +4 -4
- package/dist/esm/components/table/utils.js.map +1 -1
- package/dist/esm/components/tabs/CTabPanel.js +3 -1
- package/dist/esm/components/tabs/CTabPanel.js.map +1 -1
- package/dist/esm/components/tooltip/CTooltip.js +57 -9
- package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
- package/dist/esm/helpers/polymorphicComponent.d.ts +1 -2
- package/dist/esm/hooks/useForkedRef.d.ts +1 -1
- package/dist/esm/hooks/useForkedRef.js +6 -3
- package/dist/esm/hooks/useForkedRef.js.map +1 -1
- package/dist/esm/hooks/usePopper.js +9 -7
- package/dist/esm/hooks/usePopper.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +1 -1
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
- package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +3 -3
- package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js.map +1 -1
- package/dist/esm/utils/executeAfterTransition.js.map +1 -1
- package/dist/esm/utils/index.d.ts +2 -1
- package/dist/esm/utils/swipe.d.ts +26 -0
- package/dist/esm/utils/swipe.js +90 -0
- package/dist/esm/utils/swipe.js.map +1 -0
- package/package.json +6 -6
- package/src/components/autocomplete/CAutocompleteOptions.tsx +1 -1
- package/src/components/card/CCardImage.tsx +3 -2
- package/src/components/carousel/CCarousel.tsx +48 -51
- package/src/components/carousel/CCarouselContext.ts +1 -1
- package/src/components/carousel/CCarouselItem.tsx +25 -26
- package/src/components/carousel/__tests__/CCarousel.spec.tsx +47 -4
- package/src/components/carousel/__tests__/CCarouselItem.spec.tsx +37 -0
- package/src/components/chip/CChip.tsx +45 -78
- package/src/components/chip/__tests__/CChip.spec.tsx +26 -19
- package/src/components/chip/const.ts +3 -0
- package/src/components/chip-set/CChipSet.tsx +183 -0
- package/src/components/chip-set/__tests__/CChipSet.spec.tsx +215 -0
- package/src/components/chip-set/__tests__/__snapshots__/CChipSet.spec.tsx.snap +22 -0
- package/src/components/chip-set/index.ts +3 -0
- package/src/components/chip-set/useChipSet.ts +243 -0
- package/src/components/chip-set/utils.ts +19 -0
- package/src/components/collapse/CCollapse.tsx +18 -6
- package/src/components/conditional-portal/CConditionalPortal.tsx +4 -2
- package/src/components/dropdown/CDropdown.tsx +28 -33
- package/src/components/dropdown/CDropdownToggle.tsx +1 -1
- package/src/components/dropdown/__tests__/CDropdown.spec.tsx +55 -0
- package/src/components/focus-trap/__tests__/CFocusTrap.spec.tsx +1 -1
- package/src/components/form/CChipInput.tsx +105 -67
- package/src/components/form/CFormCheck.tsx +1 -2
- package/src/components/form/CFormInput.tsx +1 -2
- package/src/components/form/CFormSelect.tsx +1 -2
- package/src/components/form/CFormTextarea.tsx +1 -2
- package/src/components/form/CInputGroupText.tsx +3 -2
- package/src/components/form/__tests__/CChipInput.spec.tsx +67 -1
- package/src/components/form/__tests__/__snapshots__/CChipInput.spec.tsx.snap +7 -0
- package/src/components/grid/CContainer.tsx +3 -1
- package/src/components/header/CHeaderBrand.tsx +3 -2
- package/src/components/index.ts +1 -0
- package/src/components/link/CLink.tsx +7 -4
- package/src/components/list-group/CListGroupItem.tsx +3 -2
- package/src/components/modal/CModal.tsx +19 -2
- package/src/components/modal/__tests__/CModal.spec.tsx +43 -0
- package/src/components/multi-select/CMultiSelect.tsx +341 -46
- package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
- package/src/components/multi-select/CMultiSelectOptions.tsx +74 -3
- package/src/components/multi-select/CMultiSelectSelection.tsx +5 -1
- package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +12 -8
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +62 -45
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -2
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +1 -0
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +5 -1
- package/src/components/multi-select/types.ts +14 -0
- package/src/components/nav/CNav.tsx +3 -2
- package/src/components/nav/CNavGroup.tsx +193 -107
- package/src/components/nav/CNavGroupContext.ts +27 -0
- package/src/components/nav/CNavLink.tsx +26 -12
- package/src/components/nav/__tests__/CNavGroup.spec.tsx +195 -20
- package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +2 -0
- package/src/components/popover/CPopover.tsx +59 -9
- package/src/components/popover/__tests__/CPopover.spec.tsx +76 -1
- package/src/components/progress/CProgress.tsx +1 -2
- package/src/components/rating/CRating.tsx +1 -0
- package/src/components/search-button/__tests__/CSearchButton.spec.tsx +2 -2
- package/src/components/sidebar/CSidebar.tsx +51 -26
- package/src/components/sidebar/CSidebarNav.tsx +12 -51
- package/src/components/sidebar/__tests__/CSidebar.spec.tsx +26 -0
- package/src/components/table/CTableDataCell.tsx +2 -1
- package/src/components/table/types.ts +3 -1
- package/src/components/table/utils.ts +4 -4
- package/src/components/tabs/CTabPanel.tsx +3 -1
- package/src/components/tabs/CTabsContext.ts +1 -1
- package/src/components/tooltip/CTooltip.tsx +59 -9
- package/src/components/tooltip/__tests__/CTooltip.spec.tsx +96 -1
- package/src/helpers/polymorphicComponent.ts +1 -1
- package/src/hooks/useColorModes.ts +2 -2
- package/src/hooks/useForkedRef.ts +20 -15
- package/src/hooks/usePopper.ts +13 -9
- package/src/utils/__tests__/swipe.spec.ts +82 -0
- package/src/utils/executeAfterTransition.ts +1 -1
- package/src/utils/index.ts +2 -0
- package/src/utils/mergeClassNames.ts +1 -1
- package/src/utils/swipe.ts +114 -0
- package/dist/cjs/components/sidebar/CSidebarNavContext.d.ts +0 -5
- package/dist/cjs/components/sidebar/CSidebarNavContext.js +0 -8
- package/dist/cjs/components/sidebar/CSidebarNavContext.js.map +0 -1
- package/dist/esm/components/sidebar/CSidebarNavContext.d.ts +0 -5
- package/dist/esm/components/sidebar/CSidebarNavContext.js +0 -6
- package/dist/esm/components/sidebar/CSidebarNavContext.js.map +0 -1
- package/src/components/sidebar/CSidebarNavContext.ts +0 -8
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
Children,
|
|
3
|
-
forwardRef,
|
|
4
|
-
HTMLAttributes,
|
|
5
|
-
TouchEvent,
|
|
6
|
-
useState,
|
|
7
|
-
useEffect,
|
|
8
|
-
useRef,
|
|
9
|
-
} from 'react'
|
|
1
|
+
import React, { Children, forwardRef, HTMLAttributes, useState, useEffect, useRef } from 'react'
|
|
10
2
|
import PropTypes from 'prop-types'
|
|
11
3
|
import classNames from 'classnames'
|
|
12
4
|
|
|
13
|
-
import { isInViewport } from '../../utils'
|
|
5
|
+
import { isInViewport, isRTL, Swipe } from '../../utils'
|
|
14
6
|
import { useForkedRef } from '../../hooks'
|
|
15
7
|
|
|
16
8
|
import { CCarouselContext } from './CCarouselContext'
|
|
@@ -95,27 +87,32 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
95
87
|
const carouselRef = useRef<HTMLDivElement>(null)
|
|
96
88
|
const forkedRef = useForkedRef(ref, carouselRef)
|
|
97
89
|
const data = useRef<DataType>({}).current
|
|
90
|
+
const handleControlClickRef = useRef<(direction: string) => void>(() => undefined)
|
|
98
91
|
|
|
99
92
|
const [active, setActive] = useState<number>(activeIndex)
|
|
100
93
|
const [animating, setAnimating] = useState<boolean>(false)
|
|
101
94
|
const [customInterval, setCustomInterval] = useState<boolean | number>()
|
|
102
95
|
const [direction, setDirection] = useState<string>('next')
|
|
103
96
|
const [itemsNumber, setItemsNumber] = useState<number>(0)
|
|
104
|
-
const [touchPosition, setTouchPosition] = useState<number | null>(null)
|
|
105
97
|
const [visible, setVisible] = useState<boolean>()
|
|
106
98
|
|
|
107
99
|
useEffect(() => {
|
|
108
100
|
setItemsNumber(Children.toArray(children).length)
|
|
109
|
-
})
|
|
101
|
+
}, [children])
|
|
110
102
|
|
|
111
103
|
useEffect(() => {
|
|
112
|
-
|
|
104
|
+
if (visible) {
|
|
105
|
+
cycle()
|
|
106
|
+
}
|
|
113
107
|
}, [visible])
|
|
114
108
|
|
|
115
109
|
useEffect(() => {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
if (animating) {
|
|
111
|
+
onSlide?.(active, direction)
|
|
112
|
+
} else {
|
|
113
|
+
cycle()
|
|
114
|
+
onSlid?.(active, direction)
|
|
115
|
+
}
|
|
119
116
|
}, [animating])
|
|
120
117
|
|
|
121
118
|
useEffect(() => {
|
|
@@ -124,10 +121,34 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
124
121
|
return () => {
|
|
125
122
|
window.removeEventListener('scroll', handleScroll)
|
|
126
123
|
}
|
|
127
|
-
})
|
|
124
|
+
}, [])
|
|
125
|
+
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!touch || !carouselRef.current) {
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const swipe = new Swipe(carouselRef.current, {
|
|
132
|
+
onLeft: () => handleControlClickRef.current(isRTL(carouselRef.current) ? 'prev' : 'next'),
|
|
133
|
+
onRight: () => handleControlClickRef.current(isRTL(carouselRef.current) ? 'next' : 'prev'),
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
return () => swipe.dispose()
|
|
137
|
+
}, [touch])
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
return () => clearCycleTimeout()
|
|
141
|
+
}, [])
|
|
142
|
+
|
|
143
|
+
const clearCycleTimeout = () => {
|
|
144
|
+
if (data.timeout) {
|
|
145
|
+
clearTimeout(data.timeout)
|
|
146
|
+
data.timeout = null
|
|
147
|
+
}
|
|
148
|
+
}
|
|
128
149
|
|
|
129
150
|
const cycle = () => {
|
|
130
|
-
|
|
151
|
+
clearCycleTimeout()
|
|
131
152
|
if (!wrap && active === itemsNumber - 1) {
|
|
132
153
|
return
|
|
133
154
|
}
|
|
@@ -139,7 +160,7 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
139
160
|
)
|
|
140
161
|
}
|
|
141
162
|
}
|
|
142
|
-
const _pause = () => pause &&
|
|
163
|
+
const _pause = () => pause && clearCycleTimeout()
|
|
143
164
|
|
|
144
165
|
const nextItemWhenVisible = () => {
|
|
145
166
|
// Don't call next when the page isn't visible
|
|
@@ -158,11 +179,12 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
158
179
|
}
|
|
159
180
|
setDirection(direction)
|
|
160
181
|
if (direction === 'next') {
|
|
161
|
-
active === itemsNumber - 1 ?
|
|
182
|
+
setActive(active === itemsNumber - 1 ? 0 : active + 1)
|
|
162
183
|
} else {
|
|
163
|
-
active === 0 ?
|
|
184
|
+
setActive(active === 0 ? itemsNumber - 1 : active - 1)
|
|
164
185
|
}
|
|
165
186
|
}
|
|
187
|
+
handleControlClickRef.current = handleControlClick
|
|
166
188
|
|
|
167
189
|
const handleIndicatorClick = (index: number) => {
|
|
168
190
|
if (active === index) {
|
|
@@ -189,32 +211,6 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
189
211
|
}
|
|
190
212
|
}
|
|
191
213
|
|
|
192
|
-
const handleTouchMove = (e: TouchEvent) => {
|
|
193
|
-
const touchDown = touchPosition
|
|
194
|
-
|
|
195
|
-
if (touchDown === null) {
|
|
196
|
-
return
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const currentTouch = e.touches[0].clientX
|
|
200
|
-
const diff = touchDown - currentTouch
|
|
201
|
-
|
|
202
|
-
if (diff > 5) {
|
|
203
|
-
handleControlClick('next')
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (diff < -5) {
|
|
207
|
-
handleControlClick('prev')
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
setTouchPosition(null)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const handleTouchStart = (e: TouchEvent) => {
|
|
214
|
-
const touchDown = e.touches[0].clientX
|
|
215
|
-
setTouchPosition(touchDown)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
214
|
return (
|
|
219
215
|
<div
|
|
220
216
|
className={classNames(
|
|
@@ -227,7 +223,6 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
227
223
|
{...(dark && { 'data-coreui-theme': 'dark' })}
|
|
228
224
|
onMouseEnter={_pause}
|
|
229
225
|
onMouseLeave={cycle}
|
|
230
|
-
{...(touch && { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove })}
|
|
231
226
|
{...rest}
|
|
232
227
|
ref={forkedRef}
|
|
233
228
|
>
|
|
@@ -244,7 +239,9 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
244
239
|
<button
|
|
245
240
|
key={`indicator${index}`}
|
|
246
241
|
onClick={() => {
|
|
247
|
-
!animating
|
|
242
|
+
if (!animating) {
|
|
243
|
+
handleIndicatorClick(index)
|
|
244
|
+
}
|
|
248
245
|
}}
|
|
249
246
|
className={classNames({
|
|
250
247
|
active: active === index,
|
|
@@ -260,8 +257,8 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
|
|
|
260
257
|
<div className="carousel-inner">
|
|
261
258
|
{Children.map(children, (child, index) => {
|
|
262
259
|
if (React.isValidElement(child)) {
|
|
263
|
-
return React.cloneElement(child as React.ReactElement<
|
|
264
|
-
active: active === index
|
|
260
|
+
return React.cloneElement(child as React.ReactElement<Record<string, unknown>>, {
|
|
261
|
+
active: active === index,
|
|
265
262
|
direction: direction,
|
|
266
263
|
key: index,
|
|
267
264
|
})
|
|
@@ -64,37 +64,36 @@ export const CCarouselItem = forwardRef<HTMLDivElement, CCarouselItemProps>(
|
|
|
64
64
|
}, [active])
|
|
65
65
|
|
|
66
66
|
useEffect(() => {
|
|
67
|
-
carouselItemRef.current
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
const element = carouselItemRef.current
|
|
68
|
+
|
|
69
|
+
if (!element) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const handleTransitionStart = () => {
|
|
74
74
|
if (active) {
|
|
75
|
-
|
|
75
|
+
setAnimating(true)
|
|
76
76
|
}
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleTransitionEnd = () => {
|
|
80
|
+
if (active) {
|
|
81
|
+
setAnimating(false)
|
|
79
82
|
}
|
|
80
|
-
|
|
83
|
+
|
|
84
|
+
setDirectionClassName('')
|
|
85
|
+
setOrderClassName('')
|
|
86
|
+
setActiveClassName(active ? 'active' : '')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
element.addEventListener('transitionstart', handleTransitionStart)
|
|
90
|
+
element.addEventListener('transitionend', handleTransitionEnd)
|
|
91
|
+
|
|
81
92
|
return () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
})
|
|
85
|
-
carouselItemRef.current?.removeEventListener('transitionend', () => {
|
|
86
|
-
active && setAnimating(false)
|
|
87
|
-
setDirectionClassName('')
|
|
88
|
-
setOrderClassName('')
|
|
89
|
-
if (active) {
|
|
90
|
-
setActiveClassName('active')
|
|
91
|
-
}
|
|
92
|
-
if (!active) {
|
|
93
|
-
setActiveClassName('')
|
|
94
|
-
}
|
|
95
|
-
})
|
|
93
|
+
element.removeEventListener('transitionstart', handleTransitionStart)
|
|
94
|
+
element.removeEventListener('transitionend', handleTransitionEnd)
|
|
96
95
|
}
|
|
97
|
-
})
|
|
96
|
+
}, [active])
|
|
98
97
|
|
|
99
98
|
return (
|
|
100
99
|
<div
|
|
@@ -59,6 +59,49 @@ test('loads and displays CCarousel component', async () => {
|
|
|
59
59
|
expect(container).toMatchSnapshot()
|
|
60
60
|
})
|
|
61
61
|
|
|
62
|
+
test('CCarousel does not stack cycle timeouts when pause is disabled', async () => {
|
|
63
|
+
jest.useFakeTimers()
|
|
64
|
+
|
|
65
|
+
render(
|
|
66
|
+
<CCarousel interval={1000} pause={false}>
|
|
67
|
+
<CCarouselItem>Item-1</CCarouselItem>
|
|
68
|
+
<CCarouselItem>Item-2</CCarouselItem>
|
|
69
|
+
<CCarouselItem>Item-3</CCarouselItem>
|
|
70
|
+
</CCarousel>
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
const carousel = document.querySelector('.carousel') as HTMLElement
|
|
74
|
+
const baseTimerCount = jest.getTimerCount()
|
|
75
|
+
|
|
76
|
+
fireEvent.mouseLeave(carousel)
|
|
77
|
+
fireEvent.mouseLeave(carousel)
|
|
78
|
+
fireEvent.mouseLeave(carousel)
|
|
79
|
+
|
|
80
|
+
expect(jest.getTimerCount()).toBe(baseTimerCount)
|
|
81
|
+
|
|
82
|
+
jest.useRealTimers()
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
test('CCarousel clears the pending cycle timeout on unmount', async () => {
|
|
86
|
+
jest.useFakeTimers()
|
|
87
|
+
|
|
88
|
+
const { unmount } = render(
|
|
89
|
+
<CCarousel interval={1000}>
|
|
90
|
+
<CCarouselItem>Item-1</CCarouselItem>
|
|
91
|
+
<CCarouselItem>Item-2</CCarouselItem>
|
|
92
|
+
</CCarousel>
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
const baseTimerCount = jest.getTimerCount()
|
|
96
|
+
expect(baseTimerCount).toBeGreaterThan(0)
|
|
97
|
+
|
|
98
|
+
unmount()
|
|
99
|
+
|
|
100
|
+
expect(jest.getTimerCount()).toBe(baseTimerCount - 1)
|
|
101
|
+
|
|
102
|
+
jest.useRealTimers()
|
|
103
|
+
})
|
|
104
|
+
|
|
62
105
|
test('CCarousel click on indicator', async () => {
|
|
63
106
|
const { container } = render(
|
|
64
107
|
<CCarousel controls indicators>
|
|
@@ -86,7 +129,7 @@ test('CCarousel click on indicator', async () => {
|
|
|
86
129
|
|
|
87
130
|
// click
|
|
88
131
|
const ci = document.querySelector('.carousel-indicators')
|
|
89
|
-
|
|
132
|
+
fireEvent.click(ci!.children[1])
|
|
90
133
|
fireEvent.transitionEnd(item1)
|
|
91
134
|
fireEvent.transitionEnd(item2)
|
|
92
135
|
|
|
@@ -94,7 +137,7 @@ test('CCarousel click on indicator', async () => {
|
|
|
94
137
|
expect(item2).toHaveClass('active')
|
|
95
138
|
|
|
96
139
|
// goback-click
|
|
97
|
-
|
|
140
|
+
fireEvent.click(ci!.children[0])
|
|
98
141
|
fireEvent.transitionEnd(item1)
|
|
99
142
|
fireEvent.transitionEnd(item2)
|
|
100
143
|
|
|
@@ -130,7 +173,7 @@ test('CCarousel click on button', async () => {
|
|
|
130
173
|
|
|
131
174
|
// click
|
|
132
175
|
const buttonNext = document.querySelector('.carousel-control-next')
|
|
133
|
-
|
|
176
|
+
fireEvent.click(buttonNext!)
|
|
134
177
|
fireEvent.transitionEnd(item1)
|
|
135
178
|
fireEvent.transitionEnd(item2)
|
|
136
179
|
|
|
@@ -139,7 +182,7 @@ test('CCarousel click on button', async () => {
|
|
|
139
182
|
|
|
140
183
|
// goback-click
|
|
141
184
|
const buttonPrev = document.querySelector('.carousel-control-prev')
|
|
142
|
-
|
|
185
|
+
fireEvent.click(buttonPrev!)
|
|
143
186
|
fireEvent.transitionEnd(item1)
|
|
144
187
|
fireEvent.transitionEnd(item2)
|
|
145
188
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
import { CCarousel, CCarouselItem } from '../index'
|
|
5
|
+
|
|
6
|
+
const isTransition = (type: string) => type === 'transitionstart' || type === 'transitionend'
|
|
7
|
+
|
|
8
|
+
test('CCarouselItem removes the exact transition listener references on cleanup', async () => {
|
|
9
|
+
const addSpy = jest.spyOn(HTMLElement.prototype, 'addEventListener')
|
|
10
|
+
const removeSpy = jest.spyOn(HTMLElement.prototype, 'removeEventListener')
|
|
11
|
+
|
|
12
|
+
const { container, unmount } = render(
|
|
13
|
+
<CCarousel>
|
|
14
|
+
<CCarouselItem>Item-1</CCarouselItem>
|
|
15
|
+
<CCarouselItem>Item-2</CCarouselItem>
|
|
16
|
+
</CCarousel>
|
|
17
|
+
)
|
|
18
|
+
const items = new Set<EventTarget>(container.querySelectorAll('.carousel-item'))
|
|
19
|
+
unmount()
|
|
20
|
+
|
|
21
|
+
const handlersOn = (spy: jest.SpyInstance) =>
|
|
22
|
+
spy.mock.calls
|
|
23
|
+
.map((args, index) => ({ args, context: spy.mock.contexts[index] }))
|
|
24
|
+
.filter(({ args, context }) => isTransition(args[0]) && items.has(context as EventTarget))
|
|
25
|
+
.map(({ args }) => args[1])
|
|
26
|
+
|
|
27
|
+
const added = handlersOn(addSpy)
|
|
28
|
+
const removed = handlersOn(removeSpy)
|
|
29
|
+
|
|
30
|
+
expect(added.length).toBeGreaterThan(0)
|
|
31
|
+
for (const handler of added) {
|
|
32
|
+
expect(removed).toContain(handler)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
addSpy.mockRestore()
|
|
36
|
+
removeSpy.mockRestore()
|
|
37
|
+
})
|
|
@@ -49,6 +49,10 @@ export interface CChipProps extends HTMLAttributes<HTMLSpanElement | HTMLButtonE
|
|
|
49
49
|
* Disables the React Chip component and removes interactive behavior.
|
|
50
50
|
*/
|
|
51
51
|
disabled?: boolean
|
|
52
|
+
/**
|
|
53
|
+
* Turns the React Chip component into a filter chip. A filter chip is selectable and shows a leading check icon while selected.
|
|
54
|
+
*/
|
|
55
|
+
filter?: boolean
|
|
52
56
|
/**
|
|
53
57
|
* Callback fired when the React Chip component becomes deselected.
|
|
54
58
|
*/
|
|
@@ -84,18 +88,24 @@ export interface CChipProps extends HTMLAttributes<HTMLSpanElement | HTMLButtonE
|
|
|
84
88
|
* Controls the selected state of a selectable React Chip component.
|
|
85
89
|
*/
|
|
86
90
|
selected?: boolean
|
|
91
|
+
/**
|
|
92
|
+
* Replaces the default selected icon shown by a filter React Chip component with a custom icon node.
|
|
93
|
+
*/
|
|
94
|
+
selectedIcon?: ReactNode
|
|
87
95
|
/**
|
|
88
96
|
* Sets the size of the React Chip component to small or large.
|
|
89
97
|
*/
|
|
90
98
|
size?: 'sm' | 'lg'
|
|
99
|
+
/**
|
|
100
|
+
* Sets the value associated with the React Chip component, used by `CChipSet` to track selection.
|
|
101
|
+
*/
|
|
102
|
+
value?: string
|
|
91
103
|
/**
|
|
92
104
|
* Sets the visual variant of the React Chip component to outline style.
|
|
93
105
|
*/
|
|
94
106
|
variant?: 'outline'
|
|
95
107
|
}
|
|
96
108
|
|
|
97
|
-
const SELECTOR_FOCUSABLE_ITEMS = '[data-coreui-chip-focusable="true"]:not(.disabled)'
|
|
98
|
-
|
|
99
109
|
export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forwardRef<
|
|
100
110
|
HTMLSpanElement | HTMLButtonElement,
|
|
101
111
|
CChipProps
|
|
@@ -110,6 +120,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
110
120
|
clickable,
|
|
111
121
|
color,
|
|
112
122
|
disabled,
|
|
123
|
+
filter,
|
|
113
124
|
onClick,
|
|
114
125
|
onDeselect,
|
|
115
126
|
onKeyDown,
|
|
@@ -120,13 +131,17 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
120
131
|
removeIcon,
|
|
121
132
|
selectable,
|
|
122
133
|
selected,
|
|
134
|
+
selectedIcon,
|
|
123
135
|
size,
|
|
124
136
|
tabIndex,
|
|
137
|
+
value,
|
|
125
138
|
variant,
|
|
126
139
|
...rest
|
|
127
140
|
},
|
|
128
141
|
ref
|
|
129
142
|
) => {
|
|
143
|
+
// A filter chip is selectable by definition.
|
|
144
|
+
const isSelectable = Boolean(selectable || filter)
|
|
130
145
|
const chipRef = useRef<HTMLSpanElement | HTMLButtonElement>(null)
|
|
131
146
|
const forkedRef = useForkedRef(ref, chipRef)
|
|
132
147
|
const isSelectedControlled = selected !== undefined
|
|
@@ -140,47 +155,15 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
140
155
|
}, [isSelectedControlled, selected])
|
|
141
156
|
|
|
142
157
|
const isFocusable = useMemo(
|
|
143
|
-
() => Boolean(!disabled && (
|
|
144
|
-
[disabled,
|
|
158
|
+
() => Boolean(!disabled && (isSelectable || removable)),
|
|
159
|
+
[disabled, isSelectable, removable]
|
|
145
160
|
)
|
|
146
161
|
|
|
147
|
-
const getFocusableSibling = (shouldGetNext: boolean) => {
|
|
148
|
-
const currentElement = chipRef.current
|
|
149
|
-
if (!currentElement?.parentElement) {
|
|
150
|
-
return null
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const chips = Array.from(
|
|
154
|
-
currentElement.parentElement.querySelectorAll<HTMLElement>(SELECTOR_FOCUSABLE_ITEMS)
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
const index = chips.indexOf(currentElement as unknown as HTMLElement)
|
|
158
|
-
if (index === -1 || chips.length <= 1) {
|
|
159
|
-
return null
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const targetIndex = shouldGetNext ? index + 1 : index - 1
|
|
163
|
-
return chips[targetIndex] ?? null
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const navigateToEdge = (targetIndex: 0 | -1) => {
|
|
167
|
-
const currentElement = chipRef.current
|
|
168
|
-
if (!currentElement?.parentElement) {
|
|
169
|
-
return
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const chips = Array.from(
|
|
173
|
-
currentElement.parentElement.querySelectorAll<HTMLElement>(SELECTOR_FOCUSABLE_ITEMS)
|
|
174
|
-
)
|
|
175
|
-
const edgeChip = targetIndex === -1 ? chips[chips.length - 1] : chips[0]
|
|
176
|
-
edgeChip?.focus()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
162
|
const setSelectableState = (
|
|
180
163
|
nextSelected: boolean,
|
|
181
164
|
event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>
|
|
182
165
|
) => {
|
|
183
|
-
if (!
|
|
166
|
+
if (!isSelectable || disabled || nextSelected === selectedState) {
|
|
184
167
|
return
|
|
185
168
|
}
|
|
186
169
|
|
|
@@ -219,7 +202,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
219
202
|
return
|
|
220
203
|
}
|
|
221
204
|
|
|
222
|
-
if (
|
|
205
|
+
if (isSelectable) {
|
|
223
206
|
toggleSelectedState(event)
|
|
224
207
|
}
|
|
225
208
|
|
|
@@ -236,7 +219,7 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
236
219
|
case 'Enter':
|
|
237
220
|
case ' ':
|
|
238
221
|
case 'Spacebar': {
|
|
239
|
-
if (
|
|
222
|
+
if (isSelectable) {
|
|
240
223
|
event.preventDefault()
|
|
241
224
|
toggleSelectedState(event)
|
|
242
225
|
}
|
|
@@ -247,45 +230,11 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
247
230
|
case 'Delete': {
|
|
248
231
|
if (removable) {
|
|
249
232
|
event.preventDefault()
|
|
250
|
-
const sibling = getFocusableSibling(false) || getFocusableSibling(true)
|
|
251
|
-
sibling?.focus()
|
|
252
233
|
handleRemove(event)
|
|
253
234
|
}
|
|
254
235
|
break
|
|
255
236
|
}
|
|
256
237
|
|
|
257
|
-
case 'ArrowLeft': {
|
|
258
|
-
event.preventDefault()
|
|
259
|
-
const sibling = getFocusableSibling(false)
|
|
260
|
-
sibling?.focus()
|
|
261
|
-
if (selectedState && event.shiftKey) {
|
|
262
|
-
sibling?.dispatchEvent(new CustomEvent('coreui-chip-select'))
|
|
263
|
-
}
|
|
264
|
-
break
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
case 'ArrowRight': {
|
|
268
|
-
event.preventDefault()
|
|
269
|
-
const sibling = getFocusableSibling(true)
|
|
270
|
-
sibling?.focus()
|
|
271
|
-
if (selectedState && event.shiftKey) {
|
|
272
|
-
sibling?.dispatchEvent(new CustomEvent('coreui-chip-select'))
|
|
273
|
-
}
|
|
274
|
-
break
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
case 'Home': {
|
|
278
|
-
event.preventDefault()
|
|
279
|
-
navigateToEdge(0)
|
|
280
|
-
break
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
case 'End': {
|
|
284
|
-
event.preventDefault()
|
|
285
|
-
navigateToEdge(-1)
|
|
286
|
-
break
|
|
287
|
-
}
|
|
288
|
-
|
|
289
238
|
// No default
|
|
290
239
|
}
|
|
291
240
|
|
|
@@ -297,18 +246,19 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
297
246
|
className={classNames(
|
|
298
247
|
'chip',
|
|
299
248
|
{
|
|
300
|
-
active:
|
|
249
|
+
active: isSelectable ? selectedState : active,
|
|
301
250
|
disabled,
|
|
302
251
|
[`chip-${color}`]: color,
|
|
303
252
|
[`chip-${size}`]: size,
|
|
304
|
-
'chip-clickable': clickable ||
|
|
253
|
+
'chip-clickable': clickable || isSelectable || Boolean(onClick),
|
|
305
254
|
'chip-outline': variant === 'outline',
|
|
306
255
|
},
|
|
307
256
|
className
|
|
308
257
|
)}
|
|
309
258
|
data-coreui-chip-focusable={isFocusable || undefined}
|
|
259
|
+
data-coreui-chip-value={value}
|
|
310
260
|
{...(disabled && { 'aria-disabled': true })}
|
|
311
|
-
{...(
|
|
261
|
+
{...(isSelectable && { 'aria-selected': selectedState })}
|
|
312
262
|
{...(isFocusable && tabIndex === undefined && { tabIndex: 0 })}
|
|
313
263
|
onClick={handleClick}
|
|
314
264
|
onKeyDown={handleKeyDown}
|
|
@@ -316,15 +266,29 @@ export const CChip: PolymorphicRefForwardingComponent<'span', CChipProps> = forw
|
|
|
316
266
|
{...rest}
|
|
317
267
|
ref={forkedRef}
|
|
318
268
|
>
|
|
269
|
+
{filter && selectedState && (
|
|
270
|
+
<span className="chip-check" aria-hidden="true">
|
|
271
|
+
{selectedIcon ?? (
|
|
272
|
+
<svg
|
|
273
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
274
|
+
width="16"
|
|
275
|
+
height="16"
|
|
276
|
+
viewBox="0 0 512 512"
|
|
277
|
+
fill="currentColor"
|
|
278
|
+
>
|
|
279
|
+
<path d="M425.373 89.373 196 318.745 86.627 209.373l-45.254 45.254L196 409.255l274.627-274.628z" />
|
|
280
|
+
</svg>
|
|
281
|
+
)}
|
|
282
|
+
</span>
|
|
283
|
+
)}
|
|
319
284
|
{children}
|
|
320
|
-
{removable && (
|
|
285
|
+
{removable && !disabled && (
|
|
321
286
|
<button
|
|
322
287
|
type="button"
|
|
323
288
|
className="chip-remove"
|
|
324
289
|
aria-label={ariaRemoveLabel}
|
|
325
290
|
onClick={handleRemoveClick}
|
|
326
291
|
tabIndex={-1}
|
|
327
|
-
disabled={disabled}
|
|
328
292
|
>
|
|
329
293
|
{removeIcon ?? (
|
|
330
294
|
<svg
|
|
@@ -357,6 +321,7 @@ CChip.propTypes = {
|
|
|
357
321
|
clickable: PropTypes.bool,
|
|
358
322
|
color: colorPropType,
|
|
359
323
|
disabled: PropTypes.bool,
|
|
324
|
+
filter: PropTypes.bool,
|
|
360
325
|
onDeselect: PropTypes.func,
|
|
361
326
|
onRemove: PropTypes.func,
|
|
362
327
|
onSelect: PropTypes.func,
|
|
@@ -365,7 +330,9 @@ CChip.propTypes = {
|
|
|
365
330
|
removeIcon: PropTypes.node,
|
|
366
331
|
selectable: PropTypes.bool,
|
|
367
332
|
selected: PropTypes.bool,
|
|
333
|
+
selectedIcon: PropTypes.node,
|
|
368
334
|
size: PropTypes.oneOf(['sm', 'lg']),
|
|
335
|
+
value: PropTypes.string,
|
|
369
336
|
variant: PropTypes.oneOf(['outline']),
|
|
370
337
|
}
|
|
371
338
|
|
|
@@ -55,7 +55,7 @@ test('CChip selectable', async () => {
|
|
|
55
55
|
const { getByText } = render(
|
|
56
56
|
<CChip selectable={true} onSelect={onSelect} onDeselect={onDeselect}>
|
|
57
57
|
Selectable
|
|
58
|
-
</CChip
|
|
58
|
+
</CChip>
|
|
59
59
|
)
|
|
60
60
|
const chip = getByText('Selectable')
|
|
61
61
|
|
|
@@ -71,28 +71,35 @@ test('CChip selectable', async () => {
|
|
|
71
71
|
expect(onDeselect).toHaveBeenCalledTimes(1)
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
test('CChip
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
</div>,
|
|
74
|
+
test('CChip filter shows a check icon while selected and implies selectable', async () => {
|
|
75
|
+
const onSelect = jest.fn()
|
|
76
|
+
const { getByText, container } = render(
|
|
77
|
+
<CChip filter={true} onSelect={onSelect}>
|
|
78
|
+
Filter
|
|
79
|
+
</CChip>
|
|
81
80
|
)
|
|
81
|
+
const chip = getByText('Filter')
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const third = getByText('Third')
|
|
83
|
+
expect(chip).toHaveAttribute('aria-selected', 'false')
|
|
84
|
+
expect(container.querySelector('.chip-check')).not.toBeInTheDocument()
|
|
86
85
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
expect(
|
|
86
|
+
fireEvent.click(chip)
|
|
87
|
+
expect(chip).toHaveClass('active')
|
|
88
|
+
expect(onSelect).toHaveBeenCalledTimes(1)
|
|
89
|
+
expect(container.querySelector('.chip-check')).toBeInTheDocument()
|
|
90
|
+
|
|
91
|
+
fireEvent.click(chip)
|
|
92
|
+
expect(container.querySelector('.chip-check')).not.toBeInTheDocument()
|
|
93
|
+
})
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
test('CChip filter renders a custom selectedIcon', async () => {
|
|
96
|
+
const { container } = render(
|
|
97
|
+
<CChip filter={true} selected={true} selectedIcon={<span data-testid="custom-check" />}>
|
|
98
|
+
Filter
|
|
99
|
+
</CChip>
|
|
100
|
+
)
|
|
93
101
|
|
|
94
|
-
|
|
95
|
-
expect(first).toHaveFocus()
|
|
102
|
+
expect(container.querySelector('.chip-check [data-testid="custom-check"]')).toBeInTheDocument()
|
|
96
103
|
})
|
|
97
104
|
|
|
98
105
|
test('CChip delete triggers remove callback', async () => {
|
|
@@ -103,7 +110,7 @@ test('CChip delete triggers remove callback', async () => {
|
|
|
103
110
|
First
|
|
104
111
|
</CChip>
|
|
105
112
|
<CChip removable={true}>Second</CChip>
|
|
106
|
-
</div
|
|
113
|
+
</div>
|
|
107
114
|
)
|
|
108
115
|
|
|
109
116
|
const first = getByText('First')
|