@base-ui/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.
67 lines (65 loc) • 2.5 kB
JavaScript
;
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useSyncedFloatingRootContext = useSyncedFloatingRootContext;
var React = _interopRequireWildcard(require("react"));
var _useIsoLayoutEffect = require("@base-ui/utils/useIsoLayoutEffect");
var _dom = require("@floating-ui/utils/dom");
var _FloatingRootStore = require("../components/FloatingRootStore");
/**
* Keeps a FloatingRootStore in sync with the provided PopupStore.
* Uses the provided FloatingRootStore when one exists, otherwise creates one once and updates it on every render.
*/
function useSyncedFloatingRootContext(options) {
const {
popupStore,
treatPopupAsFloatingElement = false,
floatingRootContext: floatingRootContextProp,
floatingId,
nested,
onOpenChange
} = options;
const open = popupStore.useState('open');
const referenceElement = popupStore.useState('activeTriggerElement');
const floatingElement = popupStore.useState(treatPopupAsFloatingElement ? 'popupElement' : 'positionerElement');
const triggerElements = popupStore.context.triggerElements;
const handleOpenChange = onOpenChange;
const internalStoreRef = React.useRef(null);
if (floatingRootContextProp === undefined && internalStoreRef.current === null) {
internalStoreRef.current = new _FloatingRootStore.FloatingRootStore({
open,
transitionStatus: undefined,
referenceElement,
floatingElement,
triggerElements,
onOpenChange: handleOpenChange,
floatingId,
syncOnly: true,
nested
});
}
const store = floatingRootContextProp ?? internalStoreRef.current;
popupStore.useSyncedValue('floatingId', floatingId);
(0, _useIsoLayoutEffect.useIsoLayoutEffect)(() => {
const valuesToSync = {
open,
floatingId,
referenceElement,
floatingElement
};
if ((0, _dom.isElement)(referenceElement)) {
valuesToSync.domReferenceElement = referenceElement;
}
if (store.state.positionReference === store.state.referenceElement) {
valuesToSync.positionReference = referenceElement;
}
store.update(valuesToSync);
}, [open, floatingId, referenceElement, floatingElement, store]);
// Keep non-reactive context values fresh for interactions that call `store.setOpen`.
store.context.onOpenChange = handleOpenChange;
store.context.nested = nested;
return store;
}