@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.
101 lines (97 loc) • 3.5 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FloatingNode = FloatingNode;
exports.FloatingTree = FloatingTree;
exports.useFloatingNodeId = useFloatingNodeId;
exports.useFloatingTree = exports.useFloatingParentNodeId = void 0;
var React = _interopRequireWildcard(require("react"));
var _useId = require("@base-ui-components/utils/useId");
var _useIsoLayoutEffect = require("@base-ui-components/utils/useIsoLayoutEffect");
var _useRefWithInit = require("@base-ui-components/utils/useRefWithInit");
var _FloatingTreeStore = require("./FloatingTreeStore");
var _jsxRuntime = require("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";
const useFloatingParentNodeId = () => React.useContext(FloatingNodeContext)?.id || null;
/**
* Returns the nearest floating tree context, if available.
*/
exports.useFloatingParentNodeId = useFloatingParentNodeId;
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
*/
exports.useFloatingTree = useFloatingTree;
function useFloatingNodeId(externalTree) {
const id = (0, _useId.useId)();
const tree = useFloatingTree(externalTree);
const parentId = useFloatingParentNodeId();
(0, _useIsoLayoutEffect.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
*/
function FloatingNode(props) {
const {
children,
id
} = props;
const parentId = useFloatingParentNodeId();
return /*#__PURE__*/(0, _jsxRuntime.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
*/
function FloatingTree(props) {
const {
children,
externalTree
} = props;
const tree = (0, _useRefWithInit.useRefWithInit)(() => externalTree ?? new _FloatingTreeStore.FloatingTreeStore()).current;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FloatingTreeContext.Provider, {
value: tree,
children: children
});
}