@coreui/react-pro 5.24.1 → 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/README.md +1 -1
- 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/date-picker/CDatePicker.d.ts +1 -1
- package/dist/cjs/components/date-picker/CDatePicker.js.map +1 -1
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js +2 -0
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdown.js +23 -30
- 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 +2 -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 +13 -6
- package/dist/cjs/components/nav/CNavGroup.js +86 -23
- 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/one-time-password-input/COneTimePassword.js +3 -3
- package/dist/cjs/components/one-time-password-input/COneTimePassword.js.map +1 -1
- package/dist/cjs/components/popover/CPopover.js +69 -24
- 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/search-button/CSearchButton.d.ts +32 -0
- package/dist/cjs/components/search-button/CSearchButton.js +77 -0
- package/dist/cjs/components/search-button/CSearchButton.js.map +1 -0
- package/dist/cjs/components/search-button/index.d.ts +2 -0
- package/dist/cjs/components/search-button/types.d.ts +10 -0
- package/dist/cjs/components/search-button/utils.d.ts +11 -0
- package/dist/cjs/components/search-button/utils.js +115 -0
- package/dist/cjs/components/search-button/utils.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/cjs/components/sidebar/CSidebarNav.js +12 -36
- package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTable.js +2 -2
- package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableInterface.d.ts +2 -2
- 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/time-picker/CTimePicker.d.ts +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/cjs/components/tooltip/CTooltip.js +69 -24
- package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
- package/dist/cjs/components/virtual-scroller/CVirtualScroller.js +11 -8
- package/dist/cjs/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/cjs/helpers/polymorphicComponent.d.ts +1 -2
- package/dist/cjs/hooks/useDebouncedCallback.d.ts +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.js +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.js.map +1 -1
- 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 +4 -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/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
- package/dist/cjs/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
- package/dist/cjs/node_modules/ua-parser-js/dist/ua-parser.min.js +4 -4
- 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/date-picker/CDatePicker.d.ts +1 -1
- package/dist/esm/components/date-picker/CDatePicker.js.map +1 -1
- package/dist/esm/components/date-range-picker/CDateRangePicker.js +2 -0
- package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdown.js +23 -30
- 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 +2 -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 +13 -6
- package/dist/esm/components/nav/CNavGroup.js +87 -24
- 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/one-time-password-input/COneTimePassword.js +3 -3
- package/dist/esm/components/one-time-password-input/COneTimePassword.js.map +1 -1
- package/dist/esm/components/popover/CPopover.js +69 -24
- 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/search-button/CSearchButton.d.ts +32 -0
- package/dist/esm/components/search-button/CSearchButton.js +75 -0
- package/dist/esm/components/search-button/CSearchButton.js.map +1 -0
- package/dist/esm/components/search-button/index.d.ts +2 -0
- package/dist/esm/components/search-button/types.d.ts +10 -0
- package/dist/esm/components/search-button/utils.d.ts +11 -0
- package/dist/esm/components/search-button/utils.js +104 -0
- package/dist/esm/components/search-button/utils.js.map +1 -0
- 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.d.ts +12 -0
- package/dist/esm/components/sidebar/CSidebarNav.js +13 -37
- package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTable.js +2 -2
- package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableInterface.d.ts +2 -2
- 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/time-picker/CTimePicker.d.ts +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/esm/components/tooltip/CTooltip.js +69 -24
- package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
- package/dist/esm/components/virtual-scroller/CVirtualScroller.js +11 -8
- package/dist/esm/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/esm/helpers/polymorphicComponent.d.ts +1 -2
- package/dist/esm/hooks/useDebouncedCallback.d.ts +1 -1
- package/dist/esm/hooks/useDebouncedCallback.js +1 -1
- package/dist/esm/hooks/useDebouncedCallback.js.map +1 -1
- 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 +2 -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/@coreui/icons/dist/esm/free/cil-arrow-bottom.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-bottom.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-arrow-top.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-filter-x.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js +1 -1
- package/dist/esm/node_modules/@coreui/icons/dist/esm/free/cil-swap-vertical.js.map +1 -1
- package/dist/esm/node_modules/ua-parser-js/dist/ua-parser.min.js +4 -4
- 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 +8 -6
- package/src/components/autocomplete/CAutocompleteOptions.tsx +1 -1
- package/src/components/autocomplete/__tests__/CAutocomplete.spec.tsx +18 -16
- package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.tsx +37 -28
- package/src/components/autocomplete/__tests__/__snapshots__/CAutocomplete.spec.tsx.snap +129 -0
- package/src/components/autocomplete/__tests__/__snapshots__/CAutocompleteOptions.spec.tsx.snap +36 -0
- package/src/components/calendar/__tests__/CCalendar.spec.tsx +40 -45
- package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +99 -75
- package/src/components/calendar/__tests__/utils.spec.tsx +8 -18
- 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/date-picker/CDatePicker.tsx +12 -13
- package/src/components/date-picker/__tests__/CDatePicker.spec.tsx +1 -1
- package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +12 -640
- package/src/components/date-range-picker/CDateRangePicker.tsx +2 -0
- package/src/components/date-range-picker/__tests__/CDateRangePicker.spec.tsx +1 -1
- package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +21 -1259
- package/src/components/dropdown/CDropdown.tsx +29 -34
- package/src/components/dropdown/CDropdownToggle.tsx +1 -1
- package/src/components/dropdown/__tests__/CDropdown.spec.tsx +56 -1
- package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +2 -2
- package/src/components/dropdown/__tests__/__snapshots__/CDropdownMenu.spec.tsx.snap +1 -1
- 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__/CFormInput.spec.tsx +17 -20
- package/src/components/form/__tests__/__snapshots__/CChipInput.spec.tsx.snap +7 -0
- package/src/components/form/__tests__/__snapshots__/CFormInput.spec.tsx.snap +12 -3
- package/src/components/grid/CContainer.tsx +3 -1
- package/src/components/header/CHeaderBrand.tsx +3 -2
- package/src/components/index.ts +2 -0
- package/src/components/link/CLink.tsx +7 -4
- package/src/components/list-group/CListGroupItem.tsx +3 -2
- package/src/components/loading-button/__tests__/CLoadingButton.spec.tsx +1 -1
- package/src/components/loading-button/__tests__/__snapshots__/CLoadingButton.spec.tsx.snap +4 -4
- 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 +27 -69
- package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +4 -5
- package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
- package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +7 -24
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +108 -61
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -4
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +7 -0
- package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +16 -9
- package/src/components/multi-select/types.ts +14 -0
- package/src/components/nav/CNav.tsx +3 -2
- package/src/components/nav/CNavGroup.tsx +196 -105
- package/src/components/nav/CNavGroupContext.ts +27 -0
- package/src/components/nav/CNavLink.tsx +26 -12
- package/src/components/nav/__tests__/CNavGroup.spec.tsx +207 -4
- package/src/components/nav/__tests__/__snapshots__/CNavGroup.spec.tsx.snap +3 -1
- package/src/components/offcanvas/__tests__/COffcanvas.spec.tsx +1 -0
- package/src/components/one-time-password-input/COneTimePassword.tsx +10 -11
- package/src/components/picker/__tests__/CPicker.spec.tsx +1 -1
- package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +2 -16
- package/src/components/popover/CPopover.tsx +71 -26
- package/src/components/popover/__tests__/CPopover.spec.tsx +85 -4
- package/src/components/progress/CProgress.tsx +1 -2
- package/src/components/rating/CRating.tsx +1 -0
- package/src/components/search-button/CSearchButton.tsx +195 -0
- package/src/components/search-button/__tests__/CSearchButton.spec.tsx +95 -0
- package/src/components/search-button/__tests__/__snapshots__/CSearchButton.spec.tsx.snap +87 -0
- package/src/components/search-button/index.ts +3 -0
- package/src/components/search-button/types.ts +10 -0
- package/src/components/search-button/utils.ts +140 -0
- package/src/components/sidebar/CSidebar.tsx +51 -26
- package/src/components/sidebar/CSidebarNav.tsx +39 -53
- package/src/components/sidebar/__tests__/CSidebar.spec.tsx +26 -0
- package/src/components/smart-table/CSmartTable.tsx +5 -4
- package/src/components/smart-table/CSmartTableInterface.tsx +2 -2
- package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +3 -2
- package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +7 -15
- package/src/components/stepper/__tests__/CStepper.spec.tsx +24 -21
- package/src/components/stepper/__tests__/__snapshots__/CStepper.spec.tsx.snap +295 -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/tabs/__tests__/CTabContent.spec.tsx +1 -0
- package/src/components/tabs/__tests__/CTabPane.spec.tsx +1 -0
- package/src/components/time-picker/CTimePicker.tsx +6 -7
- package/src/components/time-picker/__tests__/CTimePicker.spec.tsx +10 -1
- package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +599 -315
- package/src/components/tooltip/CTooltip.tsx +72 -27
- package/src/components/tooltip/__tests__/CTooltip.spec.tsx +102 -1
- package/src/components/virtual-scroller/CVirtualScroller.tsx +13 -14
- package/src/helpers/polymorphicComponent.ts +1 -1
- package/src/hooks/useColorModes.ts +2 -2
- package/src/hooks/useDebouncedCallback.ts +7 -4
- 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/accordion/CAccordionCollapse.d.ts +0 -3
- 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/accordion/CAccordionCollapse.d.ts +0 -3
- 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/accordion/CAccordionCollapse.tsx +0 -20
- package/src/components/accordion/__tests__/CAccordionCollapse.spec.tsx +0 -10
- package/src/components/accordion/__tests__/__snapshots__/CAccordionCollapse.spec.tsx.snap +0 -11
- package/src/components/button/__tests__/__snapshots__/CButtonClose.spec.tsx.snap +0 -26
- package/src/components/calendar/__tests__/CCalendar.accessibility.spec.tsx +0 -595
- package/src/components/calendar/__tests__/CCalendar.comprehensive.spec.tsx +0 -402
- package/src/components/calendar/__tests__/CCalendar.edge-cases.spec.tsx +0 -416
- package/src/components/calendar/__tests__/CCalendar.interactions.spec.tsx +0 -593
- package/src/components/header/CHeaderBrand.tsx~HEAD +0 -36
- package/src/components/sidebar/CSidebarNavContext.ts +0 -8
- /package/src/components/calendar/__tests__/{test-setup.ts → setup.ts} +0 -0
|
@@ -30,7 +30,14 @@ import {
|
|
|
30
30
|
isGlobalSearch,
|
|
31
31
|
selectOptions,
|
|
32
32
|
} from './utils'
|
|
33
|
-
import type {
|
|
33
|
+
import type {
|
|
34
|
+
Option,
|
|
35
|
+
OptionsGroup,
|
|
36
|
+
Search,
|
|
37
|
+
SelectedOption,
|
|
38
|
+
SelectionActions,
|
|
39
|
+
SelectionState,
|
|
40
|
+
} from './types'
|
|
34
41
|
|
|
35
42
|
export interface CMultiSelectProps
|
|
36
43
|
extends Omit<CFormControlWrapperProps, 'floatingClassName' | 'floatingLabel'>,
|
|
@@ -53,6 +60,18 @@ export interface CMultiSelectProps
|
|
|
53
60
|
* @since 5.19.0
|
|
54
61
|
*/
|
|
55
62
|
ariaIndicatorLabel?: string
|
|
63
|
+
/**
|
|
64
|
+
* Accessible label for the search input (when `search` is enabled).
|
|
65
|
+
*
|
|
66
|
+
* @since 5.26.0
|
|
67
|
+
*/
|
|
68
|
+
ariaSearchLabel?: string
|
|
69
|
+
/**
|
|
70
|
+
* Accessible label prefix for a tag's delete button (selection type `tags`). The selected option's label is appended, so screen readers announce e.g. "Remove Angular".
|
|
71
|
+
*
|
|
72
|
+
* @since 5.26.0
|
|
73
|
+
*/
|
|
74
|
+
ariaTagDeleteLabel?: string
|
|
56
75
|
/**
|
|
57
76
|
* A string of all className you want applied to the base component.
|
|
58
77
|
*/
|
|
@@ -77,6 +96,12 @@ export interface CMultiSelectProps
|
|
|
77
96
|
* Toggle the disabled state for the component.
|
|
78
97
|
*/
|
|
79
98
|
disabled?: boolean
|
|
99
|
+
/**
|
|
100
|
+
* Render a custom dropdown header (the area above the options list), replacing the built-in select all button. Receives a `state` object (`{ selected, total, filtered, filteredSelected }`) and an `actions` object (`{ selectAll, deselectAll, selectFiltered, deselectFiltered }`) so you can wire your own controls. Renders independently of `selectAll`.
|
|
101
|
+
*
|
|
102
|
+
* @since 5.26.0
|
|
103
|
+
*/
|
|
104
|
+
headerTemplate?: (state: SelectionState, actions: SelectionActions) => ReactNode
|
|
80
105
|
/**
|
|
81
106
|
* Set the id attribute for the native select element.
|
|
82
107
|
*
|
|
@@ -114,6 +139,12 @@ export interface CMultiSelectProps
|
|
|
114
139
|
* The callback is fired when the Multi Select component requests to be hidden.
|
|
115
140
|
*/
|
|
116
141
|
onHide?: () => void
|
|
142
|
+
/**
|
|
143
|
+
* Execute a function when the user tries to select more options than allowed by `selectionLimit`.
|
|
144
|
+
*
|
|
145
|
+
* @since 5.26.0
|
|
146
|
+
*/
|
|
147
|
+
onSelectionLimit?: (selectionLimit: number) => void
|
|
117
148
|
/**
|
|
118
149
|
* The callback is fired when the Multi Select component requests to be shown.
|
|
119
150
|
*/
|
|
@@ -136,6 +167,18 @@ export interface CMultiSelectProps
|
|
|
136
167
|
* @since 4.12.0
|
|
137
168
|
*/
|
|
138
169
|
optionsTemplate?: (option: Option) => ReactNode
|
|
170
|
+
/**
|
|
171
|
+
* Makes each options group label a toggle that selects or deselects all options in that group. With `optionsGroupsStyle="checkbox"` (and `multiple`) the label shows a tri-state checkbox indicator (`none` / `all` / `indeterminate`) reflecting the group's selection.
|
|
172
|
+
*
|
|
173
|
+
* @since 5.26.0
|
|
174
|
+
*/
|
|
175
|
+
optionsGroupsSelectable?: boolean
|
|
176
|
+
/**
|
|
177
|
+
* Sets the options group label style when `optionsGroupsSelectable` is enabled.
|
|
178
|
+
*
|
|
179
|
+
* @since 5.26.0
|
|
180
|
+
*/
|
|
181
|
+
optionsGroupsStyle?: 'checkbox' | 'text'
|
|
139
182
|
/**
|
|
140
183
|
* Custom template for options groups.
|
|
141
184
|
*
|
|
@@ -175,6 +218,18 @@ export interface CMultiSelectProps
|
|
|
175
218
|
* Sets the label for no results when filtering.
|
|
176
219
|
*/
|
|
177
220
|
searchNoResultsLabel?: string | ReactNode
|
|
221
|
+
/**
|
|
222
|
+
* Sets the select all button label shown once everything is selected. The button is a toggle: it shows `selectAllLabel` (and selects all) until everything is selected, then shows `deselectAllLabel` (and deselects all).
|
|
223
|
+
*
|
|
224
|
+
* @since 5.26.0
|
|
225
|
+
*/
|
|
226
|
+
deselectAllLabel?: string | ReactNode
|
|
227
|
+
/**
|
|
228
|
+
* Sets the deselect filtered button label (selection type `selectAllMode="filtered"`).
|
|
229
|
+
*
|
|
230
|
+
* @since 5.26.0
|
|
231
|
+
*/
|
|
232
|
+
deselectFilteredLabel?: string | ReactNode
|
|
178
233
|
/**
|
|
179
234
|
* Enables select all button.
|
|
180
235
|
*/
|
|
@@ -183,6 +238,30 @@ export interface CMultiSelectProps
|
|
|
183
238
|
* Sets the select all button label.
|
|
184
239
|
*/
|
|
185
240
|
selectAllLabel?: string | ReactNode
|
|
241
|
+
/**
|
|
242
|
+
* Determines what the select all button operates on: all options (`'all'`) or only the currently filtered (search-visible) options (`'filtered'`).
|
|
243
|
+
*
|
|
244
|
+
* @since 5.26.0
|
|
245
|
+
*/
|
|
246
|
+
selectAllMode?: 'all' | 'filtered'
|
|
247
|
+
/**
|
|
248
|
+
* Sets the select all button style. With `'checkbox'` (and `multiple`), the button shows a tri-state checkbox indicator (`none` / `all` / `indeterminate`) and toggles between selecting and deselecting.
|
|
249
|
+
*
|
|
250
|
+
* @since 5.26.0
|
|
251
|
+
*/
|
|
252
|
+
selectAllStyle?: 'checkbox' | 'text'
|
|
253
|
+
/**
|
|
254
|
+
* Sets the select filtered button label (used with `selectAllMode="filtered"`).
|
|
255
|
+
*
|
|
256
|
+
* @since 5.26.0
|
|
257
|
+
*/
|
|
258
|
+
selectFilteredLabel?: string | ReactNode
|
|
259
|
+
/**
|
|
260
|
+
* Sets the maximum number of options that can be selected. The select all button stays enabled and selects options up to the limit, then toggles to deselect all once the limit is reached. The `onSelectionLimit` callback fires when a user tries to select more options than allowed.
|
|
261
|
+
*
|
|
262
|
+
* @since 5.26.0
|
|
263
|
+
*/
|
|
264
|
+
selectionLimit?: number
|
|
186
265
|
/**
|
|
187
266
|
* Sets the selection style.
|
|
188
267
|
*/
|
|
@@ -225,14 +304,19 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
225
304
|
allowCreateOptions,
|
|
226
305
|
ariaCleanerLabel = 'Clear all selections',
|
|
227
306
|
ariaIndicatorLabel = 'Toggle visibility of options menu',
|
|
307
|
+
ariaSearchLabel = 'Search',
|
|
308
|
+
ariaTagDeleteLabel = 'Remove',
|
|
228
309
|
className,
|
|
229
310
|
cleaner = true,
|
|
230
311
|
clearSearchOnSelect,
|
|
231
312
|
container,
|
|
313
|
+
deselectAllLabel = 'Deselect all',
|
|
314
|
+
deselectFilteredLabel = 'Deselect filtered',
|
|
232
315
|
disabled,
|
|
233
316
|
feedback,
|
|
234
317
|
feedbackInvalid,
|
|
235
318
|
feedbackValid,
|
|
319
|
+
headerTemplate,
|
|
236
320
|
id,
|
|
237
321
|
invalid,
|
|
238
322
|
label,
|
|
@@ -242,11 +326,14 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
242
326
|
onChange,
|
|
243
327
|
onFilterChange,
|
|
244
328
|
onHide,
|
|
329
|
+
onSelectionLimit,
|
|
245
330
|
onShow,
|
|
246
331
|
options,
|
|
247
332
|
optionsMaxHeight = 'auto',
|
|
248
333
|
optionsStyle = 'checkbox',
|
|
249
334
|
optionsTemplate,
|
|
335
|
+
optionsGroupsSelectable = false,
|
|
336
|
+
optionsGroupsStyle = 'checkbox',
|
|
250
337
|
optionsGroupsTemplate,
|
|
251
338
|
placeholder = 'Select...',
|
|
252
339
|
portal = false,
|
|
@@ -255,7 +342,11 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
255
342
|
search = true,
|
|
256
343
|
searchNoResultsLabel = 'No results found',
|
|
257
344
|
selectAll = true,
|
|
258
|
-
selectAllLabel = 'Select all
|
|
345
|
+
selectAllLabel = 'Select all',
|
|
346
|
+
selectAllMode = 'all',
|
|
347
|
+
selectAllStyle = 'checkbox',
|
|
348
|
+
selectFilteredLabel = 'Select filtered',
|
|
349
|
+
selectionLimit,
|
|
259
350
|
selectionType = 'tags',
|
|
260
351
|
selectionTypeCounterText = 'item(s) selected',
|
|
261
352
|
size,
|
|
@@ -288,16 +379,22 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
288
379
|
const [selected, setSelected] = useState<SelectedOption[]>([])
|
|
289
380
|
const [userOptions, setUserOptions] = useState<Option[]>([])
|
|
290
381
|
|
|
291
|
-
const filteredOptions = useMemo(
|
|
292
|
-
()
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
|
|
382
|
+
const filteredOptions = useMemo(() => {
|
|
383
|
+
const source = isExternalSearch(search)
|
|
384
|
+
? [...options, ...filterOptionsList(searchValue, userOptions)]
|
|
385
|
+
: filterOptionsList(searchValue, [...options, ...userOptions])
|
|
386
|
+
|
|
387
|
+
const flattened: (Option | OptionsGroup)[] = []
|
|
388
|
+
for (const option of source) {
|
|
389
|
+
if (Array.isArray((option as OptionsGroup).options)) {
|
|
390
|
+
flattened.push(option, ...((option as OptionsGroup).options as Option[]))
|
|
391
|
+
} else {
|
|
392
|
+
flattened.push(option)
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return flattened
|
|
397
|
+
}, [options, searchValue, userOptions])
|
|
301
398
|
|
|
302
399
|
const flattenedOptions = useMemo(
|
|
303
400
|
() =>
|
|
@@ -334,15 +431,94 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
334
431
|
return searchRef.current && createOption(String(searchValue), flattenedOptions)
|
|
335
432
|
}, [filteredOptions, searchValue])
|
|
336
433
|
|
|
434
|
+
const selectableOptions = useMemo(
|
|
435
|
+
() =>
|
|
436
|
+
flattenOptionsArray([...options, ...userOptions]).filter(
|
|
437
|
+
(option): option is Option => !option.disabled
|
|
438
|
+
),
|
|
439
|
+
[options, userOptions]
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
const filteredSelectableOptions = useMemo(
|
|
443
|
+
() =>
|
|
444
|
+
flattenOptionsArray(
|
|
445
|
+
isExternalSearch(search)
|
|
446
|
+
? [...options, ...filterOptionsList(searchValue, userOptions)]
|
|
447
|
+
: filterOptionsList(searchValue, [...options, ...userOptions])
|
|
448
|
+
).filter((option): option is Option => !option.disabled),
|
|
449
|
+
[options, searchValue, userOptions]
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
const selectedValues = new Set(selected.map((option) => option.value))
|
|
453
|
+
const countSelected = (scope: Option[]) =>
|
|
454
|
+
scope.filter((option) => selectedValues.has(option.value)).length
|
|
455
|
+
|
|
456
|
+
const hasSelectionLimit = multiple && typeof selectionLimit === 'number'
|
|
457
|
+
const isSelectionLimitReached = hasSelectionLimit && selected.length >= (selectionLimit as number)
|
|
458
|
+
const selectableTarget = (total: number) =>
|
|
459
|
+
hasSelectionLimit ? Math.min(total, selectionLimit as number) : total
|
|
460
|
+
|
|
461
|
+
const selectWithLimit = (scope: Option[]) => {
|
|
462
|
+
if (!hasSelectionLimit) {
|
|
463
|
+
setSelected(selectOptions(multiple, scope, selected))
|
|
464
|
+
return
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
const remaining = (selectionLimit as number) - selected.length
|
|
468
|
+
|
|
469
|
+
if (remaining <= 0) {
|
|
470
|
+
onSelectionLimit?.(selectionLimit as number)
|
|
471
|
+
return
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const toAdd = scope.filter((option) => !selectedValues.has(option.value))
|
|
475
|
+
setSelected(selectOptions(multiple, toAdd.slice(0, remaining), selected))
|
|
476
|
+
|
|
477
|
+
if (toAdd.length > remaining) {
|
|
478
|
+
onSelectionLimit?.(selectionLimit as number)
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const selectAllScope =
|
|
483
|
+
selectAllMode === 'filtered'
|
|
484
|
+
? { selected: countSelected(filteredSelectableOptions), total: filteredSelectableOptions.length }
|
|
485
|
+
: { selected: countSelected(selectableOptions), total: selectableOptions.length }
|
|
486
|
+
|
|
487
|
+
const selectAllTarget = selectableTarget(selectAllScope.total)
|
|
488
|
+
const isAllSelected = selectAllTarget > 0 && selectAllScope.selected >= selectAllTarget
|
|
489
|
+
const selectAllCheckboxState = isAllSelected
|
|
490
|
+
? 'all'
|
|
491
|
+
: selectAllScope.selected === 0
|
|
492
|
+
? 'none'
|
|
493
|
+
: 'indeterminate'
|
|
494
|
+
const isFilteredScopeNarrowed =
|
|
495
|
+
selectAllMode === 'filtered' && filteredSelectableOptions.length < selectableOptions.length
|
|
496
|
+
const selectAllButtonLabel = isFilteredScopeNarrowed
|
|
497
|
+
? isAllSelected
|
|
498
|
+
? deselectFilteredLabel
|
|
499
|
+
: selectFilteredLabel
|
|
500
|
+
: isAllSelected
|
|
501
|
+
? deselectAllLabel
|
|
502
|
+
: selectAllLabel
|
|
503
|
+
|
|
504
|
+
const headerState: SelectionState = {
|
|
505
|
+
selected: selected.length,
|
|
506
|
+
total: selectableOptions.length,
|
|
507
|
+
filtered: filteredSelectableOptions.length,
|
|
508
|
+
filteredSelected: countSelected(filteredSelectableOptions),
|
|
509
|
+
}
|
|
510
|
+
|
|
337
511
|
useEffect(() => {
|
|
338
512
|
if (!isInitialMount.current && resetSelectionOnOptionsChange) {
|
|
339
513
|
return setSelected([])
|
|
340
514
|
}
|
|
341
515
|
|
|
342
|
-
const _selected = flattenedOptions.filter(
|
|
516
|
+
const _selected = flattenedOptions.filter(
|
|
517
|
+
(option): option is Option => option.selected === true
|
|
518
|
+
)
|
|
343
519
|
const deselected = flattenedOptions.filter(
|
|
344
|
-
(option: Option
|
|
345
|
-
)
|
|
520
|
+
(option): option is Option => option.selected === false
|
|
521
|
+
)
|
|
346
522
|
|
|
347
523
|
if (_selected.length > 0 || deselected.length > 0) {
|
|
348
524
|
setSelected(selectOptions(multiple, _selected, selected, deselected))
|
|
@@ -381,6 +557,20 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
381
557
|
return () => {
|
|
382
558
|
if (onHide) onHide()
|
|
383
559
|
|
|
560
|
+
if (isOpen) {
|
|
561
|
+
const active = document.activeElement
|
|
562
|
+
const menu = dropdownMenuElement.current as HTMLElement | null
|
|
563
|
+
const toggler = dropdownRefElement.current as HTMLElement | null
|
|
564
|
+
|
|
565
|
+
if (menu?.contains(active) || toggler?.contains(active)) {
|
|
566
|
+
if (search && searchRef.current) {
|
|
567
|
+
searchRef.current.focus()
|
|
568
|
+
} else {
|
|
569
|
+
toggler?.focus()
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
384
574
|
setSearchValue('')
|
|
385
575
|
if (searchRef.current) {
|
|
386
576
|
searchRef.current.value = ''
|
|
@@ -483,6 +673,36 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
483
673
|
}
|
|
484
674
|
}
|
|
485
675
|
|
|
676
|
+
const handleNativeSelectKeyDown = (event: React.KeyboardEvent<HTMLSelectElement>) => {
|
|
677
|
+
if (event.key === 'Tab' || event.key === 'Escape') {
|
|
678
|
+
return
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
event.preventDefault()
|
|
682
|
+
|
|
683
|
+
const isPrintable =
|
|
684
|
+
event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey
|
|
685
|
+
|
|
686
|
+
if (
|
|
687
|
+
!isOpen &&
|
|
688
|
+
(event.key === 'Enter' || event.key === 'ArrowDown' || (search && isPrintable))
|
|
689
|
+
) {
|
|
690
|
+
openDropdown()
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if (search && searchRef.current) {
|
|
694
|
+
searchRef.current.focus()
|
|
695
|
+
|
|
696
|
+
if (isPrintable) {
|
|
697
|
+
const nextValue = searchRef.current.value + event.key
|
|
698
|
+
searchRef.current.value = nextValue
|
|
699
|
+
setSearchValue(nextValue)
|
|
700
|
+
}
|
|
701
|
+
} else {
|
|
702
|
+
;(dropdownRefElement.current as HTMLElement | null)?.focus()
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
486
706
|
const handleGlobalSearch = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
487
707
|
if (
|
|
488
708
|
isGlobalSearch(search) &&
|
|
@@ -505,6 +725,13 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
505
725
|
return
|
|
506
726
|
}
|
|
507
727
|
|
|
728
|
+
const alreadySelected = selected.some((_option) => _option.value === option.value)
|
|
729
|
+
|
|
730
|
+
if (!alreadySelected && isSelectionLimitReached) {
|
|
731
|
+
onSelectionLimit?.(selectionLimit as number)
|
|
732
|
+
return
|
|
733
|
+
}
|
|
734
|
+
|
|
508
735
|
if (option.custom && !userOptions.some((_option) => _option.value === option.value)) {
|
|
509
736
|
setUserOptions([...userOptions, option])
|
|
510
737
|
}
|
|
@@ -517,7 +744,7 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
517
744
|
}
|
|
518
745
|
}
|
|
519
746
|
|
|
520
|
-
if (
|
|
747
|
+
if (alreadySelected) {
|
|
521
748
|
setSelected(selected.filter((_option) => _option.value !== option.value))
|
|
522
749
|
} else {
|
|
523
750
|
setSelected([...selected, option] as SelectedOption[])
|
|
@@ -525,19 +752,52 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
525
752
|
}
|
|
526
753
|
|
|
527
754
|
const handleSelectAll = () => {
|
|
528
|
-
|
|
529
|
-
selectOptions(
|
|
530
|
-
multiple,
|
|
531
|
-
[...flattenedOptions.filter((option: Option) => !option.disabled), ...userOptions],
|
|
532
|
-
selected
|
|
533
|
-
)
|
|
534
|
-
)
|
|
755
|
+
selectWithLimit(selectableOptions)
|
|
535
756
|
}
|
|
536
757
|
|
|
537
758
|
const handleDeselectAll = () => {
|
|
538
759
|
setSelected(selected.filter((option) => option.disabled))
|
|
539
760
|
}
|
|
540
761
|
|
|
762
|
+
const handleSelectFiltered = () => {
|
|
763
|
+
selectWithLimit(filteredSelectableOptions)
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
const handleDeselectFiltered = () => {
|
|
767
|
+
const filteredValues = new Set(filteredSelectableOptions.map((option) => option.value))
|
|
768
|
+
setSelected(
|
|
769
|
+
selected.filter((option) => option.disabled || !filteredValues.has(option.value))
|
|
770
|
+
)
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
const handleSelectAllToggle = () => {
|
|
774
|
+
if (selectAllMode === 'filtered') {
|
|
775
|
+
isAllSelected ? handleDeselectFiltered() : handleSelectFiltered()
|
|
776
|
+
} else {
|
|
777
|
+
isAllSelected ? handleDeselectAll() : handleSelectAll()
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const handleGroupClick = (group: OptionsGroup) => {
|
|
782
|
+
const groupOptions = (group.options ?? []).filter((option) => !option.disabled)
|
|
783
|
+
const allSelected =
|
|
784
|
+
groupOptions.length > 0 && groupOptions.every((option) => selectedValues.has(option.value))
|
|
785
|
+
|
|
786
|
+
if (allSelected) {
|
|
787
|
+
const groupValues = new Set(groupOptions.map((option) => option.value))
|
|
788
|
+
setSelected(selected.filter((option) => option.disabled || !groupValues.has(option.value)))
|
|
789
|
+
} else {
|
|
790
|
+
selectWithLimit(groupOptions)
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
const headerActions: SelectionActions = {
|
|
795
|
+
selectAll: handleSelectAll,
|
|
796
|
+
deselectAll: handleDeselectAll,
|
|
797
|
+
selectFiltered: handleSelectFiltered,
|
|
798
|
+
deselectFiltered: handleDeselectFiltered,
|
|
799
|
+
}
|
|
800
|
+
|
|
541
801
|
return (
|
|
542
802
|
<CFormControlWrapper
|
|
543
803
|
describedby={rest['aria-describedby']}
|
|
@@ -551,20 +811,6 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
551
811
|
tooltipFeedback={tooltipFeedback}
|
|
552
812
|
valid={valid}
|
|
553
813
|
>
|
|
554
|
-
<CMultiSelectNativeSelect
|
|
555
|
-
id={id ?? uniqueId}
|
|
556
|
-
multiple={multiple}
|
|
557
|
-
name={name ?? uniqueId}
|
|
558
|
-
options={selected}
|
|
559
|
-
required={required}
|
|
560
|
-
value={
|
|
561
|
-
multiple
|
|
562
|
-
? selected.map((option: SelectedOption) => option.value.toString())
|
|
563
|
-
: selected.map((option: SelectedOption) => option.value)[0]
|
|
564
|
-
}
|
|
565
|
-
onChange={() => onChange && onChange(selected)}
|
|
566
|
-
ref={nativeSelectRef}
|
|
567
|
-
/>
|
|
568
814
|
<div
|
|
569
815
|
className={classNames(
|
|
570
816
|
'form-multi-select',
|
|
@@ -578,9 +824,23 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
578
824
|
className
|
|
579
825
|
)}
|
|
580
826
|
onKeyDown={handleGlobalSearch}
|
|
581
|
-
aria-expanded={isOpen}
|
|
582
827
|
ref={ref}
|
|
583
828
|
>
|
|
829
|
+
<CMultiSelectNativeSelect
|
|
830
|
+
id={id ?? uniqueId}
|
|
831
|
+
multiple={multiple}
|
|
832
|
+
name={name ?? uniqueId}
|
|
833
|
+
options={selected}
|
|
834
|
+
required={required}
|
|
835
|
+
value={
|
|
836
|
+
multiple
|
|
837
|
+
? selected.map((option: SelectedOption) => option.value.toString())
|
|
838
|
+
: selected.map((option: SelectedOption) => option.value)[0]
|
|
839
|
+
}
|
|
840
|
+
onChange={() => onChange && onChange(selected)}
|
|
841
|
+
onKeyDown={handleNativeSelectKeyDown}
|
|
842
|
+
ref={nativeSelectRef}
|
|
843
|
+
/>
|
|
584
844
|
<div
|
|
585
845
|
className="form-multi-select-input-group"
|
|
586
846
|
{...(!search && !disabled && { tabIndex: 0 })}
|
|
@@ -589,10 +849,13 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
589
849
|
role="combobox"
|
|
590
850
|
aria-haspopup="listbox"
|
|
591
851
|
aria-expanded={isOpen}
|
|
852
|
+
aria-controls={`multiselect-listbox-${uniqueId}`}
|
|
592
853
|
{...(portal && { 'aria-owns': `multiselect-listbox-${uniqueId}` })}
|
|
854
|
+
{...(disabled && { 'aria-disabled': true })}
|
|
593
855
|
ref={dropdownRefElement}
|
|
594
856
|
>
|
|
595
857
|
<CMultiSelectSelection
|
|
858
|
+
ariaTagDeleteLabel={ariaTagDeleteLabel}
|
|
596
859
|
disabled={disabled}
|
|
597
860
|
multiple={multiple}
|
|
598
861
|
onRemove={(option) => !disabled && handleOnOptionClick(option)}
|
|
@@ -610,6 +873,9 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
610
873
|
id={`search${id ?? uniqueId}`}
|
|
611
874
|
name={`search${name ?? uniqueId}`}
|
|
612
875
|
autoComplete="off"
|
|
876
|
+
aria-label={ariaSearchLabel}
|
|
877
|
+
aria-autocomplete="list"
|
|
878
|
+
aria-controls={`multiselect-listbox-${uniqueId}`}
|
|
613
879
|
onChange={handleSearchChange}
|
|
614
880
|
onKeyDown={handleSearchKeyDown}
|
|
615
881
|
{...(selected.length === 0 && { placeholder: placeholder })}
|
|
@@ -665,23 +931,40 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
|
|
|
665
931
|
aria-multiselectable={multiple}
|
|
666
932
|
ref={dropdownMenuElement}
|
|
667
933
|
>
|
|
668
|
-
{multiple && selectAll && (
|
|
669
|
-
<
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
934
|
+
{(headerTemplate || (multiple && selectAll)) && (
|
|
935
|
+
<div className="form-multi-select-dropdown-header">
|
|
936
|
+
{headerTemplate ? (
|
|
937
|
+
<div onClick={(event) => event.stopPropagation()}>
|
|
938
|
+
{headerTemplate(headerState, headerActions)}
|
|
939
|
+
</div>
|
|
940
|
+
) : (
|
|
941
|
+
<button
|
|
942
|
+
type="button"
|
|
943
|
+
className={classNames('form-multi-select-all', {
|
|
944
|
+
'form-multi-select-all-with-checkbox': selectAllStyle === 'checkbox',
|
|
945
|
+
'form-multi-selected':
|
|
946
|
+
selectAllStyle === 'checkbox' && selectAllCheckboxState === 'all',
|
|
947
|
+
'form-multi-select-indeterminate':
|
|
948
|
+
selectAllStyle === 'checkbox' && selectAllCheckboxState === 'indeterminate',
|
|
949
|
+
})}
|
|
950
|
+
onClick={() => handleSelectAllToggle()}
|
|
951
|
+
>
|
|
952
|
+
{selectAllButtonLabel}
|
|
953
|
+
</button>
|
|
954
|
+
)}
|
|
955
|
+
</div>
|
|
676
956
|
)}
|
|
677
957
|
<CMultiSelectOptions
|
|
678
958
|
loading={loading}
|
|
959
|
+
onGroupOnClick={(group) => !disabled && handleGroupClick(group)}
|
|
679
960
|
onOptionOnClick={(option) => !disabled && handleOnOptionClick(option)}
|
|
680
961
|
options={
|
|
681
962
|
filteredOptions.length === 0 && allowCreateOptions
|
|
682
963
|
? userOption || []
|
|
683
964
|
: filteredOptions
|
|
684
965
|
}
|
|
966
|
+
optionsGroupsSelectable={optionsGroupsSelectable && multiple}
|
|
967
|
+
optionsGroupsStyle={optionsGroupsStyle}
|
|
685
968
|
optionsMaxHeight={optionsMaxHeight}
|
|
686
969
|
optionsStyle={optionsStyle}
|
|
687
970
|
optionsTemplate={optionsTemplate}
|
|
@@ -703,22 +986,30 @@ CMultiSelect.propTypes = {
|
|
|
703
986
|
allowCreateOptions: PropTypes.bool,
|
|
704
987
|
ariaCleanerLabel: PropTypes.string,
|
|
705
988
|
ariaIndicatorLabel: PropTypes.string,
|
|
989
|
+
ariaSearchLabel: PropTypes.string,
|
|
990
|
+
ariaTagDeleteLabel: PropTypes.string,
|
|
706
991
|
className: PropTypes.string,
|
|
707
992
|
cleaner: PropTypes.bool,
|
|
708
993
|
clearSearchOnSelect: PropTypes.bool,
|
|
709
994
|
container: PropTypes.any,
|
|
995
|
+
deselectAllLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
996
|
+
deselectFilteredLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
710
997
|
disabled: PropTypes.bool,
|
|
998
|
+
headerTemplate: PropTypes.func,
|
|
711
999
|
loading: PropTypes.bool,
|
|
712
1000
|
multiple: PropTypes.bool,
|
|
713
1001
|
name: PropTypes.string,
|
|
714
1002
|
onChange: PropTypes.func,
|
|
715
1003
|
onFilterChange: PropTypes.func,
|
|
716
1004
|
onHide: PropTypes.func,
|
|
1005
|
+
onSelectionLimit: PropTypes.func,
|
|
717
1006
|
onShow: PropTypes.func,
|
|
718
1007
|
options: PropTypes.array.isRequired,
|
|
719
1008
|
optionsMaxHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
720
1009
|
optionsStyle: PropTypes.oneOf(['checkbox', 'text']),
|
|
721
1010
|
optionsTemplate: PropTypes.func,
|
|
1011
|
+
optionsGroupsSelectable: PropTypes.bool,
|
|
1012
|
+
optionsGroupsStyle: PropTypes.oneOf(['checkbox', 'text']),
|
|
722
1013
|
optionsGroupsTemplate: PropTypes.func,
|
|
723
1014
|
placeholder: PropTypes.string,
|
|
724
1015
|
portal: PropTypes.bool,
|
|
@@ -735,6 +1026,10 @@ CMultiSelect.propTypes = {
|
|
|
735
1026
|
searchNoResultsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
736
1027
|
selectAll: PropTypes.bool,
|
|
737
1028
|
selectAllLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
1029
|
+
selectAllMode: PropTypes.oneOf(['all', 'filtered']),
|
|
1030
|
+
selectAllStyle: PropTypes.oneOf(['checkbox', 'text']),
|
|
1031
|
+
selectFilteredLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
1032
|
+
selectionLimit: PropTypes.number,
|
|
738
1033
|
selectionType: PropTypes.oneOf(['counter', 'tags', 'text']),
|
|
739
1034
|
selectionTypeCounterText: PropTypes.string,
|
|
740
1035
|
size: PropTypes.oneOf(['sm', 'lg']),
|
|
@@ -29,11 +29,11 @@ export const CMultiSelectNativeSelect = forwardRef<
|
|
|
29
29
|
>(({ id, name, options, ...rest }, ref) => {
|
|
30
30
|
return (
|
|
31
31
|
<select
|
|
32
|
+
className="form-multi-select"
|
|
32
33
|
id={id}
|
|
33
34
|
{...(id && !name && { name: `${id}-multi-select` })} // TODO: remove in v6
|
|
34
35
|
{...(name && { name: name })}
|
|
35
36
|
tabIndex={-1}
|
|
36
|
-
style={{ display: 'none' }}
|
|
37
37
|
{...rest}
|
|
38
38
|
ref={ref}
|
|
39
39
|
>
|