From 9e6312bf6130cbc83be5b8495f04f95589750c76 Mon Sep 17 00:00:00 2001 From: Aleksandar Petrov <8142643+aleks-p@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:13:44 -0400 Subject: [PATCH] A hack to fix broken layout when resizing panels --- .../components/ExploreMapPanelContent.tsx | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/public/app/features/explore-map/components/ExploreMapPanelContent.tsx b/public/app/features/explore-map/components/ExploreMapPanelContent.tsx index d9134f5504f..6d2ec5a3aa9 100644 --- a/public/app/features/explore-map/components/ExploreMapPanelContent.tsx +++ b/public/app/features/explore-map/components/ExploreMapPanelContent.tsx @@ -17,7 +17,65 @@ interface ExploreMapPanelContentProps { } -export function ExploreMapPanelContent({ exploreId }: ExploreMapPanelContentProps) { +// Patch getBoundingClientRect to fix AutoSizer measurements with CSS transforms +// Store original function +const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect; +let isPatched = false; + +function patchGetBoundingClientRect() { + if (isPatched) { + return; + } + + Element.prototype.getBoundingClientRect = function (this: Element) { + const result = originalGetBoundingClientRect.call(this); + + // Very conservative: only patch if this is an HTMLElement with offsetWidth available + // and it's inside a transformed container + if (!(this instanceof HTMLElement)) { + return result; + } + + // Check if we should use offsetWidth by looking at the stack trace + // This is hacky but safer than checking DOM position which can fail + try { + // Only apply fix if called from AutoSizer context + const stack = new Error().stack || ''; + const isFromAutoSizer = stack.includes('AutoSizer') || stack.includes('_onResize'); + + if (!isFromAutoSizer) { + return result; + } + + // Check if this element has transforms applied + let element: Element | null = this; + while (element) { + const style = window.getComputedStyle(element); + if (style.transform && style.transform !== 'none') { + // Use offsetWidth which is not affected by transforms + return { + ...result, + width: this.offsetWidth, + height: this.offsetHeight, + right: result.left + this.offsetWidth, + bottom: result.top + this.offsetHeight, + } as DOMRect; + } + element = element.parentElement; + } + } catch (e) { + // If anything fails, return original result + return result; + } + + return result; + }; + + isPatched = true; + console.log('[ExploreMapPanelContent] Patched getBoundingClientRect for AutoSizer'); +} + +export function ExploreMapPanelContent({ exploreId, width, height }: ExploreMapPanelContentProps) { const styles = useStyles2(getStyles); const dispatch = useDispatch(); const [isInitialized, setIsInitialized] = useState(false); @@ -25,6 +83,11 @@ export function ExploreMapPanelContent({ exploreId }: ExploreMapPanelContentProp // Create scoped event bus for this panel const eventBus = useMemo(() => new EventBusSrv(), []); + // Patch getBoundingClientRect on mount + useEffect(() => { + patchGetBoundingClientRect(); + }, []); + // Check if the explore pane exists in Redux const explorePane = useSelector((state) => state.explore?.panes?.[exploreId]); @@ -72,7 +135,13 @@ export function ExploreMapPanelContent({ exploreId }: ExploreMapPanelContentProp } return ( -
+
);