import * as React from 'react'; import { mergeCallbacks, slot, useAnimationFrame, useMergedRefs, useIsomorphicLayoutEffect, getIntrinsicElementProps } from '@fluentui/react-utilities'; import { useDrawerContext_unstable } from '../../contexts/drawerContext'; /** * @internal * * Get the current scroll state of the DrawerBody. * * @param element - HTMLElement to check scroll state of */ const getScrollState = ({ scrollTop, scrollHeight, clientHeight })=>{ if (scrollHeight <= clientHeight) { return 'none'; } if (scrollTop === 0) { return 'top'; } if (scrollTop + clientHeight === scrollHeight) { return 'bottom'; } return 'middle'; }; /** * Create the state required to render DrawerBody. * * The returned state can be modified with hooks such as useDrawerBodyStyles_unstable, * before being passed to renderDrawerBody_unstable. * * @param props - props from this instance of DrawerBody * @param ref - reference to root HTMLElement of DrawerBody */ export const useDrawerBody_unstable = (props, ref)=>{ const { setScrollState } = useDrawerContext_unstable(); const scrollRef = React.useRef(null); const [setAnimationFrame, cancelAnimationFrame] = useAnimationFrame(); const updateScrollState = React.useCallback(()=>{ if (!scrollRef.current) { return; } setScrollState(getScrollState(scrollRef.current)); }, [ setScrollState ]); const onScroll = React.useCallback(()=>{ cancelAnimationFrame(); setAnimationFrame(()=>updateScrollState()); }, [ cancelAnimationFrame, setAnimationFrame, updateScrollState ]); useIsomorphicLayoutEffect(()=>{ cancelAnimationFrame(); setAnimationFrame(()=>updateScrollState()); /* update scroll state when children changes */ return ()=>cancelAnimationFrame(); }, [ props.children, cancelAnimationFrame, updateScrollState, setAnimationFrame ]); useIsomorphicLayoutEffect(()=>{ cancelAnimationFrame(); setAnimationFrame(()=>updateScrollState()); return ()=>cancelAnimationFrame(); }, [ cancelAnimationFrame, updateScrollState, setAnimationFrame ]); return { components: { root: 'div' }, root: slot.always(getIntrinsicElementProps('div', { // FIXME: // `ref` is wrongly assigned to be `HTMLElement` instead of `HTMLDivElement` // but since it would be a breaking change to fix it, we are casting ref to it's proper type ref: useMergedRefs(ref, scrollRef), ...props, onScroll: mergeCallbacks(props.onScroll, onScroll) }), { elementType: 'div' }) }; };