From 11049440672be0adcbbd753b4a502448bebeccc4 Mon Sep 17 00:00:00 2001 From: melloware Date: Thu, 24 Aug 2023 15:52:33 -0400 Subject: [PATCH] Fix #4819: Overlay handling better handling of alignment with browser changes --- components/lib/hooks/useOverlayListener.js | 11 +++++++++++ components/lib/overlaypanel/OverlayPanel.js | 19 ++++++++++++++++--- components/lib/overlaypanel/overlaypanel.d.ts | 4 ++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/components/lib/hooks/useOverlayListener.js b/components/lib/hooks/useOverlayListener.js index bba6d82c18..4490102764 100644 --- a/components/lib/hooks/useOverlayListener.js +++ b/components/lib/hooks/useOverlayListener.js @@ -17,12 +17,14 @@ export const useOverlayListener = ({ target, overlay, listener, when = true }) = * @param {boolean} options.valid It is controlled by PrimeReact. It is determined whether it is valid or not according to some custom validation. */ const [bindDocumentClickListener, unbindDocumentClickListener] = useEventListener({ + target: 'window', type: 'click', listener: (event) => { listener && listener(event, { type: 'outside', valid: event.which !== 3 && isOutsideClicked(event) }); } }); const [bindWindowResizeListener, unbindWindowResizeListener] = useResizeListener({ + target: 'window', listener: (event) => { listener && listener(event, { type: 'resize', valid: !DomHandler.isTouchDevice() }); } @@ -34,6 +36,13 @@ export const useOverlayListener = ({ target, overlay, listener, when = true }) = listener && listener(event, { type: 'orientationchange', valid: true }); } }); + const [bindWindowScrollChangeListener, unbindWindowScrollChangeListener] = useEventListener({ + target: 'window', + type: 'scroll', + listener: (event) => { + listener && listener(event, { type: 'scroll', valid: true }); + } + }); const [bindOverlayScrollListener, unbindOverlayScrollListener] = useOverlayScrollListener({ target, listener: (event) => { @@ -49,6 +58,7 @@ export const useOverlayListener = ({ target, overlay, listener, when = true }) = bindDocumentClickListener(); bindWindowResizeListener(); bindWindowOrientationChangeListener(); + bindWindowScrollChangeListener(); bindOverlayScrollListener(); }; @@ -56,6 +66,7 @@ export const useOverlayListener = ({ target, overlay, listener, when = true }) = unbindDocumentClickListener(); unbindWindowResizeListener(); unbindWindowOrientationChangeListener(); + unbindWindowScrollChangeListener(); unbindOverlayScrollListener(); }; diff --git a/components/lib/overlaypanel/OverlayPanel.js b/components/lib/overlaypanel/OverlayPanel.js index ffeb9121f6..0e492a59d1 100644 --- a/components/lib/overlaypanel/OverlayPanel.js +++ b/components/lib/overlaypanel/OverlayPanel.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import { useOnEscapeKey } from '../../lib/hooks/Hooks'; import PrimeReact, { PrimeReactContext, localeOption } from '../api/Api'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; @@ -9,7 +10,6 @@ import { Portal } from '../portal/Portal'; import { Ripple } from '../ripple/Ripple'; import { DomHandler, IconUtils, UniqueComponentId, ZIndexUtils, mergeProps } from '../utils/Utils'; import { OverlayPanelBase } from './OverlayPanelBase'; -import { useOnEscapeKey } from '../../lib/hooks/Hooks'; export const OverlayPanel = React.forwardRef((inProps, ref) => { const context = React.useContext(PrimeReactContext); @@ -37,7 +37,16 @@ export const OverlayPanel = React.forwardRef((inProps, ref) => { overlay: overlayRef, listener: (event, { type, valid }) => { if (valid) { - type === 'outside' ? props.dismissable && !isPanelClicked.current && hide() : hide(); + switch (type) { + case 'outside': + props.dismissable ? !isPanelClicked.current && hide() : hide(); + break; + case 'resize': + case 'scroll': + case 'orientationchange': + align(); + break; + } } isPanelClicked.current = false; @@ -154,7 +163,10 @@ export const OverlayPanel = React.forwardRef((inProps, ref) => { if (containerOffset.top < targetOffset.top) { overlayRef.current.setAttribute('data-p-overlaypanel-flipped', 'true'); - !isUnstyled && DomHandler.addClass(overlayRef.current, 'p-overlaypanel-flipped'); + isUnstyled && DomHandler.addClass(overlayRef.current, 'p-overlaypanel-flipped'); + } else { + overlayRef.current.setAttribute('data-p-overlaypanel-flipped', 'false'); + isUnstyled && DomHandler.removeClass(overlayRef.current, 'p-overlaypanel-flipped'); } } }; @@ -203,6 +215,7 @@ export const OverlayPanel = React.forwardRef((inProps, ref) => { toggle, show, hide, + align, getElement: () => overlayRef.current })); diff --git a/components/lib/overlaypanel/overlaypanel.d.ts b/components/lib/overlaypanel/overlaypanel.d.ts index 0979449312..44db12fda2 100644 --- a/components/lib/overlaypanel/overlaypanel.d.ts +++ b/components/lib/overlaypanel/overlaypanel.d.ts @@ -160,6 +160,10 @@ export declare class OverlayPanel extends React.Component