import * as React from 'react' export function useStableCallback) => any>( fn: T, ): T { const fnRef = React.useRef(fn) fnRef.current = fn const ref = React.useRef((...args: Array) => fnRef.current(...args)) return ref.current as T } export const useLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect /** * Taken from https://www.developerway.com/posts/implementing-advanced-use-previous-hook#part3 */ export function usePrevious(value: T): T | null { // initialise the ref with previous and current values const ref = React.useRef<{ value: T; prev: T | null }>({ value: value, prev: null, }) const current = ref.current.value // if the value passed into hook doesn't match what we store as "current" // move the "current" to the "previous" // and store the passed value as "current" if (value !== current) { ref.current = { value: value, prev: current, } } // return the previous value only return ref.current.prev } /** * React hook to wrap `IntersectionObserver`. * * This hook will create an `IntersectionObserver` and observe the ref passed to it. * * When the intersection changes, the callback will be called with the `IntersectionObserverEntry`. * * @param ref - The ref to observe * @param intersectionObserverOptions - The options to pass to the IntersectionObserver * @param options - The options to pass to the hook * @param callback - The callback to call when the intersection changes * @returns The IntersectionObserver instance * @example * ```tsx * const MyComponent = () => { * const ref = React.useRef(null) * useIntersectionObserver( * ref, * (entry) => { doSomething(entry) }, * { rootMargin: '10px' }, * { disabled: false } * ) * return
* ``` */ export function useIntersectionObserver( ref: React.RefObject, callback: (entry: IntersectionObserverEntry | undefined) => void, intersectionObserverOptions: IntersectionObserverInit = {}, options: { disabled?: boolean } = {}, ): IntersectionObserver | null { const isIntersectionObserverAvailable = React.useRef( typeof IntersectionObserver === 'function', ) const observerRef = React.useRef(null) React.useEffect(() => { if ( !ref.current || !isIntersectionObserverAvailable.current || options.disabled ) { return } observerRef.current = new IntersectionObserver(([entry]) => { callback(entry) }, intersectionObserverOptions) observerRef.current.observe(ref.current) return () => { observerRef.current?.disconnect() } }, [callback, intersectionObserverOptions, options.disabled, ref]) return observerRef.current } /** * React hook to take a `React.ForwardedRef` and returns a `ref` that can be used on a DOM element. * * @param ref - The forwarded ref * @returns The inner ref returned by `useRef` * @example * ```tsx * const MyComponent = React.forwardRef((props, ref) => { * const innerRef = useForwardedRef(ref) * return
* }) * ``` */ export function useForwardedRef(ref?: React.ForwardedRef) { const innerRef = React.useRef(null) React.useImperativeHandle(ref, () => innerRef.current!, []) return innerRef }