import React, { forwardRef, HTMLAttributes, KeyboardEvent, useRef } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' import { useForkedRef } from '../../hooks' import { getNextActiveElement } from '../../utils' export interface CTabListProps extends HTMLAttributes { /** * A string of all className you want applied to the base component. */ className?: string /** * Specify a layout type for component. */ layout?: 'fill' | 'justified' /** * Set the nav variant to tabs or pills. */ variant?: 'enclosed' | 'enclosed-pills' | 'pills' | 'tabs' | 'underline' | 'underline-border' } export const CTabList = forwardRef( ({ children, className, layout, variant, ...rest }, ref) => { const tabListRef = useRef(null) const forkedRef = useForkedRef(ref, tabListRef) const handleKeydown = (event: KeyboardEvent) => { if ( tabListRef.current !== null && (event.key === 'ArrowDown' || event.key === 'ArrowUp' || event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'Home' || event.key === 'End') ) { event.preventDefault() const target = event.target as HTMLElement // eslint-disable-next-line unicorn/prefer-spread const items: HTMLElement[] = Array.from( tabListRef.current.querySelectorAll('.nav-link:not(.disabled):not(:disabled)') ) let nextActiveElement if (event.key === 'Home' || event.key === 'End') { nextActiveElement = event.key === 'End' ? items.at(-1) : items[0] } else { nextActiveElement = getNextActiveElement( items, target, event.key === 'ArrowDown' || event.key === 'ArrowRight', true ) } if (nextActiveElement) { nextActiveElement.focus({ preventScroll: true }) } } } return (
{children}
) } ) CTabList.propTypes = { children: PropTypes.node, className: PropTypes.string, layout: PropTypes.oneOf(['fill', 'justified']), variant: PropTypes.oneOf([ 'enclosed', 'enclosed-pills', 'pills', 'tabs', 'underline', 'underline-border', ]), } CTabList.displayName = 'CTabList'