(
function TabPanels(
{
className,
children,
disableScrollFix = false,
disableTransition = false,
persistent = false,
...props
},
forwardedRef
) {
const { tabsId, tabs, activeIndex } = useTabs();
const prevIndex = useRef(activeIndex);
const [{ previous, incrementing }, setState] = useState({
previous: activeIndex,
incrementing: true,
});
// have to set these in refs since changing these might cause mounting
// and unmounting in the Transition group component :/ they should only
// be re-evaluated when the activeIndex changes.
const transitionable = useRef(!persistent && !disableTransition);
const animatable = useRef(persistent && !disableTransition);
if (prevIndex.current !== activeIndex) {
prevIndex.current = activeIndex;
transitionable.current = !persistent && !disableTransition;
animatable.current = persistent && !disableTransition;
}
useEffect(() => {
setState(({ previous }) => ({
incrementing: previous < activeIndex,
previous: disableTransition ? activeIndex : previous,
}));
// this is for only updating the incrementing state and should not be fired
// again if the disableTransition prop is changed
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex]);
const onEntered = useCallback(() => {
setState(({ incrementing }) => ({ incrementing, previous: activeIndex }));
}, [activeIndex]);
const [ref, refHandler] = useEnsuredRef(forwardedRef);
useEffect(() => {
if (!ref.current || disableScrollFix) {
return;
}
ref.current.scrollTop = 0;
// don't want it to be triggered if only the disableScrollFix prop has changed
// since it might be independent from active indexes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeIndex]);
return (
{Children.map(children, (child, index) => {
if (!isValidElement(child)) {
return child;
}
const panel = Children.only(child);
let labelledBy = panel.props["aria-labelledby"];
if (!labelledBy && !panel.props["aria-label"] && tabs[index]) {
// generally guaranteed to be defined by this point since the TabsManager
// will add ids if missing.
labelledBy = tabs[index].id;
}
return cloneElement(child, {
"aria-labelledby": labelledBy,
id: `${tabsId}-panel-${index + 1}`,
hidden: persistent && index !== activeIndex && index !== previous,
temporary: !persistent,
transitionIn: index === activeIndex,
timeout: disableTransition ? 0 : panel.props.timeout,
onEntered: disableTransition ? undefined : onEntered,
});
})}
);
}
);