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.

52 lines (51 loc) 1.89 kB
import { useId } from '@base-ui-components/utils/useId'; import { useRefWithInit } from '@base-ui-components/utils/useRefWithInit'; import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect'; import { isElement } from '@floating-ui/utils/dom'; import { useFloatingParentNodeId } from "../components/FloatingTree.js"; import { FloatingRootStore } from "../components/FloatingRootStore.js"; /** * Initializes a FloatingRootStore that is kept in sync with the provided PopupStore. * The new instance is created only once and updated on every render. */ export function useSyncedFloatingRootContext(options) { const { popupStore, noEmit = false, treatPopupAsFloatingElement = false, onOpenChange } = options; const floatingId = useId(); const nested = useFloatingParentNodeId() != null; const open = popupStore.useState('open'); const referenceElement = popupStore.useState('activeTriggerElement'); const floatingElement = popupStore.useState(treatPopupAsFloatingElement ? 'popupElement' : 'positionerElement'); const triggerElements = popupStore.context.triggerElements; const store = useRefWithInit(() => new FloatingRootStore({ open, referenceElement, floatingElement, triggerElements, onOpenChange, floatingId, nested, noEmit })).current; useIsoLayoutEffect(() => { const valuesToSync = { open, floatingId, referenceElement, floatingElement }; if (isElement(referenceElement)) { valuesToSync.domReferenceElement = referenceElement; } store.update(valuesToSync); }, [open, floatingId, referenceElement, floatingElement, store]); // TODO: When `setOpen` is a part of the PopupStore API, we don't need to sync it. store.context.onOpenChange = onOpenChange; store.context.nested = nested; store.context.noEmit = noEmit; return store; }