UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

89 lines (86 loc) 2.94 kB
import * as React from 'react'; import { useId } from '@base-ui-components/utils/useId'; import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect'; import { useRefWithInit } from '@base-ui-components/utils/useRefWithInit'; import { FloatingTreeStore } from "./FloatingTreeStore.js"; import { jsx as _jsx } from "react/jsx-runtime"; const FloatingNodeContext = /*#__PURE__*/React.createContext(null); if (process.env.NODE_ENV !== "production") FloatingNodeContext.displayName = "FloatingNodeContext"; const FloatingTreeContext = /*#__PURE__*/React.createContext(null); /** * Returns the parent node id for nested floating elements, if available. * Returns `null` for top-level floating elements. */ if (process.env.NODE_ENV !== "production") FloatingTreeContext.displayName = "FloatingTreeContext"; export const useFloatingParentNodeId = () => React.useContext(FloatingNodeContext)?.id || null; /** * Returns the nearest floating tree context, if available. */ export const useFloatingTree = externalTree => { const contextTree = React.useContext(FloatingTreeContext); return externalTree ?? contextTree; }; /** * Registers a node into the `FloatingTree`, returning its id. * @see https://floating-ui.com/docs/FloatingTree */ export function useFloatingNodeId(externalTree) { const id = useId(); const tree = useFloatingTree(externalTree); const parentId = useFloatingParentNodeId(); useIsoLayoutEffect(() => { if (!id) { return undefined; } const node = { id, parentId }; tree?.addNode(node); return () => { tree?.removeNode(node); }; }, [tree, id, parentId]); return id; } /** * Provides parent node context for nested floating elements. * @see https://floating-ui.com/docs/FloatingTree * @internal */ export function FloatingNode(props) { const { children, id } = props; const parentId = useFloatingParentNodeId(); return /*#__PURE__*/_jsx(FloatingNodeContext.Provider, { value: React.useMemo(() => ({ id, parentId }), [id, parentId]), children: children }); } /** * Provides context for nested floating elements when they are not children of * each other on the DOM. * This is not necessary in all cases, except when there must be explicit communication between parent and child floating elements. It is necessary for: * - The `bubbles` option in the `useDismiss()` Hook * - Nested virtual list navigation * - Nested floating elements that each open on hover * - Custom communication between parent and child floating elements * @see https://floating-ui.com/docs/FloatingTree * @internal */ export function FloatingTree(props) { const { children, externalTree } = props; const tree = useRefWithInit(() => externalTree ?? new FloatingTreeStore()).current; return /*#__PURE__*/_jsx(FloatingTreeContext.Provider, { value: tree, children: children }); }