diff --git a/eslint.config.mjs b/eslint.config.mjs index 371d686d..0da538d2 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -45,6 +45,9 @@ export default typescriptEslint.config( ...eslintPluginReactHooks.configs.recommended.rules, 'no-console': 'off', 'no-debugger': 'off', + // the library compiles with the classic JSX transform (tsconfig "jsx": "react"), + // so the React import is required and must count as used + 'react/jsx-uses-react': 'error', 'unicorn/filename-case': 'off', 'unicorn/no-array-for-each': 'off', 'unicorn/no-null': 'off', @@ -104,5 +107,5 @@ export default typescriptEslint.config( 'unicorn/prefer-module': 'off', }, }, - eslintPluginPrettierRecommended, + eslintPluginPrettierRecommended ) diff --git a/packages/coreui-react/src/components/card/CCardImage.tsx b/packages/coreui-react/src/components/card/CCardImage.tsx index 93462342..93592394 100644 --- a/packages/coreui-react/src/components/card/CCardImage.tsx +++ b/packages/coreui-react/src/components/card/CCardImage.tsx @@ -4,8 +4,9 @@ import classNames from 'classnames' import { PolymorphicRefForwardingComponent } from '../../helpers' -export interface CCardImageProps - extends ImgHTMLAttributes { +export interface CCardImageProps extends ImgHTMLAttributes< + HTMLImageElement | HTMLOrSVGElement | HTMLOrSVGImageElement +> { /** * Component used for the root node. Either a string to use a HTML element or a component. */ diff --git a/packages/coreui-react/src/components/carousel/CCarouselContext.ts b/packages/coreui-react/src/components/carousel/CCarouselContext.ts index 6e21932b..659de995 100644 --- a/packages/coreui-react/src/components/carousel/CCarouselContext.ts +++ b/packages/coreui-react/src/components/carousel/CCarouselContext.ts @@ -5,4 +5,4 @@ export interface CCarouselContextProps { setCustomInterval: (a: boolean | number) => void } -export const CCarouselContext = createContext({} as CCarouselContextProps) \ No newline at end of file +export const CCarouselContext = createContext({} as CCarouselContextProps) diff --git a/packages/coreui-react/src/components/chip-set/__tests__/CChipSet.spec.tsx b/packages/coreui-react/src/components/chip-set/__tests__/CChipSet.spec.tsx index 27129875..d9a8e117 100644 --- a/packages/coreui-react/src/components/chip-set/__tests__/CChipSet.spec.tsx +++ b/packages/coreui-react/src/components/chip-set/__tests__/CChipSet.spec.tsx @@ -9,7 +9,7 @@ test('loads and displays CChipSet component', async () => { A B - , + ) expect(container).toMatchSnapshot() expect(container.firstChild).toHaveClass('chip-set') @@ -20,7 +20,7 @@ test('CChipSet passes selectable down to its chips', async () => { A B - , + ) expect(getByText('A')).toHaveAttribute('aria-selected', 'false') @@ -34,7 +34,7 @@ test('CChipSet allows multiple selected chips by default', async () => { A B - , + ) fireEvent.click(getByText('A')) @@ -51,7 +51,7 @@ test('CChipSet deselects siblings in single selection mode', async () => { A B - , + ) fireEvent.click(getByText('A')) @@ -67,7 +67,7 @@ test('CChipSet honors a controlled selected', async () => { A B - , + ) expect(getByText('A')).not.toHaveClass('active') @@ -78,7 +78,7 @@ test('CChipSet forwards filter so a selected chip shows a check icon', async () const { getByText, container } = render( A - , + ) expect(getByText('A')).toHaveClass('active') @@ -91,7 +91,7 @@ test('CChipSet moves focus between chips with the keyboard', async () => { First Second Third - , + ) const first = getByText('First') @@ -120,7 +120,7 @@ test('CChipSet mirrors arrow keys in RTL', async () => { First Second - , + ) const first = getByText('First') @@ -172,7 +172,7 @@ test('CChipSet fires onRemove so the parent can drop the chip', async () => { test('CChipSet with defaultChips removes the chip itself (uncontrolled list)', async () => { const onRemove = jest.fn() const { getByText, queryByText } = render( - , + ) fireEvent.click(getByText('a').querySelector('.chip-remove') as Element) @@ -186,8 +186,12 @@ test('CChipSet renders chips from the chips prop (strings and objects)', async ( const { getByText, container } = render( , + chips={[ + 'react', + { value: 'vue', label: 'Vue' }, + { value: 'ng', label: 'Angular', selectable: false }, + ]} + /> ) expect(container.querySelectorAll('.chip')).toHaveLength(3) @@ -203,7 +207,7 @@ test('CChipSet disables every chip', async () => { const { getByText } = render( A - , + ) expect(getByText('A')).toHaveClass('disabled') diff --git a/packages/coreui-react/src/components/chip/__tests__/CChip.spec.tsx b/packages/coreui-react/src/components/chip/__tests__/CChip.spec.tsx index 1d5d1f46..8e7f36aa 100644 --- a/packages/coreui-react/src/components/chip/__tests__/CChip.spec.tsx +++ b/packages/coreui-react/src/components/chip/__tests__/CChip.spec.tsx @@ -55,7 +55,7 @@ test('CChip selectable', async () => { const { getByText } = render( Selectable - , + ) const chip = getByText('Selectable') @@ -76,7 +76,7 @@ test('CChip filter shows a check icon while selected and implies selectable', as const { getByText, container } = render( Filter - , + ) const chip = getByText('Filter') @@ -96,7 +96,7 @@ test('CChip filter renders a custom selectedIcon', async () => { const { container } = render( }> Filter - , + ) expect(container.querySelector('.chip-check [data-testid="custom-check"]')).toBeInTheDocument() @@ -110,7 +110,7 @@ test('CChip delete triggers remove callback', async () => { First Second - , + ) const first = getByText('First') diff --git a/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx b/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx index ca9bea8c..0a67bfe1 100644 --- a/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx +++ b/packages/coreui-react/src/components/conditional-portal/CConditionalPortal.tsx @@ -3,7 +3,7 @@ import { createPortal } from 'react-dom' import PropTypes from 'prop-types' const getContainer = ( - container?: DocumentFragment | Element | (() => DocumentFragment | Element | null) | null, + container?: DocumentFragment | Element | (() => DocumentFragment | Element | null) | null ) => { if (container) { return typeof container === 'function' ? container() : container diff --git a/packages/coreui-react/src/components/form/CFormCheck.tsx b/packages/coreui-react/src/components/form/CFormCheck.tsx index 1e3983bb..e6c6b874 100644 --- a/packages/coreui-react/src/components/form/CFormCheck.tsx +++ b/packages/coreui-react/src/components/form/CFormCheck.tsx @@ -32,8 +32,7 @@ export type ButtonObject = { } export interface CFormCheckProps - extends CFormControlValidationProps, - InputHTMLAttributes { + extends CFormControlValidationProps, InputHTMLAttributes { /** * Create button-like checkboxes and radio buttons. */ diff --git a/packages/coreui-react/src/components/form/CFormInput.tsx b/packages/coreui-react/src/components/form/CFormInput.tsx index 4f4e9adf..13d71478 100644 --- a/packages/coreui-react/src/components/form/CFormInput.tsx +++ b/packages/coreui-react/src/components/form/CFormInput.tsx @@ -11,8 +11,7 @@ import classNames from 'classnames' import { CFormControlWrapper, CFormControlWrapperProps } from './CFormControlWrapper' export interface CFormInputProps - extends CFormControlWrapperProps, - Omit, 'size'> { + extends CFormControlWrapperProps, Omit, 'size'> { /** * A string of all className you want applied to the component. */ diff --git a/packages/coreui-react/src/components/form/CFormSelect.tsx b/packages/coreui-react/src/components/form/CFormSelect.tsx index 000b7f7d..9ea8a051 100644 --- a/packages/coreui-react/src/components/form/CFormSelect.tsx +++ b/packages/coreui-react/src/components/form/CFormSelect.tsx @@ -12,8 +12,7 @@ type Option = { } export interface CFormSelectProps - extends CFormControlWrapperProps, - Omit, 'size'> { + extends CFormControlWrapperProps, Omit, 'size'> { /** * A string of all className you want applied to the component. */ diff --git a/packages/coreui-react/src/components/form/CFormTextarea.tsx b/packages/coreui-react/src/components/form/CFormTextarea.tsx index 7ce589be..18aac21e 100644 --- a/packages/coreui-react/src/components/form/CFormTextarea.tsx +++ b/packages/coreui-react/src/components/form/CFormTextarea.tsx @@ -5,8 +5,7 @@ import classNames from 'classnames' import { CFormControlWrapper, CFormControlWrapperProps } from './CFormControlWrapper' export interface CFormTextareaProps - extends CFormControlWrapperProps, - TextareaHTMLAttributes { + extends CFormControlWrapperProps, TextareaHTMLAttributes { /** * A string of all className you want applied to the component. */ diff --git a/packages/coreui-react/src/components/form/CInputGroupText.tsx b/packages/coreui-react/src/components/form/CInputGroupText.tsx index 1829d06e..a777d673 100644 --- a/packages/coreui-react/src/components/form/CInputGroupText.tsx +++ b/packages/coreui-react/src/components/form/CInputGroupText.tsx @@ -4,8 +4,9 @@ import classNames from 'classnames' import { PolymorphicRefForwardingComponent } from '../../helpers' -export interface CInputGroupTextProps - extends LabelHTMLAttributes { +export interface CInputGroupTextProps extends LabelHTMLAttributes< + HTMLLabelElement | HTMLSpanElement +> { /** * Component used for the root node. Either a string to use a HTML element or a component. */ diff --git a/packages/coreui-react/src/components/form/__tests__/CChipInput.spec.tsx b/packages/coreui-react/src/components/form/__tests__/CChipInput.spec.tsx index 0d046c30..a14f04c8 100644 --- a/packages/coreui-react/src/components/form/__tests__/CChipInput.spec.tsx +++ b/packages/coreui-react/src/components/form/__tests__/CChipInput.spec.tsx @@ -53,7 +53,9 @@ test('CChipInput removes chip via remove button', async () => { test('CChipInput selectable chips', async () => { const onSelect = jest.fn() - const { container } = render() + const { container } = render( + + ) const chip = container.querySelector('.chip') as HTMLElement fireEvent.click(chip) @@ -73,7 +75,7 @@ test('CChipInput always renders a hidden input for form submission', async () => test('CChipInput single selection deselects siblings', async () => { const { container } = render( - , + ) const chips = container.querySelectorAll('.chip') @@ -117,7 +119,7 @@ test('CChipInput seeds initial chips from CChip children', () => { React Vue - , + ) expect(container.querySelectorAll('.chip')).toHaveLength(2) diff --git a/packages/coreui-react/src/components/header/CHeaderBrand.tsx b/packages/coreui-react/src/components/header/CHeaderBrand.tsx index cac55004..c6f5a9b6 100644 --- a/packages/coreui-react/src/components/header/CHeaderBrand.tsx +++ b/packages/coreui-react/src/components/header/CHeaderBrand.tsx @@ -4,8 +4,9 @@ import classNames from 'classnames' import { PolymorphicRefForwardingComponent } from '../../helpers' -export interface CHeaderBrandProps - extends AnchorHTMLAttributes { +export interface CHeaderBrandProps extends AnchorHTMLAttributes< + HTMLAnchorElement | HTMLSpanElement +> { /** * Component used for the root node. Either a string to use a HTML element or a component. */ diff --git a/packages/coreui-react/src/components/link/CLink.tsx b/packages/coreui-react/src/components/link/CLink.tsx index 4f6778b9..e91b5941 100644 --- a/packages/coreui-react/src/components/link/CLink.tsx +++ b/packages/coreui-react/src/components/link/CLink.tsx @@ -4,8 +4,10 @@ import classNames from 'classnames' import { PolymorphicRefForwardingComponent } from '../../helpers' -export interface CLinkProps - extends Omit, 'as'> { +export interface CLinkProps extends Omit< + AllHTMLAttributes, + 'as' +> { /** * Toggle the active state for the component. */ diff --git a/packages/coreui-react/src/components/list-group/CListGroupItem.tsx b/packages/coreui-react/src/components/list-group/CListGroupItem.tsx index 30a5b2b8..f5b58d9c 100644 --- a/packages/coreui-react/src/components/list-group/CListGroupItem.tsx +++ b/packages/coreui-react/src/components/list-group/CListGroupItem.tsx @@ -8,8 +8,9 @@ import { PolymorphicRefForwardingComponent } from '../../helpers' import { colorPropType } from '../../props' import type { Colors } from '../../types' -export interface CListGroupItemProps - extends AnchorHTMLAttributes { +export interface CListGroupItemProps extends AnchorHTMLAttributes< + HTMLLIElement | HTMLAnchorElement | HTMLButtonElement +> { /** * Toggle the active state for the component. */ diff --git a/packages/coreui-react/src/components/nav/CNav.tsx b/packages/coreui-react/src/components/nav/CNav.tsx index f056fbf7..38f98fad 100644 --- a/packages/coreui-react/src/components/nav/CNav.tsx +++ b/packages/coreui-react/src/components/nav/CNav.tsx @@ -4,8 +4,9 @@ import classNames from 'classnames' import { PolymorphicRefForwardingComponent } from '../../helpers' -export interface CNavProps - extends HTMLAttributes { +export interface CNavProps extends HTMLAttributes< + HTMLDivElement | HTMLUListElement | HTMLOListElement +> { /** * Component used for the root node. Either a string to use a HTML element or a component. */ diff --git a/packages/coreui-react/src/components/popover/__tests__/CPopover.spec.tsx b/packages/coreui-react/src/components/popover/__tests__/CPopover.spec.tsx index 2e9e6591..851f3e21 100644 --- a/packages/coreui-react/src/components/popover/__tests__/CPopover.spec.tsx +++ b/packages/coreui-react/src/components/popover/__tests__/CPopover.spec.tsx @@ -129,7 +129,14 @@ test('CPopover onShow and onHide', async () => { const onHide = jest.fn() render( - + Test , { container: container! } diff --git a/packages/coreui-react/src/components/progress/CProgress.tsx b/packages/coreui-react/src/components/progress/CProgress.tsx index 0a8b4cea..c6f4dc87 100644 --- a/packages/coreui-react/src/components/progress/CProgress.tsx +++ b/packages/coreui-react/src/components/progress/CProgress.tsx @@ -6,8 +6,7 @@ import { CProgressStackedContext } from './CProgressStackedContext' import { CProgressBar, CProgressBarProps } from './CProgressBar' export interface CProgressProps - extends Omit, 'color'>, - CProgressBarProps { + extends Omit, 'color'>, CProgressBarProps { /** * A string of all className you want applied to the component. */ diff --git a/packages/coreui-react/src/components/search-button/__tests__/CSearchButton.spec.tsx b/packages/coreui-react/src/components/search-button/__tests__/CSearchButton.spec.tsx index 93cb3a43..9ffa28ae 100644 --- a/packages/coreui-react/src/components/search-button/__tests__/CSearchButton.spec.tsx +++ b/packages/coreui-react/src/components/search-button/__tests__/CSearchButton.spec.tsx @@ -26,7 +26,7 @@ test('loads and displays CSearchButton component', async () => { test('CSearchButton customize', async () => { const { container } = render( - , + ) expect(container).toMatchSnapshot() @@ -56,7 +56,7 @@ test('CSearchButton ignores plain typing in editable fields', async () => { <> - , + ) fireEvent.keyDown(screen.getByLabelText('Search input'), { key: 'k' }) diff --git a/packages/coreui-react/src/components/sidebar/CSidebar.tsx b/packages/coreui-react/src/components/sidebar/CSidebar.tsx index 519bc097..1d1a43a1 100644 --- a/packages/coreui-react/src/components/sidebar/CSidebar.tsx +++ b/packages/coreui-react/src/components/sidebar/CSidebar.tsx @@ -92,7 +92,7 @@ export const CSidebar: PolymorphicRefForwardingComponent<'div', CSidebarProps> = visible, ...rest }, - ref, + ref ) => { const sidebarRef = useRef(null) const forkedRef = useForkedRef(ref, sidebarRef) @@ -101,7 +101,7 @@ export const CSidebar: PolymorphicRefForwardingComponent<'div', CSidebarProps> = const [mobile, setMobile] = useState(false) const [visibleMobile, setVisibleMobile] = useState(false) const [visibleDesktop, setVisibleDesktop] = useState( - visible !== undefined ? visible : overlaid ? false : true, + visible !== undefined ? visible : overlaid ? false : true ) useEffect(() => { @@ -206,7 +206,7 @@ export const CSidebar: PolymorphicRefForwardingComponent<'div', CSidebarProps> = show: (mobile && visibleMobile) || (overlaid && visibleDesktop), hide: visibleDesktop === false && !mobile && !overlaid, }, - className, + className )} {...rest} ref={forkedRef} @@ -217,11 +217,11 @@ export const CSidebar: PolymorphicRefForwardingComponent<'div', CSidebarProps> = mobile && createPortal( , - document.body, + document.body )} ) - }, + } ) CSidebar.propTypes = { @@ -241,4 +241,4 @@ CSidebar.propTypes = { visible: PropTypes.bool, } -CSidebar.displayName = 'CSidebar' \ No newline at end of file +CSidebar.displayName = 'CSidebar' diff --git a/packages/coreui-react/src/components/table/CTableDataCell.tsx b/packages/coreui-react/src/components/table/CTableDataCell.tsx index 2d5516c5..3e798a45 100644 --- a/packages/coreui-react/src/components/table/CTableDataCell.tsx +++ b/packages/coreui-react/src/components/table/CTableDataCell.tsx @@ -6,7 +6,8 @@ import { colorPropType } from '../../props' import type { Colors } from '../../types' export interface CTableDataCellProps - extends Omit, 'align'>, + extends + Omit, 'align'>, Omit, 'align'> { /** * Highlight a table row or cell. diff --git a/packages/coreui-react/src/components/table/utils.ts b/packages/coreui-react/src/components/table/utils.ts index 9c55ade1..7374df24 100644 --- a/packages/coreui-react/src/components/table/utils.ts +++ b/packages/coreui-react/src/components/table/utils.ts @@ -11,7 +11,7 @@ export const pretifyName = (name: string) => { } export const getColumnLabel = (column: Column | string) => - typeof column === 'object' ? column.label ?? pretifyName(column.key) : pretifyName(column) + typeof column === 'object' ? (column.label ?? pretifyName(column.key)) : pretifyName(column) export const getColumnNames = (columns: (string | Column)[] | undefined, items?: Item[]) => columns diff --git a/packages/coreui-react/src/components/tabs/CTabsContext.ts b/packages/coreui-react/src/components/tabs/CTabsContext.ts index 87f0c215..7160288d 100644 --- a/packages/coreui-react/src/components/tabs/CTabsContext.ts +++ b/packages/coreui-react/src/components/tabs/CTabsContext.ts @@ -6,4 +6,4 @@ export interface CTabsContextProps { id?: string } -export const CTabsContext = createContext({} as CTabsContextProps) \ No newline at end of file +export const CTabsContext = createContext({} as CTabsContextProps) diff --git a/packages/coreui-react/src/hooks/useColorModes.ts b/packages/coreui-react/src/hooks/useColorModes.ts index b6c63a80..67c89734 100644 --- a/packages/coreui-react/src/hooks/useColorModes.ts +++ b/packages/coreui-react/src/hooks/useColorModes.ts @@ -37,10 +37,10 @@ const setTheme = (colorMode: string) => { } export const useColorModes = ( - localStorageItemName = 'coreui-react-color-scheme', + localStorageItemName = 'coreui-react-color-scheme' ): UseColorModesOutput => { const [colorMode, setColorMode] = useState( - getPreferredColorScheme(localStorageItemName), + getPreferredColorScheme(localStorageItemName) ) useEffect(() => { diff --git a/packages/coreui-react/src/hooks/useForkedRef.ts b/packages/coreui-react/src/hooks/useForkedRef.ts index 0eb7b77a..c96351ae 100644 --- a/packages/coreui-react/src/hooks/useForkedRef.ts +++ b/packages/coreui-react/src/hooks/useForkedRef.ts @@ -30,7 +30,7 @@ export function useForkedRef( export function assignRef( ref: AssignableRef | null | undefined, // eslint-disable-next-line @typescript-eslint/no-explicit-any - value: any, + value: any ) { if (ref == null) return if (isFunction(ref)) { diff --git a/packages/docs/src/components/Header.tsx b/packages/docs/src/components/Header.tsx index 70723b7f..473c4777 100644 --- a/packages/docs/src/components/Header.tsx +++ b/packages/docs/src/components/Header.tsx @@ -34,8 +34,7 @@ import { Link } from 'gatsby' const Header = forwardRef(({}, ref) => { const { colorMode, setColorMode } = useColorModes('coreui-react-docs-theme') const isSearchButtonDocsPage = - typeof window !== 'undefined' && - window.location.pathname.includes('/components/search-button/') + typeof window !== 'undefined' && window.location.pathname.includes('/components/search-button/') return ( <>