@coreui/react-pro 5.17.0 → 5.18.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/accordion/CAccordionButton.js.map +1 -1
- package/dist/cjs/components/accordion/CAccordionCollapse.d.ts +3 -0
- package/dist/cjs/components/accordion/CAccordionItem.js.map +1 -1
- package/dist/cjs/components/alert/CAlert.js +1 -5
- package/dist/cjs/components/alert/CAlert.js.map +1 -1
- package/dist/cjs/components/autocomplete/CAutocomplete.d.ts +229 -0
- package/dist/cjs/components/autocomplete/CAutocomplete.js +293 -0
- package/dist/cjs/components/autocomplete/CAutocomplete.js.map +1 -0
- package/dist/cjs/components/autocomplete/CAutocompleteOptions.d.ts +17 -0
- package/dist/cjs/components/autocomplete/CAutocompleteOptions.js +72 -0
- package/dist/cjs/components/autocomplete/CAutocompleteOptions.js.map +1 -0
- package/dist/cjs/components/autocomplete/index.d.ts +2 -0
- package/dist/cjs/components/autocomplete/types.d.ts +18 -0
- package/dist/cjs/components/autocomplete/utils.d.ts +11 -0
- package/dist/cjs/components/autocomplete/utils.js +107 -0
- package/dist/cjs/components/autocomplete/utils.js.map +1 -0
- package/dist/cjs/components/backdrop/CBackdrop.js +1 -5
- package/dist/cjs/components/backdrop/CBackdrop.js.map +1 -1
- package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
- package/dist/cjs/components/calendar/CCalendarNavigation.js.map +1 -1
- package/dist/cjs/components/calendar/CCalendarPanel.js +6 -7
- package/dist/cjs/components/calendar/CCalendarPanel.js.map +1 -1
- package/dist/cjs/components/calendar/utils.d.ts +30 -5
- package/dist/cjs/components/calendar/utils.js +20 -9
- package/dist/cjs/components/calendar/utils.js.map +1 -1
- package/dist/cjs/components/carousel/CCarousel.js.map +1 -1
- package/dist/cjs/components/carousel/CCarouselItem.js.map +1 -1
- package/dist/cjs/components/collapse/CCollapse.js +1 -5
- package/dist/cjs/components/collapse/CCollapse.js.map +1 -1
- package/dist/cjs/components/conditional-portal/CConditionalPortal.js.map +1 -1
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js +10 -6
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/cjs/components/date-range-picker/utils.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdown.js +70 -56
- package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdownContext.d.ts +3 -2
- package/dist/cjs/components/dropdown/CDropdownMenu.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdownToggle.js +18 -16
- package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/cjs/components/dropdown/utils.js.map +1 -1
- package/dist/cjs/components/element-cover/CElementCover.js.map +1 -1
- package/dist/cjs/components/form/CFormCheck.js.map +1 -1
- package/dist/cjs/components/form/CFormControlWrapper.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/grid/CCol.js.map +1 -1
- package/dist/cjs/components/grid/CContainer.js.map +1 -1
- package/dist/cjs/components/grid/CRow.js.map +1 -1
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/link/CLink.js.map +1 -1
- package/dist/cjs/components/loading-button/CLoadingButton.js.map +1 -1
- package/dist/cjs/components/modal/CModal.js +1 -5
- package/dist/cjs/components/modal/CModal.js.map +1 -1
- package/dist/cjs/components/modal/CModalHeader.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelect.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectOptions.js.map +1 -1
- package/dist/cjs/components/multi-select/CMultiSelectSelection.js.map +1 -1
- package/dist/cjs/components/multi-select/utils.js.map +1 -1
- package/dist/cjs/components/nav/CNavGroup.js +1 -5
- package/dist/cjs/components/nav/CNavGroup.js.map +1 -1
- package/dist/cjs/components/nav/CNavLink.js.map +1 -1
- package/dist/cjs/components/offcanvas/COffcanvas.js +1 -5
- package/dist/cjs/components/offcanvas/COffcanvas.js.map +1 -1
- package/dist/cjs/components/password-input/CPasswordInput.js.map +1 -1
- package/dist/cjs/components/picker/CPicker.js.map +1 -1
- package/dist/cjs/components/placeholder/CPlaceholder.js.map +1 -1
- package/dist/cjs/components/popover/CPopover.js.map +1 -1
- package/dist/cjs/components/progress/CProgress.js.map +1 -1
- package/dist/cjs/components/range-slider/CRangeSlider.js.map +1 -1
- package/dist/cjs/components/range-slider/utils.js.map +1 -1
- package/dist/cjs/components/rating/CRating.js.map +1 -1
- package/dist/cjs/components/sidebar/CSidebar.js.map +1 -1
- package/dist/cjs/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/cjs/components/smart-pagination/CSmartPagination.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableBody.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableFilter.d.ts +8 -0
- package/dist/cjs/components/smart-table/CSmartTableHead.js.map +1 -1
- package/dist/cjs/components/smart-table/CSmartTableItemsPerPageSelector.d.ts +8 -0
- package/dist/cjs/components/smart-table/utils.js.map +1 -1
- package/dist/cjs/components/stepper/CStepper.js.map +1 -1
- package/dist/cjs/components/table/CTable.js.map +1 -1
- package/dist/cjs/components/table/utils.js.map +1 -1
- package/dist/cjs/components/tabs/CTab.js.map +1 -1
- package/dist/cjs/components/tabs/CTabList.js.map +1 -1
- package/dist/cjs/components/tabs/CTabPane.js +1 -5
- package/dist/cjs/components/tabs/CTabPane.js.map +1 -1
- package/dist/cjs/components/tabs/CTabPanel.js +1 -5
- package/dist/cjs/components/tabs/CTabPanel.js.map +1 -1
- package/dist/cjs/components/tabs/CTabs.js.map +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.js +15 -1
- package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/cjs/components/time-picker/CTimePickerRollCol.js +2 -2
- package/dist/cjs/components/time-picker/CTimePickerRollCol.js.map +1 -1
- package/dist/cjs/components/time-picker/utils.js.map +1 -1
- package/dist/cjs/components/toast/CToast.js +1 -5
- package/dist/cjs/components/toast/CToast.js.map +1 -1
- package/dist/cjs/components/toast/CToastClose.js.map +1 -1
- package/dist/cjs/components/toast/CToaster.js.map +1 -1
- package/dist/cjs/components/tooltip/CTooltip.js.map +1 -1
- package/dist/cjs/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/cjs/components/widgets/CWidgetStatsD.js.map +1 -1
- package/dist/cjs/hooks/useClipboard.js.map +1 -1
- package/dist/cjs/hooks/useColorModes.js.map +1 -1
- package/dist/cjs/hooks/useDebounce.js.map +1 -1
- package/dist/cjs/hooks/useDebouncedCallback.js.map +1 -1
- package/dist/cjs/hooks/useDropdownWithPopper.js.map +1 -1
- package/dist/cjs/hooks/useForkedRef.js.map +1 -1
- package/dist/cjs/hooks/useIsVisible.d.ts +1 -1
- package/dist/cjs/hooks/useIsVisible.js +3 -1
- package/dist/cjs/hooks/useIsVisible.js.map +1 -1
- package/dist/cjs/hooks/usePopper.js.map +1 -1
- package/dist/cjs/hooks/useStateWithCallback.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/extends.js.map +1 -1
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -1
- package/dist/cjs/node_modules/@coreui/icons-react/dist/index.esm.js.map +1 -1
- package/dist/cjs/node_modules/classnames/index.js.map +1 -1
- package/dist/cjs/node_modules/dom-helpers/esm/removeClass.js.map +1 -1
- package/dist/cjs/node_modules/react-device-detect/dist/lib.js.map +1 -1
- package/dist/cjs/node_modules/react-transition-group/esm/CSSTransition.js.map +1 -1
- package/dist/cjs/node_modules/react-transition-group/esm/Transition.js.map +1 -1
- package/dist/cjs/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/cjs/utils/executeAfterTransition.js.map +1 -1
- package/dist/cjs/utils/getNextActiveElement.js.map +1 -1
- package/dist/cjs/utils/getNextSibling.d.ts +2 -0
- package/dist/cjs/utils/getNextSibling.js +20 -0
- package/dist/cjs/utils/getNextSibling.js.map +1 -0
- package/dist/cjs/utils/getPreviousSibling.d.ts +2 -0
- package/dist/cjs/utils/getPreviousSibling.js +19 -0
- package/dist/cjs/utils/getPreviousSibling.js.map +1 -0
- package/dist/cjs/utils/getRTLPlacement.js.map +1 -1
- package/dist/cjs/utils/getTransitionDurationFromElement.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +3 -1
- package/dist/cjs/utils/isObjectInArray.js.map +1 -1
- package/dist/cjs/utils/isRTL.js.map +1 -1
- package/dist/esm/components/accordion/CAccordionButton.js.map +1 -1
- package/dist/esm/components/accordion/CAccordionCollapse.d.ts +3 -0
- package/dist/esm/components/accordion/CAccordionItem.js.map +1 -1
- package/dist/esm/components/alert/CAlert.js +1 -5
- package/dist/esm/components/alert/CAlert.js.map +1 -1
- package/dist/esm/components/autocomplete/CAutocomplete.d.ts +229 -0
- package/dist/esm/components/autocomplete/CAutocomplete.js +291 -0
- package/dist/esm/components/autocomplete/CAutocomplete.js.map +1 -0
- package/dist/esm/components/autocomplete/CAutocompleteOptions.d.ts +17 -0
- package/dist/esm/components/autocomplete/CAutocompleteOptions.js +70 -0
- package/dist/esm/components/autocomplete/CAutocompleteOptions.js.map +1 -0
- package/dist/esm/components/autocomplete/index.d.ts +2 -0
- package/dist/esm/components/autocomplete/types.d.ts +18 -0
- package/dist/esm/components/autocomplete/utils.d.ts +11 -0
- package/dist/esm/components/autocomplete/utils.js +96 -0
- package/dist/esm/components/autocomplete/utils.js.map +1 -0
- package/dist/esm/components/backdrop/CBackdrop.js +1 -5
- package/dist/esm/components/backdrop/CBackdrop.js.map +1 -1
- package/dist/esm/components/calendar/CCalendar.js.map +1 -1
- package/dist/esm/components/calendar/CCalendarNavigation.js.map +1 -1
- package/dist/esm/components/calendar/CCalendarPanel.js +7 -8
- package/dist/esm/components/calendar/CCalendarPanel.js.map +1 -1
- package/dist/esm/components/calendar/utils.d.ts +30 -5
- package/dist/esm/components/calendar/utils.js +20 -9
- package/dist/esm/components/calendar/utils.js.map +1 -1
- package/dist/esm/components/carousel/CCarousel.js.map +1 -1
- package/dist/esm/components/carousel/CCarouselItem.js.map +1 -1
- package/dist/esm/components/collapse/CCollapse.js +1 -5
- package/dist/esm/components/collapse/CCollapse.js.map +1 -1
- package/dist/esm/components/conditional-portal/CConditionalPortal.js.map +1 -1
- package/dist/esm/components/date-range-picker/CDateRangePicker.js +10 -6
- package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/esm/components/date-range-picker/utils.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdown.js +71 -57
- package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdownContext.d.ts +3 -2
- package/dist/esm/components/dropdown/CDropdownMenu.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdownToggle.js +18 -16
- package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/esm/components/dropdown/utils.js.map +1 -1
- package/dist/esm/components/element-cover/CElementCover.js.map +1 -1
- package/dist/esm/components/form/CFormCheck.js.map +1 -1
- package/dist/esm/components/form/CFormControlWrapper.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/grid/CCol.js.map +1 -1
- package/dist/esm/components/grid/CContainer.js.map +1 -1
- package/dist/esm/components/grid/CRow.js.map +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/link/CLink.js.map +1 -1
- package/dist/esm/components/loading-button/CLoadingButton.js.map +1 -1
- package/dist/esm/components/modal/CModal.js +1 -5
- package/dist/esm/components/modal/CModal.js.map +1 -1
- package/dist/esm/components/modal/CModalHeader.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelect.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectNativeSelect.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectOptions.js.map +1 -1
- package/dist/esm/components/multi-select/CMultiSelectSelection.js.map +1 -1
- package/dist/esm/components/multi-select/utils.js.map +1 -1
- package/dist/esm/components/nav/CNavGroup.js +1 -5
- package/dist/esm/components/nav/CNavGroup.js.map +1 -1
- package/dist/esm/components/nav/CNavLink.js.map +1 -1
- package/dist/esm/components/offcanvas/COffcanvas.js +1 -5
- package/dist/esm/components/offcanvas/COffcanvas.js.map +1 -1
- package/dist/esm/components/password-input/CPasswordInput.js.map +1 -1
- package/dist/esm/components/picker/CPicker.js.map +1 -1
- package/dist/esm/components/placeholder/CPlaceholder.js.map +1 -1
- package/dist/esm/components/popover/CPopover.js.map +1 -1
- package/dist/esm/components/progress/CProgress.js.map +1 -1
- package/dist/esm/components/range-slider/CRangeSlider.js.map +1 -1
- package/dist/esm/components/range-slider/utils.js.map +1 -1
- package/dist/esm/components/rating/CRating.js.map +1 -1
- package/dist/esm/components/sidebar/CSidebar.js.map +1 -1
- package/dist/esm/components/sidebar/CSidebarNav.js.map +1 -1
- package/dist/esm/components/smart-pagination/CSmartPagination.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTable.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableBody.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableFilter.d.ts +8 -0
- package/dist/esm/components/smart-table/CSmartTableHead.js.map +1 -1
- package/dist/esm/components/smart-table/CSmartTableItemsPerPageSelector.d.ts +8 -0
- package/dist/esm/components/smart-table/utils.js.map +1 -1
- package/dist/esm/components/stepper/CStepper.js.map +1 -1
- package/dist/esm/components/table/CTable.js.map +1 -1
- package/dist/esm/components/table/utils.js.map +1 -1
- package/dist/esm/components/tabs/CTab.js.map +1 -1
- package/dist/esm/components/tabs/CTabList.js.map +1 -1
- package/dist/esm/components/tabs/CTabPane.js +1 -5
- package/dist/esm/components/tabs/CTabPane.js.map +1 -1
- package/dist/esm/components/tabs/CTabPanel.js +1 -5
- package/dist/esm/components/tabs/CTabPanel.js.map +1 -1
- package/dist/esm/components/tabs/CTabs.js.map +1 -1
- package/dist/esm/components/time-picker/CTimePicker.js +15 -1
- package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/esm/components/time-picker/CTimePickerRollCol.js +2 -2
- package/dist/esm/components/time-picker/CTimePickerRollCol.js.map +1 -1
- package/dist/esm/components/time-picker/utils.js.map +1 -1
- package/dist/esm/components/toast/CToast.js +1 -5
- package/dist/esm/components/toast/CToast.js.map +1 -1
- package/dist/esm/components/toast/CToastClose.js.map +1 -1
- package/dist/esm/components/toast/CToaster.js.map +1 -1
- package/dist/esm/components/tooltip/CTooltip.js.map +1 -1
- package/dist/esm/components/virtual-scroller/CVirtualScroller.js.map +1 -1
- package/dist/esm/components/widgets/CWidgetStatsD.js.map +1 -1
- package/dist/esm/hooks/useClipboard.js.map +1 -1
- package/dist/esm/hooks/useColorModes.js.map +1 -1
- package/dist/esm/hooks/useDebounce.js.map +1 -1
- package/dist/esm/hooks/useDebouncedCallback.js.map +1 -1
- package/dist/esm/hooks/useDropdownWithPopper.js.map +1 -1
- package/dist/esm/hooks/useForkedRef.js.map +1 -1
- package/dist/esm/hooks/useIsVisible.d.ts +1 -1
- package/dist/esm/hooks/useIsVisible.js +3 -1
- package/dist/esm/hooks/useIsVisible.js.map +1 -1
- package/dist/esm/hooks/usePopper.js.map +1 -1
- package/dist/esm/hooks/useStateWithCallback.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/extends.js.map +1 -1
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -1
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -1
- package/dist/esm/node_modules/@coreui/icons-react/dist/index.esm.js.map +1 -1
- package/dist/esm/node_modules/classnames/index.js.map +1 -1
- package/dist/esm/node_modules/dom-helpers/esm/removeClass.js.map +1 -1
- package/dist/esm/node_modules/react-device-detect/dist/lib.js.map +1 -1
- package/dist/esm/node_modules/react-transition-group/esm/CSSTransition.js.map +1 -1
- package/dist/esm/node_modules/react-transition-group/esm/Transition.js.map +1 -1
- package/dist/esm/node_modules/tslib/tslib.es6.js.map +1 -1
- package/dist/esm/utils/executeAfterTransition.js.map +1 -1
- package/dist/esm/utils/getNextActiveElement.js.map +1 -1
- package/dist/esm/utils/getNextSibling.d.ts +2 -0
- package/dist/esm/utils/getNextSibling.js +15 -0
- package/dist/esm/utils/getNextSibling.js.map +1 -0
- package/dist/esm/utils/getPreviousSibling.d.ts +2 -0
- package/dist/esm/utils/getPreviousSibling.js +15 -0
- package/dist/esm/utils/getPreviousSibling.js.map +1 -0
- package/dist/esm/utils/getRTLPlacement.js.map +1 -1
- package/dist/esm/utils/getTransitionDurationFromElement.js.map +1 -1
- package/dist/esm/utils/index.d.ts +3 -1
- package/dist/esm/utils/isObjectInArray.js.map +1 -1
- package/dist/esm/utils/isRTL.js.map +1 -1
- package/package.json +7 -7
- package/src/components/autocomplete/CAutocomplete.tsx +802 -0
- package/src/components/autocomplete/CAutocompleteOptions.tsx +165 -0
- package/src/components/autocomplete/__tests__/CAutocomplete.spec.tsx +244 -0
- package/src/components/autocomplete/__tests__/CAutocompleteOptions.spec.tsx +210 -0
- package/src/components/autocomplete/index.ts +3 -0
- package/src/components/autocomplete/types.ts +25 -0
- package/src/components/autocomplete/utils.ts +125 -0
- package/src/components/calendar/CCalendarPanel.tsx +5 -15
- package/src/components/calendar/utils.ts +50 -10
- package/src/components/date-range-picker/CDateRangePicker.tsx +11 -5
- package/src/components/dropdown/CDropdown.tsx +86 -60
- package/src/components/dropdown/CDropdownContext.ts +3 -3
- package/src/components/dropdown/CDropdownToggle.tsx +30 -28
- package/src/components/index.ts +1 -0
- package/src/components/time-picker/CTimePicker.tsx +14 -4
- package/src/components/time-picker/CTimePickerRollCol.tsx +2 -2
- package/src/hooks/useIsVisible.ts +5 -2
- package/src/utils/getNextSibling.ts +18 -0
- package/src/utils/getPreviousSibling.ts +18 -0
- package/src/utils/index.ts +4 -0
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +0 -11
- package/dist/cjs/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +0 -1
- package/dist/cjs/node_modules/react-transition-group/esm/ReplaceTransition.js +0 -143
- package/dist/cjs/node_modules/react-transition-group/esm/ReplaceTransition.js.map +0 -1
- package/dist/cjs/node_modules/react-transition-group/esm/SwitchTransition.js +0 -263
- package/dist/cjs/node_modules/react-transition-group/esm/SwitchTransition.js.map +0 -1
- package/dist/cjs/node_modules/react-transition-group/esm/TransitionGroup.js +0 -195
- package/dist/cjs/node_modules/react-transition-group/esm/TransitionGroup.js.map +0 -1
- package/dist/cjs/node_modules/react-transition-group/esm/utils/ChildMapping.js +0 -149
- package/dist/cjs/node_modules/react-transition-group/esm/utils/ChildMapping.js.map +0 -1
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +0 -7
- package/dist/esm/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +0 -1
- package/dist/esm/node_modules/react-transition-group/esm/ReplaceTransition.js +0 -139
- package/dist/esm/node_modules/react-transition-group/esm/ReplaceTransition.js.map +0 -1
- package/dist/esm/node_modules/react-transition-group/esm/SwitchTransition.js +0 -258
- package/dist/esm/node_modules/react-transition-group/esm/SwitchTransition.js.map +0 -1
- package/dist/esm/node_modules/react-transition-group/esm/TransitionGroup.js +0 -191
- package/dist/esm/node_modules/react-transition-group/esm/TransitionGroup.js.map +0 -1
- package/dist/esm/node_modules/react-transition-group/esm/utils/ChildMapping.js +0 -144
- package/dist/esm/node_modules/react-transition-group/esm/utils/ChildMapping.js.map +0 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import classNames from 'classnames'
|
|
4
|
+
|
|
5
|
+
import { CElementCover } from '../element-cover'
|
|
6
|
+
import { CVirtualScroller } from '../virtual-scroller'
|
|
7
|
+
|
|
8
|
+
import { getNextSibling, getPreviousSibling } from '../../utils'
|
|
9
|
+
|
|
10
|
+
import type { Option, OptionsGroup } from './types'
|
|
11
|
+
import { getOptionLabel, highlightSubstring, isOptionDisabled, isOptionSelected } from './utils'
|
|
12
|
+
|
|
13
|
+
export interface CAutocompleteOptionsProps extends HTMLAttributes<HTMLDivElement> {
|
|
14
|
+
highlightOptionsOnSearch?: boolean
|
|
15
|
+
loading?: boolean
|
|
16
|
+
onOptionClick?: (option: Option) => void
|
|
17
|
+
options: (Option | OptionsGroup)[]
|
|
18
|
+
optionsMaxHeight?: number | string
|
|
19
|
+
optionsTemplate?: (option: Option) => ReactNode
|
|
20
|
+
optionsGroupsTemplate?: (option: OptionsGroup) => ReactNode
|
|
21
|
+
searchNoResultsLabel?: boolean | string | ReactNode
|
|
22
|
+
searchValue?: string
|
|
23
|
+
selected: Option | null
|
|
24
|
+
virtualScroller?: boolean
|
|
25
|
+
visibleItems?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const CAutocompleteOptions = forwardRef<HTMLDivElement, CAutocompleteOptionsProps>(
|
|
29
|
+
(
|
|
30
|
+
{
|
|
31
|
+
highlightOptionsOnSearch,
|
|
32
|
+
loading,
|
|
33
|
+
onOptionClick,
|
|
34
|
+
options,
|
|
35
|
+
optionsMaxHeight,
|
|
36
|
+
optionsTemplate,
|
|
37
|
+
optionsGroupsTemplate,
|
|
38
|
+
searchNoResultsLabel,
|
|
39
|
+
searchValue,
|
|
40
|
+
selected,
|
|
41
|
+
virtualScroller,
|
|
42
|
+
visibleItems = 10,
|
|
43
|
+
},
|
|
44
|
+
ref
|
|
45
|
+
) => {
|
|
46
|
+
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>, option: Option) => {
|
|
47
|
+
if (event.code === 'Space' || event.key === 'Enter') {
|
|
48
|
+
event.preventDefault()
|
|
49
|
+
onOptionClick?.(option)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (event.key === 'Down' || event.key === 'ArrowDown') {
|
|
53
|
+
event.preventDefault()
|
|
54
|
+
const target = event.target as HTMLElement
|
|
55
|
+
const next = getNextSibling(
|
|
56
|
+
target,
|
|
57
|
+
'.autocomplete-option:not(.disabled):not(:disabled)'
|
|
58
|
+
) as HTMLElement | null
|
|
59
|
+
|
|
60
|
+
if (next) {
|
|
61
|
+
next.focus()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (event.key === 'Up' || event.key === 'ArrowUp') {
|
|
66
|
+
event.preventDefault()
|
|
67
|
+
const target = event.target as HTMLElement
|
|
68
|
+
const prev = getPreviousSibling(
|
|
69
|
+
target,
|
|
70
|
+
'.autocomplete-option:not(.disabled):not(:disabled)'
|
|
71
|
+
) as HTMLElement | null
|
|
72
|
+
|
|
73
|
+
if (prev) {
|
|
74
|
+
prev.focus()
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const createOption = (option: Option, index: number) => (
|
|
80
|
+
<div
|
|
81
|
+
className={classNames('autocomplete-option', {
|
|
82
|
+
disabled: isOptionDisabled(option),
|
|
83
|
+
selected: isOptionSelected(option, selected),
|
|
84
|
+
})}
|
|
85
|
+
key={index}
|
|
86
|
+
onClick={() => onOptionClick && onOptionClick(option as Option)}
|
|
87
|
+
onKeyDown={(event) => handleKeyDown(event, option as Option)}
|
|
88
|
+
tabIndex={0}
|
|
89
|
+
>
|
|
90
|
+
{optionsTemplate ? (
|
|
91
|
+
optionsTemplate(option as Option)
|
|
92
|
+
) : highlightOptionsOnSearch ? (
|
|
93
|
+
<div
|
|
94
|
+
dangerouslySetInnerHTML={{
|
|
95
|
+
__html: highlightSubstring(getOptionLabel(option), searchValue),
|
|
96
|
+
}}
|
|
97
|
+
></div>
|
|
98
|
+
) : (
|
|
99
|
+
getOptionLabel(option)
|
|
100
|
+
)}
|
|
101
|
+
</div>
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
const createOptions = (options: (Option | OptionsGroup)[]): JSX.Element | JSX.Element[] =>
|
|
105
|
+
options.length > 0 ? (
|
|
106
|
+
options.map((option: Option | OptionsGroup | string, index: number) =>
|
|
107
|
+
typeof option !== 'string' && 'options' in option ? (
|
|
108
|
+
<React.Fragment key={index}>
|
|
109
|
+
<div className="autocomplete-optgroup-label">
|
|
110
|
+
{optionsGroupsTemplate
|
|
111
|
+
? optionsGroupsTemplate(option as OptionsGroup)
|
|
112
|
+
: option.label}
|
|
113
|
+
</div>
|
|
114
|
+
{option.options.map((option: Option, index: number) => createOption(option, index))}
|
|
115
|
+
</React.Fragment>
|
|
116
|
+
) : (
|
|
117
|
+
createOption(option as Option, index)
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
) : (
|
|
121
|
+
<div className="autocomplete-options-empty">{searchNoResultsLabel}</div>
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<>
|
|
126
|
+
{virtualScroller ? (
|
|
127
|
+
<CVirtualScroller
|
|
128
|
+
className="autocomplete-options"
|
|
129
|
+
visibleItems={visibleItems}
|
|
130
|
+
role="listbox"
|
|
131
|
+
ref={ref}
|
|
132
|
+
>
|
|
133
|
+
{createOptions(options)}
|
|
134
|
+
</CVirtualScroller>
|
|
135
|
+
) : (
|
|
136
|
+
<div
|
|
137
|
+
className="autocomplete-options"
|
|
138
|
+
{...(optionsMaxHeight !== 'auto' && {
|
|
139
|
+
style: { maxHeight: optionsMaxHeight, overflow: 'scroll' },
|
|
140
|
+
})}
|
|
141
|
+
role="listbox"
|
|
142
|
+
ref={ref}
|
|
143
|
+
>
|
|
144
|
+
{createOptions(options)}
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
{loading && <CElementCover />}
|
|
148
|
+
</>
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
CAutocompleteOptions.propTypes = {
|
|
154
|
+
loading: PropTypes.bool,
|
|
155
|
+
onOptionClick: PropTypes.func,
|
|
156
|
+
options: PropTypes.array.isRequired,
|
|
157
|
+
optionsMaxHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
158
|
+
optionsTemplate: PropTypes.func,
|
|
159
|
+
optionsGroupsTemplate: PropTypes.func,
|
|
160
|
+
searchNoResultsLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
161
|
+
virtualScroller: PropTypes.bool,
|
|
162
|
+
visibleItems: PropTypes.number,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
CAutocompleteOptions.displayName = 'CAutocompleteOptions'
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
import { CAutocomplete } from '../CAutocomplete'
|
|
5
|
+
|
|
6
|
+
const mockOptions = [
|
|
7
|
+
{ label: 'Apple', value: 1 },
|
|
8
|
+
{ label: 'Banana', value: 2 },
|
|
9
|
+
{ label: 'Cherry', value: 3 },
|
|
10
|
+
{ label: 'Date', value: 4 },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const mockOptionsWithGroups = [
|
|
14
|
+
{
|
|
15
|
+
label: 'Fruits',
|
|
16
|
+
options: [
|
|
17
|
+
{ label: 'Apple', value: 1 },
|
|
18
|
+
{ label: 'Banana', value: 2 },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: 'Vegetables',
|
|
23
|
+
options: [
|
|
24
|
+
{ label: 'Carrot', value: 3 },
|
|
25
|
+
{ label: 'Spinach', value: 4 },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
test('loads and displays CAutocomplete component', async () => {
|
|
31
|
+
const { container } = render(<CAutocomplete options={mockOptions} />)
|
|
32
|
+
expect(container).toMatchSnapshot()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('CAutocomplete customize', async () => {
|
|
36
|
+
const { container } = render(
|
|
37
|
+
<CAutocomplete
|
|
38
|
+
className="bazinga"
|
|
39
|
+
disabled={true}
|
|
40
|
+
size="lg"
|
|
41
|
+
placeholder="Select option"
|
|
42
|
+
options={mockOptions}
|
|
43
|
+
cleaner={true}
|
|
44
|
+
indicator={true}
|
|
45
|
+
/>
|
|
46
|
+
)
|
|
47
|
+
expect(container).toMatchSnapshot()
|
|
48
|
+
expect(container.querySelector('.autocomplete')).toHaveClass('bazinga')
|
|
49
|
+
expect(container.querySelector('.autocomplete')).toHaveClass('autocomplete-lg')
|
|
50
|
+
expect(container.querySelector('.autocomplete')).toHaveClass('disabled')
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('CAutocomplete renders input with placeholder', async () => {
|
|
54
|
+
render(<CAutocomplete options={mockOptions} placeholder="Type to search..." />)
|
|
55
|
+
const input = screen.getByRole('combobox')
|
|
56
|
+
expect(input).toHaveAttribute('placeholder', 'Type to search...')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test('CAutocomplete opens dropdown on input click', async () => {
|
|
60
|
+
render(<CAutocomplete options={mockOptions} />)
|
|
61
|
+
const input = screen.getByRole('combobox')
|
|
62
|
+
|
|
63
|
+
fireEvent.click(input)
|
|
64
|
+
|
|
65
|
+
await waitFor(() => {
|
|
66
|
+
const listbox = screen.getByRole('listbox')
|
|
67
|
+
expect(listbox).toBeVisible()
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test('CAutocomplete filters options on input change', async () => {
|
|
72
|
+
render(<CAutocomplete options={mockOptions} />)
|
|
73
|
+
const input = screen.getByRole('combobox')
|
|
74
|
+
|
|
75
|
+
fireEvent.change(input, { target: { value: 'app' } })
|
|
76
|
+
|
|
77
|
+
await waitFor(() => {
|
|
78
|
+
const option = screen.getByText('Apple')
|
|
79
|
+
expect(option).toBeVisible()
|
|
80
|
+
expect(screen.queryByText('Banana')).not.toBeInTheDocument()
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
test('CAutocomplete selects option on click', async () => {
|
|
85
|
+
const onChange = jest.fn()
|
|
86
|
+
render(<CAutocomplete options={mockOptions} onChange={onChange} />)
|
|
87
|
+
|
|
88
|
+
const input = screen.getByRole('combobox')
|
|
89
|
+
fireEvent.click(input)
|
|
90
|
+
|
|
91
|
+
await waitFor(() => {
|
|
92
|
+
const option = screen.getByText('Apple')
|
|
93
|
+
fireEvent.click(option)
|
|
94
|
+
expect(onChange).toHaveBeenCalledWith(mockOptions[0])
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
test('CAutocomplete selects option on Enter key', async () => {
|
|
99
|
+
const onChange = jest.fn()
|
|
100
|
+
render(<CAutocomplete options={mockOptions} onChange={onChange} />)
|
|
101
|
+
|
|
102
|
+
const input = screen.getByRole('combobox')
|
|
103
|
+
fireEvent.change(input, { target: { value: 'Apple' } })
|
|
104
|
+
fireEvent.keyDown(input, { key: 'Enter' })
|
|
105
|
+
|
|
106
|
+
expect(onChange).toHaveBeenCalledWith(mockOptions[0])
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('CAutocomplete closes dropdown on Escape key', async () => {
|
|
110
|
+
render(<CAutocomplete options={mockOptions} />)
|
|
111
|
+
const input = screen.getByRole('combobox')
|
|
112
|
+
|
|
113
|
+
fireEvent.click(input)
|
|
114
|
+
|
|
115
|
+
await waitFor(() => {
|
|
116
|
+
expect(screen.getByRole('listbox')).toBeVisible()
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
fireEvent.keyDown(input, { key: 'Escape' })
|
|
120
|
+
|
|
121
|
+
await waitFor(() => {
|
|
122
|
+
expect(input).toHaveAttribute('aria-expanded', 'false')
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('CAutocomplete navigates options with arrow keys', async () => {
|
|
127
|
+
render(<CAutocomplete options={mockOptions} />)
|
|
128
|
+
const input = screen.getByRole('combobox')
|
|
129
|
+
|
|
130
|
+
fireEvent.click(input)
|
|
131
|
+
|
|
132
|
+
await waitFor(() => {
|
|
133
|
+
expect(screen.getByRole('listbox')).toBeVisible()
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
fireEvent.keyDown(input, { key: 'ArrowDown' })
|
|
137
|
+
|
|
138
|
+
const firstOption = screen.getByText('Apple')
|
|
139
|
+
expect(firstOption).toHaveFocus()
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('CAutocomplete shows cleaner button when option selected', async () => {
|
|
143
|
+
render(<CAutocomplete options={mockOptions} cleaner={true} value={1} />)
|
|
144
|
+
|
|
145
|
+
const cleanerButton = screen.getByRole('button', { name: '' })
|
|
146
|
+
expect(cleanerButton).toHaveClass('autocomplete-cleaner')
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test('CAutocomplete clears selection when cleaner clicked', async () => {
|
|
150
|
+
const onChange = jest.fn()
|
|
151
|
+
render(<CAutocomplete options={mockOptions} cleaner={true} value={1} onChange={onChange} />)
|
|
152
|
+
|
|
153
|
+
const cleanerButton = screen.getByRole('button', { name: '' })
|
|
154
|
+
fireEvent.click(cleanerButton)
|
|
155
|
+
|
|
156
|
+
expect(onChange).toHaveBeenCalledWith(undefined)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
test('CAutocomplete shows no results message', async () => {
|
|
160
|
+
render(<CAutocomplete options={mockOptions} searchNoResultsLabel="No options found" />)
|
|
161
|
+
|
|
162
|
+
const input = screen.getByRole('combobox')
|
|
163
|
+
fireEvent.change(input, { target: { value: 'xyz' } })
|
|
164
|
+
|
|
165
|
+
await waitFor(() => {
|
|
166
|
+
expect(screen.getByText('No options found')).toBeVisible()
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
test('CAutocomplete renders option groups', async () => {
|
|
171
|
+
render(<CAutocomplete options={mockOptionsWithGroups} />)
|
|
172
|
+
|
|
173
|
+
const input = screen.getByRole('combobox')
|
|
174
|
+
fireEvent.click(input)
|
|
175
|
+
|
|
176
|
+
await waitFor(() => {
|
|
177
|
+
expect(screen.getByText('Fruits')).toBeVisible()
|
|
178
|
+
expect(screen.getByText('Vegetables')).toBeVisible()
|
|
179
|
+
expect(screen.getByText('Apple')).toBeVisible()
|
|
180
|
+
expect(screen.getByText('Carrot')).toBeVisible()
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
test('CAutocomplete shows hint when enabled', async () => {
|
|
185
|
+
render(<CAutocomplete options={mockOptions} showHints={true} />)
|
|
186
|
+
|
|
187
|
+
const input = screen.getByRole('combobox')
|
|
188
|
+
fireEvent.change(input, { target: { value: 'ap' } })
|
|
189
|
+
|
|
190
|
+
await waitFor(() => {
|
|
191
|
+
const hintInput = screen.getByDisplayValue('apple')
|
|
192
|
+
expect(hintInput).toHaveClass('autocomplete-selection-hint')
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
test('CAutocomplete allows custom values when allowOnlyDefinedOptions is false', async () => {
|
|
197
|
+
const onChange = jest.fn()
|
|
198
|
+
render(
|
|
199
|
+
<CAutocomplete options={mockOptions} onChange={onChange} allowOnlyDefinedOptions={false} />
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
const input = screen.getByRole('combobox')
|
|
203
|
+
fireEvent.change(input, { target: { value: 'Custom Value' } })
|
|
204
|
+
fireEvent.keyDown(input, { key: 'Enter' })
|
|
205
|
+
|
|
206
|
+
expect(onChange).toHaveBeenCalledWith('Custom Value')
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
test('CAutocomplete prevents custom values when allowOnlyDefinedOptions is true', async () => {
|
|
210
|
+
const onChange = jest.fn()
|
|
211
|
+
render(<CAutocomplete options={mockOptions} onChange={onChange} allowOnlyDefinedOptions={true} />)
|
|
212
|
+
|
|
213
|
+
const input = screen.getByRole('combobox')
|
|
214
|
+
fireEvent.change(input, { target: { value: 'Custom Value' } })
|
|
215
|
+
fireEvent.keyDown(input, { key: 'Enter' })
|
|
216
|
+
|
|
217
|
+
expect(onChange).not.toHaveBeenCalled()
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
test('CAutocomplete highlights search matches', async () => {
|
|
221
|
+
render(<CAutocomplete options={mockOptions} highlightOptionsOnSearch={true} />)
|
|
222
|
+
|
|
223
|
+
const input = screen.getByRole('combobox')
|
|
224
|
+
fireEvent.change(input, { target: { value: 'app' } })
|
|
225
|
+
|
|
226
|
+
await waitFor(() => {
|
|
227
|
+
const option = screen.getByText('Apple')
|
|
228
|
+
expect(option.closest('.autocomplete-option')).toBeInTheDocument()
|
|
229
|
+
})
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
test('CAutocomplete is disabled when disabled prop is true', async () => {
|
|
233
|
+
render(<CAutocomplete options={mockOptions} disabled={true} />)
|
|
234
|
+
|
|
235
|
+
const input = screen.getByRole('combobox')
|
|
236
|
+
expect(input).toBeDisabled()
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test('CAutocomplete is readonly when readOnly prop is true', async () => {
|
|
240
|
+
render(<CAutocomplete options={mockOptions} readOnly={true} />)
|
|
241
|
+
|
|
242
|
+
const input = screen.getByRole('combobox')
|
|
243
|
+
expect(input).toHaveAttribute('readonly')
|
|
244
|
+
})
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { render, screen, fireEvent } from '@testing-library/react'
|
|
3
|
+
import '@testing-library/jest-dom'
|
|
4
|
+
import { CAutocompleteOptions } from '../CAutocompleteOptions'
|
|
5
|
+
|
|
6
|
+
const mockOptions = [
|
|
7
|
+
{ label: 'Apple', value: 1 },
|
|
8
|
+
{ label: 'Banana', value: 2 },
|
|
9
|
+
{ label: 'Cherry', value: 3 },
|
|
10
|
+
{ label: 'Date', value: 4 },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
const mockOptionsWithGroups = [
|
|
14
|
+
{
|
|
15
|
+
label: 'Fruits',
|
|
16
|
+
options: [
|
|
17
|
+
{ label: 'Apple', value: 1 },
|
|
18
|
+
{ label: 'Banana', value: 2 },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
label: 'Vegetables',
|
|
23
|
+
options: [
|
|
24
|
+
{ label: 'Carrot', value: 3 },
|
|
25
|
+
{ label: 'Spinach', value: 4 },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
test('loads and displays CAutocompleteOptions component', async () => {
|
|
31
|
+
const { container } = render(<CAutocompleteOptions options={mockOptions} selected={[]} />)
|
|
32
|
+
expect(container).toMatchSnapshot()
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('CAutocompleteOptions renders all options', async () => {
|
|
36
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} />)
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText('Apple')).toBeVisible()
|
|
39
|
+
expect(screen.getByText('Banana')).toBeVisible()
|
|
40
|
+
expect(screen.getByText('Cherry')).toBeVisible()
|
|
41
|
+
expect(screen.getByText('Date')).toBeVisible()
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('CAutocompleteOptions renders option groups', async () => {
|
|
45
|
+
render(<CAutocompleteOptions options={mockOptionsWithGroups} selected={[]} />)
|
|
46
|
+
|
|
47
|
+
expect(screen.getByText('Fruits')).toBeVisible()
|
|
48
|
+
expect(screen.getByText('Vegetables')).toBeVisible()
|
|
49
|
+
expect(screen.getByText('Apple')).toBeVisible()
|
|
50
|
+
expect(screen.getByText('Carrot')).toBeVisible()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('CAutocompleteOptions marks selected option', async () => {
|
|
54
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[mockOptions[0]]} />)
|
|
55
|
+
|
|
56
|
+
const selectedOption = screen.getByText('Apple').closest('.autocomplete-option')
|
|
57
|
+
expect(selectedOption).toHaveClass('selected')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test('CAutocompleteOptions calls onOptionClick when option clicked', async () => {
|
|
61
|
+
const onOptionClick = jest.fn()
|
|
62
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} onOptionClick={onOptionClick} />)
|
|
63
|
+
|
|
64
|
+
const option = screen.getByText('Apple')
|
|
65
|
+
fireEvent.click(option)
|
|
66
|
+
|
|
67
|
+
expect(onOptionClick).toHaveBeenCalledWith(mockOptions[0])
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test('CAutocompleteOptions handles Enter key press', async () => {
|
|
71
|
+
const onOptionClick = jest.fn()
|
|
72
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} onOptionClick={onOptionClick} />)
|
|
73
|
+
|
|
74
|
+
const option = screen.getByText('Apple')
|
|
75
|
+
fireEvent.keyDown(option, { key: 'Enter' })
|
|
76
|
+
|
|
77
|
+
expect(onOptionClick).toHaveBeenCalledWith(mockOptions[0])
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('CAutocompleteOptions handles Space key press', async () => {
|
|
81
|
+
const onOptionClick = jest.fn()
|
|
82
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} onOptionClick={onOptionClick} />)
|
|
83
|
+
|
|
84
|
+
const option = screen.getByText('Apple')
|
|
85
|
+
fireEvent.keyDown(option, { code: 'Space' })
|
|
86
|
+
|
|
87
|
+
expect(onOptionClick).toHaveBeenCalledWith(mockOptions[0])
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
test('CAutocompleteOptions navigates with arrow keys', async () => {
|
|
91
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} />)
|
|
92
|
+
|
|
93
|
+
const firstOption = screen.getByText('Apple')
|
|
94
|
+
const secondOption = screen.getByText('Banana')
|
|
95
|
+
|
|
96
|
+
firstOption.focus()
|
|
97
|
+
fireEvent.keyDown(firstOption, { key: 'ArrowDown' })
|
|
98
|
+
|
|
99
|
+
expect(document.activeElement).toBe(secondOption)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
test('CAutocompleteOptions shows no results message', async () => {
|
|
103
|
+
render(
|
|
104
|
+
<CAutocompleteOptions options={[]} selected={[]} searchNoResultsLabel="No options found" />
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
expect(screen.getByText('No options found')).toBeVisible()
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('CAutocompleteOptions highlights search matches', async () => {
|
|
111
|
+
render(
|
|
112
|
+
<CAutocompleteOptions
|
|
113
|
+
options={mockOptions}
|
|
114
|
+
selected={[]}
|
|
115
|
+
highlightOptionsOnSearch={true}
|
|
116
|
+
searchValue="app"
|
|
117
|
+
/>
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
const option = screen.getByText('Apple').closest('.autocomplete-option')
|
|
121
|
+
expect(option).toContainHTML('dangerouslySetInnerHTML')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('CAutocompleteOptions uses custom option template', async () => {
|
|
125
|
+
const customTemplate = (option) => (
|
|
126
|
+
<div className="custom-option">
|
|
127
|
+
{option.label} - {option.value}
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
render(
|
|
132
|
+
<CAutocompleteOptions options={mockOptions} selected={[]} optionsTemplate={customTemplate} />
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
expect(screen.getByText('Apple - 1')).toBeVisible()
|
|
136
|
+
expect(screen.getByText('Banana - 2')).toBeVisible()
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
test('CAutocompleteOptions uses custom group template', async () => {
|
|
140
|
+
const customGroupTemplate = (group) => (
|
|
141
|
+
<div className="custom-group">{group.label.toUpperCase()}</div>
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
render(
|
|
145
|
+
<CAutocompleteOptions
|
|
146
|
+
options={mockOptionsWithGroups}
|
|
147
|
+
selected={[]}
|
|
148
|
+
optionsGroupsTemplate={customGroupTemplate}
|
|
149
|
+
/>
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
expect(screen.getByText('FRUITS')).toBeVisible()
|
|
153
|
+
expect(screen.getByText('VEGETABLES')).toBeVisible()
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('CAutocompleteOptions shows loading state', async () => {
|
|
157
|
+
const { container } = render(
|
|
158
|
+
<CAutocompleteOptions options={mockOptions} selected={[]} loading={true} />
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
expect(container.querySelector('.element-cover')).toBeInTheDocument()
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
test('CAutocompleteOptions renders with virtual scroller', async () => {
|
|
165
|
+
const { container } = render(
|
|
166
|
+
<CAutocompleteOptions
|
|
167
|
+
options={mockOptions}
|
|
168
|
+
selected={[]}
|
|
169
|
+
virtualScroller={true}
|
|
170
|
+
visibleItems={2}
|
|
171
|
+
/>
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
expect(container.querySelector('.virtual-scroller')).toBeInTheDocument()
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('CAutocompleteOptions sets max height', async () => {
|
|
178
|
+
const { container } = render(
|
|
179
|
+
<CAutocompleteOptions options={mockOptions} selected={[]} optionsMaxHeight={200} />
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
const optionsContainer = container.querySelector('.autocomplete-options')
|
|
183
|
+
expect(optionsContainer).toHaveStyle('max-height: 200px')
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('CAutocompleteOptions marks disabled options', async () => {
|
|
187
|
+
const optionsWithDisabled = [
|
|
188
|
+
{ label: 'Apple', value: 1 },
|
|
189
|
+
{ label: 'Banana', value: 2, disabled: true },
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
render(<CAutocompleteOptions options={optionsWithDisabled} selected={[]} />)
|
|
193
|
+
|
|
194
|
+
const disabledOption = screen.getByText('Banana').closest('.autocomplete-option')
|
|
195
|
+
expect(disabledOption).toHaveClass('disabled')
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
test('CAutocompleteOptions has correct accessibility attributes', async () => {
|
|
199
|
+
render(<CAutocompleteOptions options={mockOptions} selected={[]} />)
|
|
200
|
+
|
|
201
|
+
const listbox = screen.getByRole('listbox')
|
|
202
|
+
expect(listbox).toBeInTheDocument()
|
|
203
|
+
|
|
204
|
+
const options = screen.getAllByRole('option')
|
|
205
|
+
expect(options).toHaveLength(4)
|
|
206
|
+
|
|
207
|
+
options.forEach((option) => {
|
|
208
|
+
expect(option).toHaveAttribute('tabIndex', '0')
|
|
209
|
+
})
|
|
210
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type Option =
|
|
2
|
+
| string
|
|
3
|
+
| {
|
|
4
|
+
disabled?: boolean
|
|
5
|
+
label: string
|
|
6
|
+
options?: Option[]
|
|
7
|
+
custom?: boolean
|
|
8
|
+
selected?: boolean
|
|
9
|
+
value?: number | string
|
|
10
|
+
[key: string]: unknown
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type OptionsGroup = {
|
|
14
|
+
label: string
|
|
15
|
+
options?: Option[]
|
|
16
|
+
[key: string]: unknown
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type Search =
|
|
20
|
+
| 'external'
|
|
21
|
+
| 'global'
|
|
22
|
+
| {
|
|
23
|
+
external?: boolean
|
|
24
|
+
global?: boolean
|
|
25
|
+
}
|