Files
2025-03-07 19:22:02 +01:00

85 lines
2.8 KiB
JavaScript

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'
})
};
};