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.

141 lines (138 loc) 5.54 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.MenuStore = void 0; var React = _interopRequireWildcard(require("react")); var _store = require("@base-ui-components/utils/store"); var _empty = require("@base-ui-components/utils/empty"); var _useRefWithInit = require("@base-ui-components/utils/useRefWithInit"); var _floatingUiReact = require("../../floating-ui-react"); var _popups = require("../../utils/popups"); const selectors = { ..._popups.popupStoreSelectors, disabled: (0, _store.createSelector)(state => state.parent.type === 'menubar' ? state.parent.context.disabled || state.disabled : state.disabled), modal: (0, _store.createSelector)(state => (state.parent.type === undefined || state.parent.type === 'context-menu') && (state.modal ?? true)), allowMouseEnter: (0, _store.createSelector)(state => state.parent.type === 'menu' ? state.parent.store.select('allowMouseEnter') : state.allowMouseEnter), stickIfOpen: (0, _store.createSelector)(state => state.stickIfOpen), parent: (0, _store.createSelector)(state => state.parent), rootId: (0, _store.createSelector)(state => { if (state.parent.type === 'menu') { return state.parent.store.select('rootId'); } return state.parent.type !== undefined ? state.parent.context.rootId : state.rootId; }), activeIndex: (0, _store.createSelector)(state => state.activeIndex), isActive: (0, _store.createSelector)((state, itemIndex) => state.activeIndex === itemIndex), hoverEnabled: (0, _store.createSelector)(state => state.hoverEnabled), instantType: (0, _store.createSelector)(state => state.instantType), lastOpenChangeReason: (0, _store.createSelector)(state => state.openChangeReason), floatingTreeRoot: (0, _store.createSelector)(state => { if (state.parent.type === 'menu') { return state.parent.store.select('floatingTreeRoot'); } return state.floatingTreeRoot; }), floatingNodeId: (0, _store.createSelector)(state => state.floatingNodeId), floatingParentNodeId: (0, _store.createSelector)(state => state.floatingParentNodeId), itemProps: (0, _store.createSelector)(state => state.itemProps), closeDelay: (0, _store.createSelector)(state => state.closeDelay), keyboardEventRelay: (0, _store.createSelector)(state => { if (state.keyboardEventRelay) { return state.keyboardEventRelay; } if (state.parent.type === 'menu') { return state.parent.store.select('keyboardEventRelay'); } return undefined; }) }; class MenuStore extends _store.ReactStore { constructor(initialState) { super({ ...createInitialState(), ...initialState }, { positionerRef: /*#__PURE__*/React.createRef(), popupRef: /*#__PURE__*/React.createRef(), typingRef: { current: false }, itemDomElements: { current: [] }, itemLabels: { current: [] }, allowMouseUpTriggerRef: { current: false }, triggerFocusTargetRef: /*#__PURE__*/React.createRef(), beforeContentFocusGuardRef: /*#__PURE__*/React.createRef(), onOpenChangeComplete: undefined, triggerElements: new _popups.PopupTriggerMap() }, selectors); // Sync `allowMouseEnter` with parent menu if applicable. this.observe((0, _store.createSelector)(state => state.allowMouseEnter), (allowMouseEnter, oldValue) => { // The allowMouseEnter !== oldValue check prevent calling parent store's set // on intialization. Without it, React might complain about updating one component during rendering another. if (this.state.parent.type === 'menu' && allowMouseEnter !== oldValue) { this.state.parent.store.set('allowMouseEnter', allowMouseEnter); } }); // Set up propagation of state from parent menu if applicable. this.unsubscribeParentListener = this.observe('parent', parent => { this.unsubscribeParentListener?.(); if (parent.type === 'menu') { this.unsubscribeParentListener = parent.store.subscribe(() => { this.notifyAll(); }); this.context.allowMouseUpTriggerRef = parent.store.context.allowMouseUpTriggerRef; return; } if (parent.type !== undefined) { this.context.allowMouseUpTriggerRef = parent.context.allowMouseUpTriggerRef; } this.unsubscribeParentListener = null; }); } setOpen(open, eventDetails) { this.state.floatingRootContext.context.events.emit('setOpen', { open, eventDetails }); } static useStore(externalStore, initialState) { // eslint-disable-next-line react-hooks/rules-of-hooks const store = (0, _useRefWithInit.useRefWithInit)(() => { return externalStore ?? new MenuStore(initialState); }).current; return store; } unsubscribeParentListener = null; } exports.MenuStore = MenuStore; function createInitialState() { return { ...(0, _popups.createInitialPopupStoreState)(), disabled: false, modal: true, allowMouseEnter: true, stickIfOpen: true, parent: { type: undefined }, rootId: undefined, activeIndex: null, hoverEnabled: true, instantType: undefined, openChangeReason: null, floatingTreeRoot: new _floatingUiReact.FloatingTreeStore(), floatingNodeId: undefined, floatingParentNodeId: null, itemProps: _empty.EMPTY_OBJECT, keyboardEventRelay: undefined, closeDelay: 0 }; }