/*!--------------------------------------------------------------------------------------------- * 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 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; }