diff --git a/packages/base/src/features/OpenUI5Support.ts b/packages/base/src/features/OpenUI5Support.ts index fd27ba9da491..cc4d49be4690 100644 --- a/packages/base/src/features/OpenUI5Support.ts +++ b/packages/base/src/features/OpenUI5Support.ts @@ -6,7 +6,7 @@ import { removeOpenedPopup, getTopmostPopup, } from "./patchPopup.js"; -import type { OpenUI5Popup } from "./patchPopup.js"; +import type { OpenUI5Popup, PopupInfo } from "./patchPopup.js"; import { registerFeature } from "../FeaturesRegistry.js"; import { setTheme } from "../config/Theme.js"; import type { CLDRData } from "../asset-registries/LocaleData.js"; @@ -230,8 +230,8 @@ class OpenUI5Support { return !!link.href.match(/\/css(-|_)variables\.css/) || !!link.href.match(/\/library\.css/); } - static addOpenedPopup(popup: object) { - addOpenedPopup(popup); + static addOpenedPopup(popupInfo: PopupInfo) { + addOpenedPopup(popupInfo); } static removeOpenedPopup(popup: object) { diff --git a/packages/base/src/features/patchPopup.ts b/packages/base/src/features/patchPopup.ts index f724bfe9ecf5..a50cf88d4e73 100644 --- a/packages/base/src/features/patchPopup.ts +++ b/packages/base/src/features/patchPopup.ts @@ -16,22 +16,49 @@ type OpenUI5Popup = { } }; +type PopupInfo = { + type: "OpenUI5" | "WebComponent"; + instance: object; +}; + // contains all OpenUI5 and Web Component popups that are currently opened -const AllOpenedPopupsRegistry = getSharedResource<{ openedRegistry: Array }>("AllOpenedPopupsRegistry", { openedRegistry: [] }); +const AllOpenedPopupsRegistry = getSharedResource<{ openedRegistry: Array }>("AllOpenedPopupsRegistry", { openedRegistry: [] }); -const addOpenedPopup = (popup: object) => { - AllOpenedPopupsRegistry.openedRegistry.push(popup); +const addOpenedPopup = (popupInfo: PopupInfo) => { + AllOpenedPopupsRegistry.openedRegistry.push(popupInfo); }; const removeOpenedPopup = (popup: object) => { - const index = AllOpenedPopupsRegistry.openedRegistry.indexOf(popup); + const index = AllOpenedPopupsRegistry.openedRegistry.findIndex(el => el.instance === popup); if (index > -1) { AllOpenedPopupsRegistry.openedRegistry.splice(index, 1); } }; const getTopmostPopup = () => { - return AllOpenedPopupsRegistry.openedRegistry[AllOpenedPopupsRegistry.openedRegistry.length - 1]; + return AllOpenedPopupsRegistry.openedRegistry[AllOpenedPopupsRegistry.openedRegistry.length - 1].instance; +}; + +/** + * Original OpenUI5 popup focus event is triggered only + * if there are no Web Component popups opened on top of it. + * + * @param {object} popup - The popup instance to check. + * @returns {boolean} True if the focus event should be triggered, false otherwise. + */ +const shouldCallOpenUI5FocusEvent = (popup: object) => { + for (let i = AllOpenedPopupsRegistry.openedRegistry.length - 1; i >= 0; i--) { + const popupInfo = AllOpenedPopupsRegistry.openedRegistry[i]; + if (popupInfo.type !== "OpenUI5") { + return false; + } + + if (popupInfo.instance === popup) { + break; + } + } + + return true; }; const openNativePopover = (domRef: HTMLElement) => { @@ -73,7 +100,10 @@ const patchOpen = (Popup: OpenUI5Popup) => { } } - addOpenedPopup(this); + addOpenedPopup({ + type: "OpenUI5", + instance: this, + }); }; }; @@ -94,9 +124,7 @@ const patchClosed = (Popup: OpenUI5Popup) => { const patchFocusEvent = (Popup: OpenUI5Popup) => { const origFocusEvent = Popup.prototype.onFocusEvent; Popup.prototype.onFocusEvent = function onFocusEvent(e: FocusEvent) { - // If the popup is the topmost one, we call the original focus event handler from the OpenUI5 Popup, - // otherwise the focus event is handled by the Web Component Popup. - if (this === getTopmostPopup()) { + if (shouldCallOpenUI5FocusEvent(this)) { origFocusEvent.call(this, e); } }; @@ -122,4 +150,4 @@ export { getTopmostPopup, }; -export type { OpenUI5Popup }; +export type { OpenUI5Popup, PopupInfo }; diff --git a/packages/main/src/popup-utils/OpenedPopupsRegistry.ts b/packages/main/src/popup-utils/OpenedPopupsRegistry.ts index 3b3898a68079..f280d47015af 100644 --- a/packages/main/src/popup-utils/OpenedPopupsRegistry.ts +++ b/packages/main/src/popup-utils/OpenedPopupsRegistry.ts @@ -3,6 +3,7 @@ import { isEscape } from "@ui5/webcomponents-base/dist/Keys.js"; import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; import type OpenUI5Support from "@ui5/webcomponents-base/dist/features/OpenUI5Support.js"; import type Popup from "../Popup.js"; +import type { PopupInfo } from "@ui5/webcomponents-base/dist/features/patchPopup.js"; type RegisteredPopup = { instance: Popup; @@ -12,8 +13,8 @@ type RegisteredPopup = { const OpenedPopupsRegistry = getSharedResource<{ openedRegistry: Array }>("OpenedPopupsRegistry", { openedRegistry: [] }); const openUI5Support = getFeature("OpenUI5Support"); -function registerPopupWithOpenUI5Support(popup: object) { - openUI5Support?.addOpenedPopup(popup); +function registerPopupWithOpenUI5Support(popupInfo: PopupInfo) { + openUI5Support?.addOpenedPopup(popupInfo); } function unregisterPopupWithOpenUI5Support(popup: object) { @@ -27,7 +28,10 @@ const addOpenedPopup = (instance: Popup, parentPopovers: Array = []) => { parentPopovers, }); - registerPopupWithOpenUI5Support(instance); + registerPopupWithOpenUI5Support({ + type: "WebComponent", + instance, + }); } _updateTopModalPopup(); diff --git a/packages/main/test/pages/DialogAndOpenUI5Dialog.html b/packages/main/test/pages/DialogAndOpenUI5Dialog.html index eb2d50f11290..de3c6d473964 100644 --- a/packages/main/test/pages/DialogAndOpenUI5Dialog.html +++ b/packages/main/test/pages/DialogAndOpenUI5Dialog.html @@ -21,13 +21,14 @@ data-sap-ui-compatVersion="edge"> @@ -94,7 +121,7 @@ Open WebC Dialog -
+
Open UI5 dialog