@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.
109 lines (105 loc) • 4.45 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createInitialPopupStoreState = createInitialPopupStoreState;
exports.createPopupFloatingRootContext = createPopupFloatingRootContext;
exports.popupStoreSelectors = void 0;
var _empty = require("@base-ui/utils/empty");
var _FloatingRootStore = require("../../floating-ui-react/components/FloatingRootStore");
var _getEmptyRootContext = require("../../floating-ui-react/utils/getEmptyRootContext");
/**
* State common to all popup stores.
*/
function createInitialPopupStoreState() {
return {
open: false,
openProp: undefined,
mounted: false,
transitionStatus: undefined,
floatingRootContext: (0, _getEmptyRootContext.getEmptyRootContext)(),
floatingId: undefined,
triggerCount: 0,
preventUnmountingOnClose: false,
payload: undefined,
activeTriggerId: null,
activeTriggerElement: null,
triggerIdProp: undefined,
popupElement: null,
positionerElement: null,
activeTriggerProps: _empty.EMPTY_OBJECT,
inactiveTriggerProps: _empty.EMPTY_OBJECT,
popupProps: _empty.EMPTY_OBJECT
};
}
function createPopupFloatingRootContext(triggerElements, floatingId, nested = false) {
return new _FloatingRootStore.FloatingRootStore({
open: false,
transitionStatus: undefined,
floatingElement: null,
referenceElement: null,
triggerElements,
floatingId,
syncOnly: true,
nested,
onOpenChange: undefined
});
}
const activeTriggerIdSelector = state => state.triggerIdProp ?? state.activeTriggerId;
const openSelector = state => state.openProp ?? state.open;
const popupIdSelector = state => {
const popupId = state.popupElement?.id ?? state.floatingId;
return popupId || undefined;
};
function triggerOwnsOpenPopup(state, triggerId) {
return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) === triggerId;
}
function triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) {
if (triggerOwnsOpenPopup(state, triggerId)) {
return true;
}
return triggerId !== undefined && openSelector(state) && activeTriggerIdSelector(state) == null && state.triggerCount === 1;
}
const popupStoreSelectors = exports.popupStoreSelectors = {
open: openSelector,
mounted: state => state.mounted,
transitionStatus: state => state.transitionStatus,
floatingRootContext: state => state.floatingRootContext,
triggerCount: state => state.triggerCount,
preventUnmountingOnClose: state => state.preventUnmountingOnClose,
payload: state => state.payload,
activeTriggerId: activeTriggerIdSelector,
activeTriggerElement: state => state.mounted ? state.activeTriggerElement : null,
popupId: popupIdSelector,
/**
* Whether the trigger with the given ID was used to open the popup.
*/
isTriggerActive: (state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId,
/**
* Whether the popup is open and was activated by a trigger with the given ID.
*/
isOpenedByTrigger: (state, triggerId) => triggerOwnsOpenPopup(state, triggerId),
/**
* Whether the popup is mounted and was activated by a trigger with the given ID.
*/
isMountedByTrigger: (state, triggerId) => triggerId !== undefined && activeTriggerIdSelector(state) === triggerId && state.mounted,
triggerProps: (state, isActive) => isActive ? state.activeTriggerProps : state.inactiveTriggerProps,
/**
* Popup id for the trigger that currently owns the open popup.
*/
triggerPopupId: (state, triggerId) => triggerOwnsOpenPopupOrIsOnlyTrigger(state, triggerId) ? popupIdSelector(state) : undefined,
popupProps: state => state.popupProps,
popupElement: state => state.popupElement,
positionerElement: state => state.positionerElement
};
/**
* Store members a detached handle-backed trigger reads or invokes for trigger registration and data
* forwarding. `set`/`update` are included only for trigger-count and trigger-data bookkeeping; on a
* detached (inert) store they are intentionally no-ops, so a write through them is not guaranteed to
* be durable. Component handle-store views Pick these from their concrete store (preserving its
* context and selectors) and add any component-specific trigger-invoked members such as `setOpen`.
*/
/**
* The subset of a popup store that trigger registration and data forwarding rely on. Narrow enough
* that an inert store can be passed while detached.
*/