@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.
85 lines (81 loc) • 2.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FloatingRootStore = void 0;
var _store = require("@base-ui/utils/store");
var _createEventEmitter = require("../utils/createEventEmitter");
var _utils = require("../utils");
const selectors = {
open: (0, _store.createSelector)(state => state.open),
transitionStatus: (0, _store.createSelector)(state => state.transitionStatus),
domReferenceElement: (0, _store.createSelector)(state => state.domReferenceElement),
referenceElement: (0, _store.createSelector)(state => state.positionReference ?? state.referenceElement),
floatingElement: (0, _store.createSelector)(state => state.floatingElement),
floatingId: (0, _store.createSelector)(state => state.floatingId)
};
class FloatingRootStore extends _store.ReactStore {
constructor(options) {
const {
syncOnly,
nested,
onOpenChange,
triggerElements,
...initialState
} = options;
super({
...initialState,
positionReference: initialState.referenceElement,
domReferenceElement: initialState.referenceElement
}, {
onOpenChange,
dataRef: {
current: {}
},
events: (0, _createEventEmitter.createEventEmitter)(),
nested,
triggerElements
}, selectors);
this.syncOnly = syncOnly;
}
/**
* Syncs the event used by hover logic to distinguish hover-open from click-like interaction.
*/
syncOpenEvent = (newOpen, event) => {
if (!newOpen || !this.state.open ||
// Prevent a pending hover-open from overwriting a click-open event, while allowing
// click events to upgrade a hover-open.
event != null && (0, _utils.isClickLikeEvent)(event)) {
this.context.dataRef.current.openEvent = newOpen ? event : undefined;
}
};
/**
* Runs the root-owned side effects for an open state change.
*/
dispatchOpenChange = (newOpen, eventDetails) => {
this.syncOpenEvent(newOpen, eventDetails.event);
const details = {
open: newOpen,
reason: eventDetails.reason,
nativeEvent: eventDetails.event,
nested: this.context.nested,
triggerElement: eventDetails.trigger
};
this.context.events.emit('openchange', details);
};
/**
* Emits the `openchange` event through the internal event emitter and calls the `onOpenChange` handler with the provided arguments.
*
* @param newOpen The new open state.
* @param eventDetails Details about the event that triggered the open state change.
*/
setOpen = (newOpen, eventDetails) => {
if (this.syncOnly) {
this.context.onOpenChange?.(newOpen, eventDetails);
return;
}
this.dispatchOpenChange(newOpen, eventDetails);
this.context.onOpenChange?.(newOpen, eventDetails);
};
}
exports.FloatingRootStore = FloatingRootStore;