rdesign/frontend/node_modules/use-stick-to-bottom/dist/StickToBottom.js

82 lines
3.4 KiB
JavaScript

/*!---------------------------------------------------------------------------------------------
* Copyright (c) StackBlitz. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as React from "react";
import { createContext, useContext, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, } from "react";
import { useStickToBottom, } from "./useStickToBottom.js";
const StickToBottomContext = createContext(null);
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
export function StickToBottom({ instance, children, resize, initial, mass, damping, stiffness, targetScrollTop: currentTargetScrollTop, contextRef, ...props }) {
const customTargetScrollTop = useRef(null);
const targetScrollTop = React.useCallback((target, elements) => {
const get = context?.targetScrollTop ?? currentTargetScrollTop;
return get?.(target, elements) ?? target;
}, [currentTargetScrollTop]);
const defaultInstance = useStickToBottom({
mass,
damping,
stiffness,
resize,
initial,
targetScrollTop,
});
const { scrollRef, contentRef, scrollToBottom, stopScroll, isAtBottom, escapedFromLock, state, } = instance ?? defaultInstance;
const context = useMemo(() => ({
scrollToBottom,
stopScroll,
scrollRef,
isAtBottom,
escapedFromLock,
contentRef,
state,
get targetScrollTop() {
return customTargetScrollTop.current;
},
set targetScrollTop(targetScrollTop) {
customTargetScrollTop.current = targetScrollTop;
},
}), [
scrollToBottom,
isAtBottom,
contentRef,
scrollRef,
stopScroll,
escapedFromLock,
state,
]);
useImperativeHandle(contextRef, () => context, [context]);
useIsomorphicLayoutEffect(() => {
if (!scrollRef.current) {
return;
}
if (getComputedStyle(scrollRef.current).overflow === "visible") {
scrollRef.current.style.overflow = "auto";
}
}, []);
return (React.createElement(StickToBottomContext.Provider, { value: context },
React.createElement("div", { ...props }, typeof children === "function" ? children(context) : children)));
}
(function (StickToBottom) {
function Content({ children, scrollClassName, ...props }) {
const context = useStickToBottomContext();
return (React.createElement("div", { ref: context.scrollRef, style: {
height: "100%",
width: "100%",
scrollbarGutter: "stable both-edges",
}, className: scrollClassName },
React.createElement("div", { ...props, ref: context.contentRef }, typeof children === "function" ? children(context) : children)));
}
StickToBottom.Content = Content;
})(StickToBottom || (StickToBottom = {}));
/**
* Use this hook inside a <StickToBottom> component to gain access to whether the component is at the bottom of the scrollable area.
*/
export function useStickToBottomContext() {
const context = useContext(StickToBottomContext);
if (!context) {
throw new Error("use-stick-to-bottom component context must be used within a StickToBottom component");
}
return context;
}