UNPKG

@elastic/eui

Version:

Elastic UI Component Library

249 lines (239 loc) 10.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports._resetFlyoutManagerStore = _resetFlyoutManagerStore; exports.getFlyoutManagerStore = getFlyoutManagerStore; var _actions = require("./actions"); var _reducer = require("./reducer"); function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ /** * Events emitted by the flyout manager store for external consumers. */ function createStore() { var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _reducer.initialState; var currentState = initial; var listeners = new Set(); var eventListeners = new Set(); // Transient, one-shot close annotations keyed by flyoutId. `goBack` stamps the // flyouts it removes so the managed flyout can report `navigation-back`; any // other removal (e.g. closeAllFlyouts cascade) leaves no stamp and defaults to // `navigation-cascade`. Kept off reducer state because it is a per-close // annotation, not persistent state. var pendingCloseMeta = new Map(); var getState = function getState() { return currentState; }; var subscribe = function subscribe(listener) { listeners.add(listener); return function () { listeners.delete(listener); }; }; var subscribeToEvents = function subscribeToEvents(listener) { eventListeners.add(listener); return function () { eventListeners.delete(listener); }; }; var emitEvent = function emitEvent(event) { eventListeners.forEach(function (listener) { listener(event); }); }; // The onClick handlers won't execute until after store is fully assigned. // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const' var store; var computeHistoryItems = function computeHistoryItems(dispatchFn) { var _currentSession$child; var currentSessionIndex = currentState.sessions.length - 1; var currentSession = currentSessionIndex >= 0 ? currentState.sessions[currentSessionIndex] : null; if (!currentSession) { return []; } var previousSessions = currentState.sessions.slice(0, currentSessionIndex); // Only include sessions in the same history group (same historyKey reference) var previousSessionsInGroup = previousSessions.filter(function (session) { return session.historyKey === currentSession.historyKey; }); var childHistory = (_currentSession$child = currentSession.childHistory) !== null && _currentSession$child !== void 0 ? _currentSession$child : []; var childItems = _toConsumableArray(childHistory).reverse().map(function (entry) { return { title: entry.title, iconType: entry.iconType, onClick: function onClick() { dispatchFn((0, _actions.goToFlyout)(entry.flyoutId, 'child')); } }; }); // Previous sessions (same group): list each session's current child then its child history var previousSessionItems = []; var _loop = function _loop() { var _session$childHistory; var session = previousSessionsInGroup[i]; var mainTitle = session.title; var mainFlyoutId = session.mainFlyoutId; var history = (_session$childHistory = session.childHistory) !== null && _session$childHistory !== void 0 ? _session$childHistory : []; var hasChildren = session.childFlyoutId != null && session.childTitle != null || history.length > 0; if (session.childFlyoutId && session.childTitle) { previousSessionItems.push({ title: session.childTitle, iconType: session.childIconType, onClick: function onClick() { dispatchFn((0, _actions.goToFlyout)(mainFlyoutId, 'main')); } }); } var _loop2 = function _loop2() { var entry = history[h]; previousSessionItems.push({ title: entry.title, iconType: entry.iconType, onClick: function onClick() { dispatchFn((0, _actions.goToFlyout)(mainFlyoutId, 'main')); dispatchFn((0, _actions.goToFlyout)(entry.flyoutId, 'child')); } }); }; for (var h = history.length - 1; h >= 0; h--) { _loop2(); } if (!hasChildren) { previousSessionItems.push({ title: mainTitle, iconType: session.iconType, onClick: function onClick() { dispatchFn((0, _actions.goToFlyout)(mainFlyoutId, 'main')); } }); } }; for (var i = previousSessionsInGroup.length - 1; i >= 0; i--) { _loop(); } return [].concat(_toConsumableArray(childItems), previousSessionItems); }; var dispatch = function dispatch(action) { var nextState = (0, _reducer.flyoutManagerReducer)(currentState, action); if (nextState !== currentState) { var previousSessions = currentState.sessions; currentState = nextState; // Recompute history items eagerly if sessions changed // This ensures stable references and avoids stale closures if (nextState.sessions !== previousSessions) { store.historyItems = computeHistoryItems(dispatch); // Detect removed sessions and emit CLOSE_SESSION events var nextSessionIds = new Set(nextState.sessions.map(function (s) { return s.mainFlyoutId; })); previousSessions.forEach(function (session) { if (!nextSessionIds.has(session.mainFlyoutId)) { emitEvent({ type: 'CLOSE_SESSION', session: session }); } }); } listeners.forEach(function (l) { l(); }); } }; store = { getState: getState, subscribe: subscribe, subscribeToEvents: subscribeToEvents, dispatch: dispatch, addFlyout: function addFlyout(flyoutId, title, level, size, historyKey, iconType, minWidth) { return dispatch((0, _actions.addFlyout)(flyoutId, title, level, size, historyKey, iconType, minWidth)); }, closeFlyout: function closeFlyout(flyoutId) { return dispatch((0, _actions.closeFlyout)(flyoutId)); }, closeAllFlyouts: function closeAllFlyouts() { return dispatch((0, _actions.closeAllFlyouts)()); }, setActiveFlyout: function setActiveFlyout(flyoutId) { return dispatch((0, _actions.setActiveFlyout)(flyoutId)); }, setFlyoutWidth: function setFlyoutWidth(flyoutId, width) { return dispatch((0, _actions.setFlyoutWidth)(flyoutId, width)); }, setPagination: function setPagination(flyoutId, pagination) { return dispatch((0, _actions.setPagination)(flyoutId, pagination)); }, setPushPadding: function setPushPadding(side, width) { return dispatch((0, _actions.setPushPadding)(side, width)); }, setContainerElement: function setContainerElement(element) { return dispatch((0, _actions.setContainerElement)(element)); }, goBack: function goBack() { // Stamp the flyouts goBack removes as `navigation-back` (vs. the default // `navigation-cascade`) BEFORE dispatching. dispatch synchronously flushes // subscribers, which can consume the meta during unmount, so peek the pure // reducer to learn which flyouts go away and stamp them first. var action = (0, _actions.goBack)(); var nextState = (0, _reducer.flyoutManagerReducer)(currentState, action); var remaining = new Set(nextState.flyouts.map(function (f) { return f.flyoutId; })); currentState.flyouts.forEach(function (f) { if (!remaining.has(f.flyoutId)) { pendingCloseMeta.set(f.flyoutId, { reason: 'navigation-back' }); } }); dispatch(action); }, goToFlyout: function goToFlyout(flyoutId, level) { return dispatch((0, _actions.goToFlyout)(flyoutId, level)); }, addUnmanagedFlyout: function addUnmanagedFlyout(flyoutId) { return dispatch((0, _actions.addUnmanagedFlyout)(flyoutId)); }, closeUnmanagedFlyout: function closeUnmanagedFlyout(flyoutId) { return dispatch((0, _actions.closeUnmanagedFlyout)(flyoutId)); }, consumeCloseMeta: function consumeCloseMeta(flyoutId) { var meta = pendingCloseMeta.get(flyoutId); if (meta) { pendingCloseMeta.delete(flyoutId); } return meta; }, historyItems: computeHistoryItems(dispatch) // Initialize with current state }; return store; } // Module-level singleton. A necessary trade-off to avoid global namespace pollution or the need for a third-party library. var storeInstance = null; /** * Returns a singleton store instance shared across all React roots within the same JS context. * Uses module-level singleton to ensure deduplication even if modules are loaded twice. */ function getFlyoutManagerStore() { if (!storeInstance) { storeInstance = createStore(); } return storeInstance; } /** * For testing purposes - allows resetting the store */ function _resetFlyoutManagerStore() { storeInstance = null; }