UNPKG

@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.

79 lines (78 loc) 3.07 kB
'use client'; import { useOnMount } from '@base-ui/utils/useOnMount'; import { useRefWithInit } from '@base-ui/utils/useRefWithInit'; import { Timeout } from '@base-ui/utils/useTimeout'; import { isInteractiveElement } from "../utils.js"; export { isInteractiveElement }; export class HoverInteraction { constructor() { this.pointerType = undefined; this.interactedInside = false; this.handler = undefined; this.blockMouseMove = true; this.performedPointerEventsMutation = false; this.pointerEventsScopeElement = null; this.pointerEventsReferenceElement = null; this.pointerEventsFloatingElement = null; this.restTimeoutPending = false; this.openChangeTimeout = new Timeout(); this.restTimeout = new Timeout(); this.handleCloseOptions = undefined; } static create() { return new HoverInteraction(); } dispose = () => { this.openChangeTimeout.clear(); this.restTimeout.clear(); }; disposeEffect = () => { return this.dispose; }; } const pointerEventsMutationOwnerByScopeElement = new WeakMap(); export function clearSafePolygonPointerEventsMutation(instance) { if (!instance.performedPointerEventsMutation) { return; } const scopeElement = instance.pointerEventsScopeElement; if (scopeElement && pointerEventsMutationOwnerByScopeElement.get(scopeElement) === instance) { instance.pointerEventsScopeElement?.style.removeProperty('pointer-events'); instance.pointerEventsReferenceElement?.style.removeProperty('pointer-events'); instance.pointerEventsFloatingElement?.style.removeProperty('pointer-events'); pointerEventsMutationOwnerByScopeElement.delete(scopeElement); } instance.performedPointerEventsMutation = false; instance.pointerEventsScopeElement = null; instance.pointerEventsReferenceElement = null; instance.pointerEventsFloatingElement = null; } export function applySafePolygonPointerEventsMutation(instance, options) { const { scopeElement, referenceElement, floatingElement } = options; const existingOwner = pointerEventsMutationOwnerByScopeElement.get(scopeElement); if (existingOwner && existingOwner !== instance) { clearSafePolygonPointerEventsMutation(existingOwner); } clearSafePolygonPointerEventsMutation(instance); instance.performedPointerEventsMutation = true; instance.pointerEventsScopeElement = scopeElement; instance.pointerEventsReferenceElement = referenceElement; instance.pointerEventsFloatingElement = floatingElement; pointerEventsMutationOwnerByScopeElement.set(scopeElement, instance); scopeElement.style.pointerEvents = 'none'; referenceElement.style.pointerEvents = 'auto'; floatingElement.style.pointerEvents = 'auto'; } export function useHoverInteractionSharedState(store) { const instance = useRefWithInit(HoverInteraction.create).current; const data = store.context.dataRef.current; if (!data.hoverInteractionState) { data.hoverInteractionState = instance; } useOnMount(data.hoverInteractionState.disposeEffect); return data.hoverInteractionState; }