UNPKG

@redocly/theme

Version:

Shared UI components lib

68 lines (55 loc) 2.1 kB
import { useEffect, useState, useCallback, useMemo } from 'react'; import type { FileTabs } from '@redocly/theme/components/CodeBlock/CodeBlock'; type CodeBlockTabsProps = { tabs: FileTabs; containerRef: React.RefObject<HTMLDivElement | null>; tabRefs: React.RefObject<HTMLButtonElement[]>; }; export function useCodeBlockTabsControls({ tabs, containerRef, tabRefs }: CodeBlockTabsProps) { const [showControls, setShowControls] = useState(false); const tabsWidth = useMemo( () => tabRefs?.current?.reduce((acc, tabRef) => { return tabRef ? acc + tabRef.offsetWidth : acc; }, 0) || 0, // eslint-disable-next-line react-hooks/exhaustive-deps [tabRefs?.current?.length], ); const { currentIndex, isFirstTab, isLastTab } = useMemo(() => { const currentIndex = tabs.files.findIndex((file) => file.name === tabs.activeTabName); return { currentIndex, isFirstTab: currentIndex === 0, isLastTab: currentIndex === tabs.files.length - 1, }; }, [tabs]); useEffect(() => { if (containerRef.current) { const container = containerRef.current; const resizeObserver = new ResizeObserver((entries) => { const containerWidth = entries[0].contentRect.width; setShowControls(tabsWidth > containerWidth); }); resizeObserver.observe(container); return () => { resizeObserver.unobserve(container as HTMLDivElement); }; } // eslint-disable-next-line react-hooks/exhaustive-deps }, [containerRef.current]); const handlePrevTab = useCallback(() => { if (!isFirstTab) { const prevTab = tabs.files[currentIndex - 1].name; tabs.handleTabSwitch(prevTab); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentIndex]); const handleNextTab = useCallback(() => { if (!isLastTab) { const nextTab = tabs.files[currentIndex + 1].name; tabs.handleTabSwitch(nextTab); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentIndex]); return { showControls, handlePrevTab, handleNextTab }; }