Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
410fc45
chore: improve test page
TeodorTaushanov Sep 4, 2025
ee8ff86
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 5, 2025
e026e3d
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 9, 2025
c5ca2a0
fix(OpenUI5Support): fix closing popups with escape key
TeodorTaushanov Sep 9, 2025
24ca8a6
fix: handle more cases
TeodorTaushanov Sep 10, 2025
5a3d049
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 11, 2025
630adf1
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 11, 2025
c991a65
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 12, 2025
739df46
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 12, 2025
cb6f02e
chore: patch OpenUI5 Element class
TeodorTaushanov Sep 12, 2025
4613918
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 15, 2025
c88a6f8
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 15, 2025
d6e0b99
chore: add tests
TeodorTaushanov Sep 15, 2025
8b77694
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 15, 2025
0154a4a
chore: change patched controls
TeodorTaushanov Sep 16, 2025
318a60a
chore: add more test
TeodorTaushanov Sep 16, 2025
ab66d7a
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 16, 2025
c9b1f36
chore: remove unused code
TeodorTaushanov Sep 16, 2025
317470e
chore: address copilot comments
TeodorTaushanov Sep 16, 2025
ce11d6b
chore: fix tests
TeodorTaushanov Sep 16, 2025
7f4e20a
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 16, 2025
89d6311
chore: fix tests
TeodorTaushanov Sep 16, 2025
e1b4d5f
chore: add more tests
TeodorTaushanov Sep 16, 2025
69072d3
Merge remote-tracking branch 'origin/main' into popup_patcher_keyboard
TeodorTaushanov Sep 17, 2025
48435c6
chore: resolves merge conflicts
TeodorTaushanov Sep 17, 2025
8db7a90
chore: fix lint error
TeodorTaushanov Sep 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/base/src/features/OpenUI5Support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
removeOpenedPopup,
getTopmostPopup,
} from "./patchPopup.js";
import type { OpenUI5Popup, PopupInfo } from "./patchPopup.js";
import type { OpenUI5Popup, OpenUI5PopupControl, PopupInfo } from "./patchPopup.js";
import { registerFeature } from "../FeaturesRegistry.js";
import { setTheme } from "../config/Theme.js";
import type { CLDRData } from "../asset-registries/LocaleData.js";
Expand Down Expand Up @@ -99,7 +99,7 @@ class OpenUI5Support {
OpenUI5Support.initPromise = new Promise<void>(resolve => {
window.sap.ui.require(["sap/ui/core/Core"], async (Core: OpenUI5Core) => {
const callback = () => {
let deps: Array<string> = ["sap/ui/core/Popup", "sap/ui/core/Patcher", "sap/ui/core/LocaleData"];
let deps: Array<string> = ["sap/ui/core/Popup", "sap/m/Dialog", "sap/m/Popover", "sap/ui/core/Patcher", "sap/ui/core/LocaleData"];
if (OpenUI5Support.isAtLeastVersion116()) { // for versions since 1.116.0 and onward, use the modular core
deps = [
...deps,
Expand All @@ -110,9 +110,9 @@ class OpenUI5Support {
"sap/ui/core/date/CalendarUtils",
];
}
window.sap.ui.require(deps, (Popup: OpenUI5Popup, Patcher: OpenUI5Patcher) => {
window.sap.ui.require(deps, (Popup: OpenUI5Popup, Dialog: OpenUI5PopupControl, Popover: OpenUI5PopupControl, Patcher: OpenUI5Patcher) => {
patchPatcher(Patcher);
patchPopup(Popup);
patchPopup(Popup, Dialog, Popover);
resolve();
});
};
Expand Down
41 changes: 30 additions & 11 deletions packages/base/src/features/patchPopup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ type OpenUI5Popup = {
}
};

type OpenUI5PopupControl = {
prototype: {
onsapescape: (e: Event) => void,
oPopup: OpenUI5Popup,
}
};

type PopupInfo = {
type: "OpenUI5" | "WebComponent";
instance: object;
Expand All @@ -41,25 +48,24 @@ const getTopmostPopup = () => {
};

/**
* Original OpenUI5 popup focus event is triggered only
* if there are no Web Component popups opened on top of it.
* Checks if 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.
* @param {object} popup The popup instance to check against.
* @returns {boolean} `true` if a Web Component popup is stacked above; otherwise `false`.
*/
const shouldCallOpenUI5FocusEvent = (popup: object) => {
const hasWebComponentPopupAbove = (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.type === "WebComponent") {
return true;
}

if (popupInfo.instance === popup) {
break;
}
}

return true;
return false;
};

const openNativePopover = (domRef: HTMLElement) => {
Expand All @@ -85,6 +91,17 @@ const isNativePopoverOpen = (root: Document | ShadowRoot = document): boolean =>
});
};

const patchPopupControl = (PopupControl: OpenUI5PopupControl) => {
const origOnsapescape = PopupControl.prototype.onsapescape;
PopupControl.prototype.onsapescape = function onsapescape(e: Event) {
if (hasWebComponentPopupAbove(this.oPopup)) {
return;
}

origOnsapescape.call(this, e);
};
};

const patchOpen = (Popup: OpenUI5Popup) => {
const origOpen = Popup.prototype.open;
Popup.prototype.open = function open(...args: any[]) {
Expand Down Expand Up @@ -125,7 +142,7 @@ const patchClosed = (Popup: OpenUI5Popup) => {
const patchFocusEvent = (Popup: OpenUI5Popup) => {
const origFocusEvent = Popup.prototype.onFocusEvent;
Popup.prototype.onFocusEvent = function onFocusEvent(e: FocusEvent) {
if (shouldCallOpenUI5FocusEvent(this)) {
if (!hasWebComponentPopupAbove(this)) {
origFocusEvent.call(this, e);
}
};
Expand All @@ -137,12 +154,14 @@ const createGlobalStyles = () => {
document.adoptedStyleSheets = [...document.adoptedStyleSheets, stylesheet];
};

const patchPopup = (Popup: OpenUI5Popup) => {
const patchPopup = (Popup: OpenUI5Popup, Dialog: OpenUI5PopupControl, Popover: OpenUI5PopupControl) => {
insertOpenUI5PopupStyles();
patchOpen(Popup); // Popup.prototype.open
patchClosed(Popup); // Popup.prototype._closed
createGlobalStyles(); // Ensures correct popover positioning by OpenUI5 (otherwise 0,0 is the center of the screen)
patchFocusEvent(Popup);// Popup.prototype.onFocusEvent
patchPopupControl(Dialog); // Dialog.prototype.onsapescape
patchPopupControl(Popover); // Popover.prototype.onsapescape
};

export {
Expand All @@ -152,4 +171,4 @@ export {
getTopmostPopup,
};

export type { OpenUI5Popup, PopupInfo };
export type { OpenUI5Popup, OpenUI5PopupControl, PopupInfo };
7 changes: 7 additions & 0 deletions packages/base/src/util/openui5support/eventMarking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const defaultKey = "handledByControl";

const isMarked = (event: any, key: string = defaultKey) => {
return !!event[`_sapui_${key}`];
};

export default isMarked;
Loading
Loading