interface PaginationItem { href: string; label: string; isActive?: boolean; ariaLabel?: string; } interface GetItemStateParams { activeIndex: number; items: PaginationItem[]; isCompact: boolean; index: number; } interface ItemState { isFirst: boolean; isHidden: boolean; isLast: boolean; isSecond: boolean; isSecondFromEnd: boolean; hasIcon: boolean; showSeparator: boolean; } export function getItemState({ activeIndex, items, isCompact, index, }: GetItemStateParams): ItemState { const isFirst = index === 0; const isSecond = index === 1; const isCurrent = index === activeIndex; const isSecondFromEnd = index === items.length - 2; const isLast = index === items.length - 1; const isSiblingActive = activeIndex === index - 1 || activeIndex === index + 1; const maxVisible = 5; // must be odd number to work properly const isCloseToCurrent = (index < activeIndex + Math.floor(maxVisible / 2) && index > activeIndex) || (index > activeIndex - Math.floor(maxVisible / 2) && index < activeIndex); const isCloseToFirst = index < maxVisible - 1 && activeIndex < maxVisible - 2; const isCloseToLast = index > items.length - maxVisible && activeIndex > items.length - (maxVisible - 1); const isHidden = !( isCloseToCurrent || isCloseToFirst || isCloseToLast || isFirst || isCurrent || isLast ); const showSeparator = (isSecond && isHidden) || (isSecondFromEnd && isHidden); const hasIcon = isCompact && !isCurrent && (isFirst || isLast) && !isSiblingActive && !(items.length <= maxVisible); return { isFirst, isHidden, isLast, isSecond, isSecondFromEnd, hasIcon, showSeparator, }; }