@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
JavaScript
'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;
}