@elastic/eui 112.2.0-snapshot.1770205951498 → 112.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/es/components/flyout/index.js +4 -1
  2. package/es/components/flyout/manager/flyout_managed.js +31 -11
  3. package/es/components/flyout/manager/index.js +2 -0
  4. package/es/components/flyout/manager/store.js +31 -0
  5. package/es/components/form/file_picker/file_picker.js +1 -1
  6. package/eui.d.ts +47 -34
  7. package/lib/components/flyout/index.js +6 -0
  8. package/lib/components/flyout/manager/flyout_managed.js +30 -10
  9. package/lib/components/flyout/manager/index.js +7 -0
  10. package/lib/components/flyout/manager/store.js +30 -0
  11. package/lib/components/form/file_picker/file_picker.js +1 -1
  12. package/optimize/es/components/flyout/index.js +4 -1
  13. package/optimize/es/components/flyout/manager/flyout_managed.js +31 -11
  14. package/optimize/es/components/flyout/manager/index.js +2 -0
  15. package/optimize/es/components/flyout/manager/store.js +31 -0
  16. package/optimize/es/components/form/file_picker/file_picker.js +1 -1
  17. package/optimize/lib/components/flyout/index.js +6 -0
  18. package/optimize/lib/components/flyout/manager/flyout_managed.js +30 -10
  19. package/optimize/lib/components/flyout/manager/index.js +7 -0
  20. package/optimize/lib/components/flyout/manager/store.js +30 -0
  21. package/optimize/lib/components/form/file_picker/file_picker.js +1 -1
  22. package/package.json +2 -3
  23. package/test-env/components/flyout/index.js +6 -0
  24. package/test-env/components/flyout/manager/flyout_managed.js +30 -10
  25. package/test-env/components/flyout/manager/index.js +7 -0
  26. package/test-env/components/flyout/manager/store.js +30 -0
  27. package/test-env/components/form/file_picker/file_picker.js +1 -1
@@ -16,4 +16,7 @@ export { EuiFlyoutMenu } from './flyout_menu';
16
16
 
17
17
  // Hooks for using Manager-based flyouts
18
18
  export { useIsInManagedFlyout, useHasActiveSession } from './manager';
19
- export { useIsInsideParentFlyout } from './flyout_parent_context';
19
+ export { useIsInsideParentFlyout } from './flyout_parent_context';
20
+
21
+ // Flyout manager store (for cross-root state synchronization)
22
+ export { getFlyoutManagerStore } from './manager';
@@ -22,8 +22,9 @@ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t =
22
22
  * Side Public License, v 1.
23
23
  */
24
24
 
25
- import React, { useEffect, useMemo, useRef, useState, forwardRef } from 'react';
25
+ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState, forwardRef } from 'react';
26
26
  import PropTypes from "prop-types";
27
+ import { flushSync } from 'react-dom';
27
28
  import { useCombinedRefs, useEuiMemoizedStyles } from '../../../services';
28
29
  import { useEuiI18n } from '../../i18n';
29
30
  import { useResizeObserver } from '../../observer/resize_observer';
@@ -135,11 +136,25 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
135
136
  // Track if flyout was ever registered to avoid false positives on initial mount
136
137
  var wasRegisteredRef = useRef(false);
137
138
 
138
- // Register with flyout manager context when open, remove when closed
139
+ // Track flyoutExistsInManager in a ref to avoid dependency loop
140
+ // The cleanup function needs the current value but shouldn't cause re-runs
141
+ var flyoutExistsInManagerRef = useRef(flyoutExistsInManager);
142
+
143
+ // Update ref when flyoutExistsInManager changes
139
144
  useEffect(function () {
145
+ flyoutExistsInManagerRef.current = flyoutExistsInManager;
146
+ }, [flyoutExistsInManager]);
147
+
148
+ // Register with flyout manager context when open, remove when closed
149
+ // Using useLayoutEffect to run synchronously before DOM updates
150
+ useLayoutEffect(function () {
140
151
  addFlyout(flyoutId, title, level, size);
141
152
  return function () {
142
- closeFlyout(flyoutId);
153
+ // Only call closeFlyout if it wasn't already called via onClose
154
+ // This prevents duplicate removal when using Escape/X button
155
+ if (flyoutExistsInManagerRef.current) {
156
+ closeFlyout(flyoutId);
157
+ }
143
158
 
144
159
  // Reset navigation tracking when explicitly closed via isOpen=false
145
160
  wasRegisteredRef.current = false;
@@ -175,12 +190,6 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
175
190
  onActiveCallbackRef.current();
176
191
  }
177
192
  }, [currentSession, flyoutId, level]);
178
- useEffect(function () {
179
- return function () {
180
- // Only remove from manager on component unmount, don't trigger close callback
181
- closeFlyout(flyoutId);
182
- };
183
- }, [closeFlyout, flyoutId]);
184
193
 
185
194
  // Track width changes for flyouts
186
195
  var _useResizeObserver = useResizeObserver(isActive ? flyoutRef : null, 'width'),
@@ -188,8 +197,19 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
188
197
 
189
198
  // Pass the stabilized onClose callback to the flyout menu context
190
199
  var onClose = function onClose(e) {
191
- var _onCloseCallbackRef$c2;
192
- (_onCloseCallbackRef$c2 = onCloseCallbackRef.current) === null || _onCloseCallbackRef$c2 === void 0 || _onCloseCallbackRef$c2.call(onCloseCallbackRef, e);
200
+ // CRITICAL: Update manager state FIRST before allowing React to unmount
201
+ // This prevents race conditions during portal inline DOM transitions
202
+ // and ensures cascade close logic runs before DOM cleanup begins
203
+ // Using flushSync to force synchronous state update completion
204
+ flushSync(function () {
205
+ closeFlyout(flyoutId);
206
+ });
207
+
208
+ // trigger parent callback, unmounts the component
209
+ if (onCloseCallbackRef.current) {
210
+ var event = e || new MouseEvent('click');
211
+ onCloseCallbackRef.current(event);
212
+ }
193
213
  };
194
214
 
195
215
  // Update width in manager state when it changes
@@ -14,6 +14,8 @@ export { addFlyout as addFlyoutAction, closeFlyout as closeFlyoutAction, setActi
14
14
  /** Reducer and default state for the flyout manager. */
15
15
  export { flyoutManagerReducer, initialState } from './reducer';
16
16
 
17
+ /** Flyout manager store singleton and types. */
18
+ export { getFlyoutManagerStore } from './store';
17
19
  /** Provider component exposing the Flyout Manager API via context. */
18
20
  export { EuiFlyoutManager } from './provider';
19
21
 
@@ -8,10 +8,16 @@
8
8
 
9
9
  import { addFlyout as addFlyoutAction, closeFlyout as closeFlyoutAction, setActiveFlyout as setActiveFlyoutAction, setFlyoutWidth as setFlyoutWidthAction, setPushPadding as setPushPaddingAction, goBack as goBackAction, goToFlyout as goToFlyoutAction, addUnmanagedFlyout as addUnmanagedFlyoutAction, closeUnmanagedFlyout as closeUnmanagedFlyoutAction } from './actions';
10
10
  import { flyoutManagerReducer, initialState } from './reducer';
11
+
12
+ /**
13
+ * Events emitted by the flyout manager store for external consumers.
14
+ */
15
+
11
16
  function createStore() {
12
17
  var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
13
18
  var currentState = initial;
14
19
  var listeners = new Set();
20
+ var eventListeners = new Set();
15
21
  var getState = function getState() {
16
22
  return currentState;
17
23
  };
@@ -21,6 +27,17 @@ function createStore() {
21
27
  listeners.delete(listener);
22
28
  };
23
29
  };
30
+ var subscribeToEvents = function subscribeToEvents(listener) {
31
+ eventListeners.add(listener);
32
+ return function () {
33
+ eventListeners.delete(listener);
34
+ };
35
+ };
36
+ var emitEvent = function emitEvent(event) {
37
+ eventListeners.forEach(function (listener) {
38
+ listener(event);
39
+ });
40
+ };
24
41
 
25
42
  // The onClick handlers won't execute until after store is fully assigned.
26
43
  // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const'
@@ -49,6 +66,19 @@ function createStore() {
49
66
  // This ensures stable references and avoids stale closures
50
67
  if (nextState.sessions !== previousSessions) {
51
68
  store.historyItems = computeHistoryItems();
69
+
70
+ // Detect removed sessions and emit CLOSE_SESSION events
71
+ var nextSessionIds = new Set(nextState.sessions.map(function (s) {
72
+ return s.mainFlyoutId;
73
+ }));
74
+ previousSessions.forEach(function (session) {
75
+ if (!nextSessionIds.has(session.mainFlyoutId)) {
76
+ emitEvent({
77
+ type: 'CLOSE_SESSION',
78
+ session: session
79
+ });
80
+ }
81
+ });
52
82
  }
53
83
  listeners.forEach(function (l) {
54
84
  l();
@@ -58,6 +88,7 @@ function createStore() {
58
88
  store = {
59
89
  getState: getState,
60
90
  subscribe: subscribe,
91
+ subscribeToEvents: subscribeToEvents,
61
92
  dispatch: dispatch,
62
93
  addFlyout: function addFlyout(flyoutId, title, level, size) {
63
94
  return dispatch(addFlyoutAction(flyoutId, title, level, size));
@@ -214,7 +214,7 @@ export var EuiFilePickerClass = /*#__PURE__*/function (_Component) {
214
214
  css: iconStyles,
215
215
  className: "euiFilePicker__icon",
216
216
  color: iconColor,
217
- type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'importAction',
217
+ type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'upload',
218
218
  size: normalFormControl ? 'm' : 'l',
219
219
  "aria-hidden": "true"
220
220
  }), ___EmotionJSX("span", {
package/eui.d.ts CHANGED
@@ -12278,6 +12278,49 @@ declare module '@elastic/eui/src/components/flyout/manager/reducer' {
12278
12278
  */
12279
12279
  export function flyoutManagerReducer(state: EuiFlyoutManagerState | undefined, action: Action): EuiFlyoutManagerState;
12280
12280
 
12281
+ }
12282
+ declare module '@elastic/eui/src/components/flyout/manager/store' {
12283
+ import type { EuiFlyoutLevel, EuiFlyoutManagerState, FlyoutSession } from '@elastic/eui/src/components/flyout/manager/types';
12284
+ import type { Action } from '@elastic/eui/src/components/flyout/manager/actions';
12285
+ type Listener = () => void;
12286
+ /**
12287
+ * Events emitted by the flyout manager store for external consumers.
12288
+ */
12289
+ export type FlyoutManagerEvent = {
12290
+ type: 'CLOSE_SESSION';
12291
+ session: FlyoutSession;
12292
+ };
12293
+ type EventListener = (event: FlyoutManagerEvent) => void;
12294
+ export interface FlyoutManagerStore {
12295
+ getState: () => EuiFlyoutManagerState;
12296
+ subscribe: (listener: Listener) => () => void;
12297
+ subscribeToEvents: (listener: EventListener) => () => void;
12298
+ dispatch: (action: Action) => void;
12299
+ addFlyout: (flyoutId: string, title: string, level?: EuiFlyoutLevel, size?: string) => void;
12300
+ closeFlyout: (flyoutId: string) => void;
12301
+ setActiveFlyout: (flyoutId: string | null) => void;
12302
+ setFlyoutWidth: (flyoutId: string, width: number) => void;
12303
+ setPushPadding: (side: 'left' | 'right', width: number) => void;
12304
+ goBack: () => void;
12305
+ goToFlyout: (flyoutId: string) => void;
12306
+ addUnmanagedFlyout: (flyoutId: string) => void;
12307
+ closeUnmanagedFlyout: (flyoutId: string) => void;
12308
+ historyItems: Array<{
12309
+ title: string;
12310
+ onClick: () => void;
12311
+ }>;
12312
+ }
12313
+ /**
12314
+ * Returns a singleton store instance shared across all React roots within the same JS context.
12315
+ * Uses module-level singleton to ensure deduplication even if modules are loaded twice.
12316
+ */
12317
+ export function getFlyoutManagerStore(): FlyoutManagerStore;
12318
+ /**
12319
+ * For testing purposes - allows resetting the store
12320
+ */
12321
+ export function _resetFlyoutManagerStore(): void;
12322
+ export {};
12323
+
12281
12324
  }
12282
12325
  declare module '@elastic/eui/src/components/flyout/manager/selectors' {
12283
12326
  export const useSession: (flyoutId?: string | null) => import ("@elastic/eui/src/components/flyout/manager/types").FlyoutSession | null;
@@ -12352,40 +12395,6 @@ declare module '@elastic/eui/src/components/flyout/manager/layout_mode' {
12352
12395
  /** Current layout mode for managed flyouts (`side-by-side` or `stacked`). */
12353
12396
  export const useFlyoutLayoutMode: () => EuiFlyoutLayoutMode;
12354
12397
 
12355
- }
12356
- declare module '@elastic/eui/src/components/flyout/manager/store' {
12357
- import type { EuiFlyoutLevel, EuiFlyoutManagerState } from '@elastic/eui/src/components/flyout/manager/types';
12358
- import type { Action } from '@elastic/eui/src/components/flyout/manager/actions';
12359
- type Listener = () => void;
12360
- export interface FlyoutManagerStore {
12361
- getState: () => EuiFlyoutManagerState;
12362
- subscribe: (listener: Listener) => () => void;
12363
- dispatch: (action: Action) => void;
12364
- addFlyout: (flyoutId: string, title: string, level?: EuiFlyoutLevel, size?: string) => void;
12365
- closeFlyout: (flyoutId: string) => void;
12366
- setActiveFlyout: (flyoutId: string | null) => void;
12367
- setFlyoutWidth: (flyoutId: string, width: number) => void;
12368
- setPushPadding: (side: 'left' | 'right', width: number) => void;
12369
- goBack: () => void;
12370
- goToFlyout: (flyoutId: string) => void;
12371
- addUnmanagedFlyout: (flyoutId: string) => void;
12372
- closeUnmanagedFlyout: (flyoutId: string) => void;
12373
- historyItems: Array<{
12374
- title: string;
12375
- onClick: () => void;
12376
- }>;
12377
- }
12378
- /**
12379
- * Returns a singleton store instance shared across all React roots within the same JS context.
12380
- * Uses module-level singleton to ensure deduplication even if modules are loaded twice.
12381
- */
12382
- export function getFlyoutManagerStore(): FlyoutManagerStore;
12383
- /**
12384
- * For testing purposes - allows resetting the store
12385
- */
12386
- export function _resetFlyoutManagerStore(): void;
12387
- export {};
12388
-
12389
12398
  }
12390
12399
  declare module '@elastic/eui/src/components/flyout/manager/provider' {
12391
12400
  import React from 'react';
@@ -13103,6 +13112,9 @@ declare module '@elastic/eui/src/components/flyout/manager' {
13103
13112
  export { addFlyout as addFlyoutAction, closeFlyout as closeFlyoutAction, setActiveFlyout as setActiveFlyoutAction, setFlyoutWidth as setFlyoutWidthAction, setPushPadding as setPushPaddingAction, setActivityStage as setActivityStageAction, } from '@elastic/eui/src/components/flyout/manager/actions';
13104
13113
  /** Reducer and default state for the flyout manager. */
13105
13114
  export { flyoutManagerReducer, initialState } from '@elastic/eui/src/components/flyout/manager/reducer';
13115
+ /** Flyout manager store singleton and types. */
13116
+ export { getFlyoutManagerStore, type FlyoutManagerStore, type FlyoutManagerEvent, } from '@elastic/eui/src/components/flyout/manager/store';
13117
+ export type { EuiFlyoutManagerState, FlyoutSession } from '@elastic/eui/src/components/flyout/manager/types';
13106
13118
  /** Provider component exposing the Flyout Manager API via context. */
13107
13119
  export { EuiFlyoutManager } from '@elastic/eui/src/components/flyout/manager/provider';
13108
13120
  /**
@@ -14197,6 +14209,7 @@ declare module '@elastic/eui/src/components/flyout' {
14197
14209
  export { EuiFlyoutMenu } from '@elastic/eui/src/components/flyout/flyout_menu';
14198
14210
  export { useIsInManagedFlyout, useHasActiveSession } from '@elastic/eui/src/components/flyout/manager';
14199
14211
  export { useIsInsideParentFlyout } from '@elastic/eui/src/components/flyout/flyout_parent_context';
14212
+ export { getFlyoutManagerStore, type FlyoutManagerStore, type FlyoutManagerEvent, type EuiFlyoutManagerState, type FlyoutSession, } from '@elastic/eui/src/components/flyout/manager';
14200
14213
 
14201
14214
  }
14202
14215
  declare module '@elastic/eui/src/components/provider/component_defaults/component_defaults' {
@@ -51,6 +51,12 @@ Object.defineProperty(exports, "euiFlyoutSlideInRight", {
51
51
  return _flyout2.euiFlyoutSlideInRight;
52
52
  }
53
53
  });
54
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
55
+ enumerable: true,
56
+ get: function get() {
57
+ return _manager.getFlyoutManagerStore;
58
+ }
59
+ });
54
60
  Object.defineProperty(exports, "useHasActiveSession", {
55
61
  enumerable: true,
56
62
  get: function get() {
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.EuiManagedFlyout = void 0;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
9
  var _propTypes = _interopRequireDefault(require("prop-types"));
10
+ var _reactDom = require("react-dom");
10
11
  var _services = require("../../../services");
11
12
  var _i18n = require("../../i18n");
12
13
  var _resize_observer = require("../../observer/resize_observer");
@@ -142,11 +143,25 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
142
143
  // Track if flyout was ever registered to avoid false positives on initial mount
143
144
  var wasRegisteredRef = (0, _react.useRef)(false);
144
145
 
145
- // Register with flyout manager context when open, remove when closed
146
+ // Track flyoutExistsInManager in a ref to avoid dependency loop
147
+ // The cleanup function needs the current value but shouldn't cause re-runs
148
+ var flyoutExistsInManagerRef = (0, _react.useRef)(flyoutExistsInManager);
149
+
150
+ // Update ref when flyoutExistsInManager changes
146
151
  (0, _react.useEffect)(function () {
152
+ flyoutExistsInManagerRef.current = flyoutExistsInManager;
153
+ }, [flyoutExistsInManager]);
154
+
155
+ // Register with flyout manager context when open, remove when closed
156
+ // Using useLayoutEffect to run synchronously before DOM updates
157
+ (0, _react.useLayoutEffect)(function () {
147
158
  addFlyout(flyoutId, title, level, size);
148
159
  return function () {
149
- closeFlyout(flyoutId);
160
+ // Only call closeFlyout if it wasn't already called via onClose
161
+ // This prevents duplicate removal when using Escape/X button
162
+ if (flyoutExistsInManagerRef.current) {
163
+ closeFlyout(flyoutId);
164
+ }
150
165
 
151
166
  // Reset navigation tracking when explicitly closed via isOpen=false
152
167
  wasRegisteredRef.current = false;
@@ -182,12 +197,6 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
182
197
  onActiveCallbackRef.current();
183
198
  }
184
199
  }, [currentSession, flyoutId, level]);
185
- (0, _react.useEffect)(function () {
186
- return function () {
187
- // Only remove from manager on component unmount, don't trigger close callback
188
- closeFlyout(flyoutId);
189
- };
190
- }, [closeFlyout, flyoutId]);
191
200
 
192
201
  // Track width changes for flyouts
193
202
  var _useResizeObserver = (0, _resize_observer.useResizeObserver)(isActive ? flyoutRef : null, 'width'),
@@ -195,8 +204,19 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
195
204
 
196
205
  // Pass the stabilized onClose callback to the flyout menu context
197
206
  var onClose = function onClose(e) {
198
- var _onCloseCallbackRef$c2;
199
- (_onCloseCallbackRef$c2 = onCloseCallbackRef.current) === null || _onCloseCallbackRef$c2 === void 0 || _onCloseCallbackRef$c2.call(onCloseCallbackRef, e);
207
+ // CRITICAL: Update manager state FIRST before allowing React to unmount
208
+ // This prevents race conditions during portal inline DOM transitions
209
+ // and ensures cascade close logic runs before DOM cleanup begins
210
+ // Using flushSync to force synchronous state update completion
211
+ (0, _reactDom.flushSync)(function () {
212
+ closeFlyout(flyoutId);
213
+ });
214
+
215
+ // trigger parent callback, unmounts the component
216
+ if (onCloseCallbackRef.current) {
217
+ var event = e || new MouseEvent('click');
218
+ onCloseCallbackRef.current(event);
219
+ }
200
220
  };
201
221
 
202
222
  // Update width in manager state when it changes
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "flyoutManagerReducer", {
39
39
  return _reducer.flyoutManagerReducer;
40
40
  }
41
41
  });
42
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
43
+ enumerable: true,
44
+ get: function get() {
45
+ return _store.getFlyoutManagerStore;
46
+ }
47
+ });
42
48
  Object.defineProperty(exports, "getWidthFromSize", {
43
49
  enumerable: true,
44
50
  get: function get() {
@@ -161,6 +167,7 @@ Object.defineProperty(exports, "usePushPaddingOffsets", {
161
167
  });
162
168
  var _actions = require("./actions");
163
169
  var _reducer = require("./reducer");
170
+ var _store = require("./store");
164
171
  var _provider = require("./provider");
165
172
  var _hooks = require("./hooks");
166
173
  var _flyout_child = require("./flyout_child");
@@ -15,10 +15,15 @@ var _reducer = require("./reducer");
15
15
  * Side Public License, v 1.
16
16
  */
17
17
 
18
+ /**
19
+ * Events emitted by the flyout manager store for external consumers.
20
+ */
21
+
18
22
  function createStore() {
19
23
  var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _reducer.initialState;
20
24
  var currentState = initial;
21
25
  var listeners = new Set();
26
+ var eventListeners = new Set();
22
27
  var getState = function getState() {
23
28
  return currentState;
24
29
  };
@@ -28,6 +33,17 @@ function createStore() {
28
33
  listeners.delete(listener);
29
34
  };
30
35
  };
36
+ var subscribeToEvents = function subscribeToEvents(listener) {
37
+ eventListeners.add(listener);
38
+ return function () {
39
+ eventListeners.delete(listener);
40
+ };
41
+ };
42
+ var emitEvent = function emitEvent(event) {
43
+ eventListeners.forEach(function (listener) {
44
+ listener(event);
45
+ });
46
+ };
31
47
 
32
48
  // The onClick handlers won't execute until after store is fully assigned.
33
49
  // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const'
@@ -56,6 +72,19 @@ function createStore() {
56
72
  // This ensures stable references and avoids stale closures
57
73
  if (nextState.sessions !== previousSessions) {
58
74
  store.historyItems = computeHistoryItems();
75
+
76
+ // Detect removed sessions and emit CLOSE_SESSION events
77
+ var nextSessionIds = new Set(nextState.sessions.map(function (s) {
78
+ return s.mainFlyoutId;
79
+ }));
80
+ previousSessions.forEach(function (session) {
81
+ if (!nextSessionIds.has(session.mainFlyoutId)) {
82
+ emitEvent({
83
+ type: 'CLOSE_SESSION',
84
+ session: session
85
+ });
86
+ }
87
+ });
59
88
  }
60
89
  listeners.forEach(function (l) {
61
90
  l();
@@ -65,6 +94,7 @@ function createStore() {
65
94
  store = {
66
95
  getState: getState,
67
96
  subscribe: subscribe,
97
+ subscribeToEvents: subscribeToEvents,
68
98
  dispatch: dispatch,
69
99
  addFlyout: function addFlyout(flyoutId, title, level, size) {
70
100
  return dispatch((0, _actions.addFlyout)(flyoutId, title, level, size));
@@ -221,7 +221,7 @@ var EuiFilePickerClass = exports.EuiFilePickerClass = /*#__PURE__*/function (_Co
221
221
  css: iconStyles,
222
222
  className: "euiFilePicker__icon",
223
223
  color: iconColor,
224
- type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'importAction',
224
+ type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'upload',
225
225
  size: normalFormControl ? 'm' : 'l',
226
226
  "aria-hidden": "true"
227
227
  }), (0, _react2.jsx)("span", {
@@ -16,4 +16,7 @@ export { EuiFlyoutMenu } from './flyout_menu';
16
16
 
17
17
  // Hooks for using Manager-based flyouts
18
18
  export { useIsInManagedFlyout, useHasActiveSession } from './manager';
19
- export { useIsInsideParentFlyout } from './flyout_parent_context';
19
+ export { useIsInsideParentFlyout } from './flyout_parent_context';
20
+
21
+ // Flyout manager store (for cross-root state synchronization)
22
+ export { getFlyoutManagerStore } from './manager';
@@ -13,7 +13,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
13
13
  * Side Public License, v 1.
14
14
  */
15
15
 
16
- import React, { useEffect, useMemo, useRef, useState, forwardRef } from 'react';
16
+ import React, { useEffect, useLayoutEffect, useMemo, useRef, useState, forwardRef } from 'react';
17
+ import { flushSync } from 'react-dom';
17
18
  import { useCombinedRefs, useEuiMemoizedStyles } from '../../../services';
18
19
  import { useEuiI18n } from '../../i18n';
19
20
  import { useResizeObserver } from '../../observer/resize_observer';
@@ -125,11 +126,25 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
125
126
  // Track if flyout was ever registered to avoid false positives on initial mount
126
127
  var wasRegisteredRef = useRef(false);
127
128
 
128
- // Register with flyout manager context when open, remove when closed
129
+ // Track flyoutExistsInManager in a ref to avoid dependency loop
130
+ // The cleanup function needs the current value but shouldn't cause re-runs
131
+ var flyoutExistsInManagerRef = useRef(flyoutExistsInManager);
132
+
133
+ // Update ref when flyoutExistsInManager changes
129
134
  useEffect(function () {
135
+ flyoutExistsInManagerRef.current = flyoutExistsInManager;
136
+ }, [flyoutExistsInManager]);
137
+
138
+ // Register with flyout manager context when open, remove when closed
139
+ // Using useLayoutEffect to run synchronously before DOM updates
140
+ useLayoutEffect(function () {
130
141
  addFlyout(flyoutId, title, level, size);
131
142
  return function () {
132
- closeFlyout(flyoutId);
143
+ // Only call closeFlyout if it wasn't already called via onClose
144
+ // This prevents duplicate removal when using Escape/X button
145
+ if (flyoutExistsInManagerRef.current) {
146
+ closeFlyout(flyoutId);
147
+ }
133
148
 
134
149
  // Reset navigation tracking when explicitly closed via isOpen=false
135
150
  wasRegisteredRef.current = false;
@@ -165,12 +180,6 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
165
180
  onActiveCallbackRef.current();
166
181
  }
167
182
  }, [currentSession, flyoutId, level]);
168
- useEffect(function () {
169
- return function () {
170
- // Only remove from manager on component unmount, don't trigger close callback
171
- closeFlyout(flyoutId);
172
- };
173
- }, [closeFlyout, flyoutId]);
174
183
 
175
184
  // Track width changes for flyouts
176
185
  var _useResizeObserver = useResizeObserver(isActive ? flyoutRef : null, 'width'),
@@ -178,8 +187,19 @@ export var EuiManagedFlyout = /*#__PURE__*/forwardRef(function (_ref, ref) {
178
187
 
179
188
  // Pass the stabilized onClose callback to the flyout menu context
180
189
  var onClose = function onClose(e) {
181
- var _onCloseCallbackRef$c2;
182
- (_onCloseCallbackRef$c2 = onCloseCallbackRef.current) === null || _onCloseCallbackRef$c2 === void 0 || _onCloseCallbackRef$c2.call(onCloseCallbackRef, e);
190
+ // CRITICAL: Update manager state FIRST before allowing React to unmount
191
+ // This prevents race conditions during portal inline DOM transitions
192
+ // and ensures cascade close logic runs before DOM cleanup begins
193
+ // Using flushSync to force synchronous state update completion
194
+ flushSync(function () {
195
+ closeFlyout(flyoutId);
196
+ });
197
+
198
+ // trigger parent callback, unmounts the component
199
+ if (onCloseCallbackRef.current) {
200
+ var event = e || new MouseEvent('click');
201
+ onCloseCallbackRef.current(event);
202
+ }
183
203
  };
184
204
 
185
205
  // Update width in manager state when it changes
@@ -14,6 +14,8 @@ export { addFlyout as addFlyoutAction, closeFlyout as closeFlyoutAction, setActi
14
14
  /** Reducer and default state for the flyout manager. */
15
15
  export { flyoutManagerReducer, initialState } from './reducer';
16
16
 
17
+ /** Flyout manager store singleton and types. */
18
+ export { getFlyoutManagerStore } from './store';
17
19
  /** Provider component exposing the Flyout Manager API via context. */
18
20
  export { EuiFlyoutManager } from './provider';
19
21
 
@@ -8,10 +8,16 @@
8
8
 
9
9
  import { addFlyout as addFlyoutAction, closeFlyout as closeFlyoutAction, setActiveFlyout as setActiveFlyoutAction, setFlyoutWidth as setFlyoutWidthAction, setPushPadding as setPushPaddingAction, goBack as goBackAction, goToFlyout as goToFlyoutAction, addUnmanagedFlyout as addUnmanagedFlyoutAction, closeUnmanagedFlyout as closeUnmanagedFlyoutAction } from './actions';
10
10
  import { flyoutManagerReducer, initialState } from './reducer';
11
+
12
+ /**
13
+ * Events emitted by the flyout manager store for external consumers.
14
+ */
15
+
11
16
  function createStore() {
12
17
  var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
13
18
  var currentState = initial;
14
19
  var listeners = new Set();
20
+ var eventListeners = new Set();
15
21
  var getState = function getState() {
16
22
  return currentState;
17
23
  };
@@ -21,6 +27,17 @@ function createStore() {
21
27
  listeners.delete(listener);
22
28
  };
23
29
  };
30
+ var subscribeToEvents = function subscribeToEvents(listener) {
31
+ eventListeners.add(listener);
32
+ return function () {
33
+ eventListeners.delete(listener);
34
+ };
35
+ };
36
+ var emitEvent = function emitEvent(event) {
37
+ eventListeners.forEach(function (listener) {
38
+ listener(event);
39
+ });
40
+ };
24
41
 
25
42
  // The onClick handlers won't execute until after store is fully assigned.
26
43
  // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const'
@@ -49,6 +66,19 @@ function createStore() {
49
66
  // This ensures stable references and avoids stale closures
50
67
  if (nextState.sessions !== previousSessions) {
51
68
  store.historyItems = computeHistoryItems();
69
+
70
+ // Detect removed sessions and emit CLOSE_SESSION events
71
+ var nextSessionIds = new Set(nextState.sessions.map(function (s) {
72
+ return s.mainFlyoutId;
73
+ }));
74
+ previousSessions.forEach(function (session) {
75
+ if (!nextSessionIds.has(session.mainFlyoutId)) {
76
+ emitEvent({
77
+ type: 'CLOSE_SESSION',
78
+ session: session
79
+ });
80
+ }
81
+ });
52
82
  }
53
83
  listeners.forEach(function (l) {
54
84
  l();
@@ -58,6 +88,7 @@ function createStore() {
58
88
  store = {
59
89
  getState: getState,
60
90
  subscribe: subscribe,
91
+ subscribeToEvents: subscribeToEvents,
61
92
  dispatch: dispatch,
62
93
  addFlyout: function addFlyout(flyoutId, title, level, size) {
63
94
  return dispatch(addFlyoutAction(flyoutId, title, level, size));
@@ -201,7 +201,7 @@ export var EuiFilePickerClass = /*#__PURE__*/function (_Component) {
201
201
  css: iconStyles,
202
202
  className: "euiFilePicker__icon",
203
203
  color: iconColor,
204
- type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'importAction',
204
+ type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'upload',
205
205
  size: normalFormControl ? 'm' : 'l',
206
206
  "aria-hidden": "true"
207
207
  }), ___EmotionJSX("span", {
@@ -51,6 +51,12 @@ Object.defineProperty(exports, "euiFlyoutSlideInRight", {
51
51
  return _flyout2.euiFlyoutSlideInRight;
52
52
  }
53
53
  });
54
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
55
+ enumerable: true,
56
+ get: function get() {
57
+ return _manager.getFlyoutManagerStore;
58
+ }
59
+ });
54
60
  Object.defineProperty(exports, "useHasActiveSession", {
55
61
  enumerable: true,
56
62
  get: function get() {
@@ -11,6 +11,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
11
11
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
12
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
13
  var _react = _interopRequireWildcard(require("react"));
14
+ var _reactDom = require("react-dom");
14
15
  var _services = require("../../../services");
15
16
  var _i18n = require("../../i18n");
16
17
  var _resize_observer = require("../../observer/resize_observer");
@@ -133,11 +134,25 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
133
134
  // Track if flyout was ever registered to avoid false positives on initial mount
134
135
  var wasRegisteredRef = (0, _react.useRef)(false);
135
136
 
136
- // Register with flyout manager context when open, remove when closed
137
+ // Track flyoutExistsInManager in a ref to avoid dependency loop
138
+ // The cleanup function needs the current value but shouldn't cause re-runs
139
+ var flyoutExistsInManagerRef = (0, _react.useRef)(flyoutExistsInManager);
140
+
141
+ // Update ref when flyoutExistsInManager changes
137
142
  (0, _react.useEffect)(function () {
143
+ flyoutExistsInManagerRef.current = flyoutExistsInManager;
144
+ }, [flyoutExistsInManager]);
145
+
146
+ // Register with flyout manager context when open, remove when closed
147
+ // Using useLayoutEffect to run synchronously before DOM updates
148
+ (0, _react.useLayoutEffect)(function () {
138
149
  addFlyout(flyoutId, title, level, size);
139
150
  return function () {
140
- closeFlyout(flyoutId);
151
+ // Only call closeFlyout if it wasn't already called via onClose
152
+ // This prevents duplicate removal when using Escape/X button
153
+ if (flyoutExistsInManagerRef.current) {
154
+ closeFlyout(flyoutId);
155
+ }
141
156
 
142
157
  // Reset navigation tracking when explicitly closed via isOpen=false
143
158
  wasRegisteredRef.current = false;
@@ -173,12 +188,6 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
173
188
  onActiveCallbackRef.current();
174
189
  }
175
190
  }, [currentSession, flyoutId, level]);
176
- (0, _react.useEffect)(function () {
177
- return function () {
178
- // Only remove from manager on component unmount, don't trigger close callback
179
- closeFlyout(flyoutId);
180
- };
181
- }, [closeFlyout, flyoutId]);
182
191
 
183
192
  // Track width changes for flyouts
184
193
  var _useResizeObserver = (0, _resize_observer.useResizeObserver)(isActive ? flyoutRef : null, 'width'),
@@ -186,8 +195,19 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
186
195
 
187
196
  // Pass the stabilized onClose callback to the flyout menu context
188
197
  var onClose = function onClose(e) {
189
- var _onCloseCallbackRef$c2;
190
- (_onCloseCallbackRef$c2 = onCloseCallbackRef.current) === null || _onCloseCallbackRef$c2 === void 0 || _onCloseCallbackRef$c2.call(onCloseCallbackRef, e);
198
+ // CRITICAL: Update manager state FIRST before allowing React to unmount
199
+ // This prevents race conditions during portal inline DOM transitions
200
+ // and ensures cascade close logic runs before DOM cleanup begins
201
+ // Using flushSync to force synchronous state update completion
202
+ (0, _reactDom.flushSync)(function () {
203
+ closeFlyout(flyoutId);
204
+ });
205
+
206
+ // trigger parent callback, unmounts the component
207
+ if (onCloseCallbackRef.current) {
208
+ var event = e || new MouseEvent('click');
209
+ onCloseCallbackRef.current(event);
210
+ }
191
211
  };
192
212
 
193
213
  // Update width in manager state when it changes
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "flyoutManagerReducer", {
39
39
  return _reducer.flyoutManagerReducer;
40
40
  }
41
41
  });
42
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
43
+ enumerable: true,
44
+ get: function get() {
45
+ return _store.getFlyoutManagerStore;
46
+ }
47
+ });
42
48
  Object.defineProperty(exports, "getWidthFromSize", {
43
49
  enumerable: true,
44
50
  get: function get() {
@@ -161,6 +167,7 @@ Object.defineProperty(exports, "usePushPaddingOffsets", {
161
167
  });
162
168
  var _actions = require("./actions");
163
169
  var _reducer = require("./reducer");
170
+ var _store = require("./store");
164
171
  var _provider = require("./provider");
165
172
  var _hooks = require("./hooks");
166
173
  var _flyout_child = require("./flyout_child");
@@ -15,10 +15,15 @@ var _reducer = require("./reducer");
15
15
  * Side Public License, v 1.
16
16
  */
17
17
 
18
+ /**
19
+ * Events emitted by the flyout manager store for external consumers.
20
+ */
21
+
18
22
  function createStore() {
19
23
  var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _reducer.initialState;
20
24
  var currentState = initial;
21
25
  var listeners = new Set();
26
+ var eventListeners = new Set();
22
27
  var getState = function getState() {
23
28
  return currentState;
24
29
  };
@@ -28,6 +33,17 @@ function createStore() {
28
33
  listeners.delete(listener);
29
34
  };
30
35
  };
36
+ var subscribeToEvents = function subscribeToEvents(listener) {
37
+ eventListeners.add(listener);
38
+ return function () {
39
+ eventListeners.delete(listener);
40
+ };
41
+ };
42
+ var emitEvent = function emitEvent(event) {
43
+ eventListeners.forEach(function (listener) {
44
+ listener(event);
45
+ });
46
+ };
31
47
 
32
48
  // The onClick handlers won't execute until after store is fully assigned.
33
49
  // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const'
@@ -56,6 +72,19 @@ function createStore() {
56
72
  // This ensures stable references and avoids stale closures
57
73
  if (nextState.sessions !== previousSessions) {
58
74
  store.historyItems = computeHistoryItems();
75
+
76
+ // Detect removed sessions and emit CLOSE_SESSION events
77
+ var nextSessionIds = new Set(nextState.sessions.map(function (s) {
78
+ return s.mainFlyoutId;
79
+ }));
80
+ previousSessions.forEach(function (session) {
81
+ if (!nextSessionIds.has(session.mainFlyoutId)) {
82
+ emitEvent({
83
+ type: 'CLOSE_SESSION',
84
+ session: session
85
+ });
86
+ }
87
+ });
59
88
  }
60
89
  listeners.forEach(function (l) {
61
90
  l();
@@ -65,6 +94,7 @@ function createStore() {
65
94
  store = {
66
95
  getState: getState,
67
96
  subscribe: subscribe,
97
+ subscribeToEvents: subscribeToEvents,
68
98
  dispatch: dispatch,
69
99
  addFlyout: function addFlyout(flyoutId, title, level, size) {
70
100
  return dispatch((0, _actions.addFlyout)(flyoutId, title, level, size));
@@ -209,7 +209,7 @@ var EuiFilePickerClass = exports.EuiFilePickerClass = /*#__PURE__*/function (_Co
209
209
  css: iconStyles,
210
210
  className: "euiFilePicker__icon",
211
211
  color: iconColor,
212
- type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'importAction',
212
+ type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'upload',
213
213
  size: normalFormControl ? 'm' : 'l',
214
214
  "aria-hidden": "true"
215
215
  }), (0, _react2.jsx)("span", {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elastic/eui",
3
3
  "description": "Elastic UI Component Library",
4
- "version": "112.2.0-snapshot.1770205951498",
4
+ "version": "112.3.0",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "lib",
7
7
  "module": "es",
@@ -281,6 +281,5 @@
281
281
  ],
282
282
  "installConfig": {
283
283
  "hoistingLimits": "workspaces"
284
- },
285
- "stableVersion": "112.2.0"
284
+ }
286
285
  }
@@ -51,6 +51,12 @@ Object.defineProperty(exports, "euiFlyoutSlideInRight", {
51
51
  return _flyout2.euiFlyoutSlideInRight;
52
52
  }
53
53
  });
54
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
55
+ enumerable: true,
56
+ get: function get() {
57
+ return _manager.getFlyoutManagerStore;
58
+ }
59
+ });
54
60
  Object.defineProperty(exports, "useHasActiveSession", {
55
61
  enumerable: true,
56
62
  get: function get() {
@@ -12,6 +12,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
12
12
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
13
13
  var _react = _interopRequireWildcard(require("react"));
14
14
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
+ var _reactDom = require("react-dom");
15
16
  var _services = require("../../../services");
16
17
  var _i18n = require("../../i18n");
17
18
  var _resize_observer = require("../../observer/resize_observer");
@@ -134,11 +135,25 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
134
135
  // Track if flyout was ever registered to avoid false positives on initial mount
135
136
  var wasRegisteredRef = (0, _react.useRef)(false);
136
137
 
137
- // Register with flyout manager context when open, remove when closed
138
+ // Track flyoutExistsInManager in a ref to avoid dependency loop
139
+ // The cleanup function needs the current value but shouldn't cause re-runs
140
+ var flyoutExistsInManagerRef = (0, _react.useRef)(flyoutExistsInManager);
141
+
142
+ // Update ref when flyoutExistsInManager changes
138
143
  (0, _react.useEffect)(function () {
144
+ flyoutExistsInManagerRef.current = flyoutExistsInManager;
145
+ }, [flyoutExistsInManager]);
146
+
147
+ // Register with flyout manager context when open, remove when closed
148
+ // Using useLayoutEffect to run synchronously before DOM updates
149
+ (0, _react.useLayoutEffect)(function () {
139
150
  addFlyout(flyoutId, title, level, size);
140
151
  return function () {
141
- closeFlyout(flyoutId);
152
+ // Only call closeFlyout if it wasn't already called via onClose
153
+ // This prevents duplicate removal when using Escape/X button
154
+ if (flyoutExistsInManagerRef.current) {
155
+ closeFlyout(flyoutId);
156
+ }
142
157
 
143
158
  // Reset navigation tracking when explicitly closed via isOpen=false
144
159
  wasRegisteredRef.current = false;
@@ -174,12 +189,6 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
174
189
  onActiveCallbackRef.current();
175
190
  }
176
191
  }, [currentSession, flyoutId, level]);
177
- (0, _react.useEffect)(function () {
178
- return function () {
179
- // Only remove from manager on component unmount, don't trigger close callback
180
- closeFlyout(flyoutId);
181
- };
182
- }, [closeFlyout, flyoutId]);
183
192
 
184
193
  // Track width changes for flyouts
185
194
  var _useResizeObserver = (0, _resize_observer.useResizeObserver)(isActive ? flyoutRef : null, 'width'),
@@ -187,8 +196,19 @@ var EuiManagedFlyout = exports.EuiManagedFlyout = /*#__PURE__*/(0, _react.forwar
187
196
 
188
197
  // Pass the stabilized onClose callback to the flyout menu context
189
198
  var onClose = function onClose(e) {
190
- var _onCloseCallbackRef$c2;
191
- (_onCloseCallbackRef$c2 = onCloseCallbackRef.current) === null || _onCloseCallbackRef$c2 === void 0 || _onCloseCallbackRef$c2.call(onCloseCallbackRef, e);
199
+ // CRITICAL: Update manager state FIRST before allowing React to unmount
200
+ // This prevents race conditions during portal inline DOM transitions
201
+ // and ensures cascade close logic runs before DOM cleanup begins
202
+ // Using flushSync to force synchronous state update completion
203
+ (0, _reactDom.flushSync)(function () {
204
+ closeFlyout(flyoutId);
205
+ });
206
+
207
+ // trigger parent callback, unmounts the component
208
+ if (onCloseCallbackRef.current) {
209
+ var event = e || new MouseEvent('click');
210
+ onCloseCallbackRef.current(event);
211
+ }
192
212
  };
193
213
 
194
214
  // Update width in manager state when it changes
@@ -39,6 +39,12 @@ Object.defineProperty(exports, "flyoutManagerReducer", {
39
39
  return _reducer.flyoutManagerReducer;
40
40
  }
41
41
  });
42
+ Object.defineProperty(exports, "getFlyoutManagerStore", {
43
+ enumerable: true,
44
+ get: function get() {
45
+ return _store.getFlyoutManagerStore;
46
+ }
47
+ });
42
48
  Object.defineProperty(exports, "getWidthFromSize", {
43
49
  enumerable: true,
44
50
  get: function get() {
@@ -161,6 +167,7 @@ Object.defineProperty(exports, "usePushPaddingOffsets", {
161
167
  });
162
168
  var _actions = require("./actions");
163
169
  var _reducer = require("./reducer");
170
+ var _store = require("./store");
164
171
  var _provider = require("./provider");
165
172
  var _hooks = require("./hooks");
166
173
  var _flyout_child = require("./flyout_child");
@@ -15,10 +15,15 @@ var _reducer = require("./reducer");
15
15
  * Side Public License, v 1.
16
16
  */
17
17
 
18
+ /**
19
+ * Events emitted by the flyout manager store for external consumers.
20
+ */
21
+
18
22
  function createStore() {
19
23
  var initial = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _reducer.initialState;
20
24
  var currentState = initial;
21
25
  var listeners = new Set();
26
+ var eventListeners = new Set();
22
27
  var getState = function getState() {
23
28
  return currentState;
24
29
  };
@@ -28,6 +33,17 @@ function createStore() {
28
33
  listeners.delete(listener);
29
34
  };
30
35
  };
36
+ var subscribeToEvents = function subscribeToEvents(listener) {
37
+ eventListeners.add(listener);
38
+ return function () {
39
+ eventListeners.delete(listener);
40
+ };
41
+ };
42
+ var emitEvent = function emitEvent(event) {
43
+ eventListeners.forEach(function (listener) {
44
+ listener(event);
45
+ });
46
+ };
31
47
 
32
48
  // The onClick handlers won't execute until after store is fully assigned.
33
49
  // eslint-disable-next-line prefer-const -- Forward declaration requires 'let' not 'const'
@@ -56,6 +72,19 @@ function createStore() {
56
72
  // This ensures stable references and avoids stale closures
57
73
  if (nextState.sessions !== previousSessions) {
58
74
  store.historyItems = computeHistoryItems();
75
+
76
+ // Detect removed sessions and emit CLOSE_SESSION events
77
+ var nextSessionIds = new Set(nextState.sessions.map(function (s) {
78
+ return s.mainFlyoutId;
79
+ }));
80
+ previousSessions.forEach(function (session) {
81
+ if (!nextSessionIds.has(session.mainFlyoutId)) {
82
+ emitEvent({
83
+ type: 'CLOSE_SESSION',
84
+ session: session
85
+ });
86
+ }
87
+ });
59
88
  }
60
89
  listeners.forEach(function (l) {
61
90
  l();
@@ -65,6 +94,7 @@ function createStore() {
65
94
  store = {
66
95
  getState: getState,
67
96
  subscribe: subscribe,
97
+ subscribeToEvents: subscribeToEvents,
68
98
  dispatch: dispatch,
69
99
  addFlyout: function addFlyout(flyoutId, title, level, size) {
70
100
  return dispatch((0, _actions.addFlyout)(flyoutId, title, level, size));
@@ -210,7 +210,7 @@ var EuiFilePickerClass = exports.EuiFilePickerClass = /*#__PURE__*/function (_Co
210
210
  css: iconStyles,
211
211
  className: "euiFilePicker__icon",
212
212
  color: iconColor,
213
- type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'importAction',
213
+ type: isInvalid ? 'alert' : disabled ? 'minusInCircle' : 'upload',
214
214
  size: normalFormControl ? 'm' : 'l',
215
215
  "aria-hidden": "true"
216
216
  }), (0, _react2.jsx)("span", {