UNPKG

@stratakit/foundations

Version:
106 lines (105 loc) 2.62 kB
import * as React from "react"; import { isBrowser, supportsPopover } from "./~utils.js"; const useLayoutEffect = isBrowser ? React.useLayoutEffect : React.useEffect; function useControlledState(initialValue, controlledState, setControlledState) { const [uncontrolledState, setUncontrolledState] = React.useState(initialValue); const state = React.useMemo( () => controlledState !== void 0 ? controlledState : uncontrolledState, [controlledState, uncontrolledState] ); const setControlledStateRef = useLatestRef(setControlledState); const setState = React.useCallback( (value) => { setUncontrolledState(value); setControlledStateRef.current?.(value); }, [setControlledStateRef] ); return [state, setState]; } function useLatestRef(value) { const valueRef = React.useRef(value); React.useInsertionEffect(() => { valueRef.current = value; }); return valueRef; } function useMergedRefs(...refs) { return React.useCallback( (instance) => { for (const ref of refs) { if (typeof ref === "function") { ref(instance); } else if (ref) { ref.current = instance; } } }, [...refs] ); } function useUnreactiveCallback(callback) { const latestCallback = useLatestRef(callback); return React.useCallback( (...args) => latestCallback.current?.(...args), [latestCallback] ); } function useEventHandlers(...handlers) { const latestHandlers = useLatestRef(handlers); return React.useCallback( (event) => { for (const handler of latestHandlers.current) { handler?.(event); if (event.defaultPrevented) return; } }, [latestHandlers] ); } function useSafeContext(context) { const value = React.useContext(context); if (value === void 0) { throw new Error(`${context.displayName || "Context"} is undefined`); } return value; } function usePopoverApi({ element, open }) { React.useEffect( function syncPopoverWithOpenState() { if (element?.popover && element?.isConnected) { element?.togglePopover?.(open); } }, [open, element] ); return React.useMemo( () => ({ style: { zIndex: supportsPopover ? void 0 : 9999 }, popover: "manual" }), [] ); } function useIsClient() { return React.useSyncExternalStore( React.useCallback(() => () => { }, []), () => true, () => false ); } export { useControlledState, useEventHandlers, useIsClient, useLatestRef, useLayoutEffect, useMergedRefs, usePopoverApi, useSafeContext, useUnreactiveCallback };