diff --git a/components/lib/cascadeselect/CascadeSelect.js b/components/lib/cascadeselect/CascadeSelect.js index 2137ca206b..21af0ceca2 100644 --- a/components/lib/cascadeselect/CascadeSelect.js +++ b/components/lib/cascadeselect/CascadeSelect.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PrimeReact, { PrimeReactContext } from '../api/Api'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; -import { useMountEffect, useOnEscapeKey, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { ChevronDownIcon } from '../icons/chevrondown'; import { SpinnerIcon } from '../icons/spinner'; import { OverlayService } from '../overlayservice/OverlayService'; @@ -49,7 +49,15 @@ export const CascadeSelect = React.memo( when: overlayVisibleState }); - useOnEscapeKey(overlayRef, overlayVisibleState, () => hide()); + const cascadeSelectOverlayDisplayOrder = useDisplayOrder('cascade-select', overlayVisibleState); + + useGlobalOnEscapeKey({ + callback: () => { + hide(); + }, + when: overlayVisibleState, + priority: [ESC_KEY_HANDLING_PRIORITIES.CASCADE_SELECT, cascadeSelectOverlayDisplayOrder] + }); const onOptionSelect = (event) => { if (props.onChange) { diff --git a/components/lib/cascadeselect/cascadeselect.d.ts b/components/lib/cascadeselect/cascadeselect.d.ts index 5024cb8002..2d6dd7de7d 100644 --- a/components/lib/cascadeselect/cascadeselect.d.ts +++ b/components/lib/cascadeselect/cascadeselect.d.ts @@ -9,6 +9,7 @@ */ import * as React from 'react'; import { CSSTransitionProps as ReactCSSTransitionProps } from 'react-transition-group/CSSTransition'; +import { APIOptions } from '../api/api'; import { ComponentHooks } from '../componentbase/componentbase'; import { CSSTransitionProps } from '../csstransition'; import { PassThroughOptions } from '../passthrough'; diff --git a/components/lib/confirmdialog/confirmdialog.d.ts b/components/lib/confirmdialog/confirmdialog.d.ts index a10e6ef8f6..39d8344e3d 100644 --- a/components/lib/confirmdialog/confirmdialog.d.ts +++ b/components/lib/confirmdialog/confirmdialog.d.ts @@ -8,6 +8,7 @@ * */ import * as React from 'react'; +import { CSSTransitionProps as ReactCSSTransitionProps } from 'react-transition-group/CSSTransition'; import { ButtonPassThroughOptions } from '../button/button'; import { ComponentHooks } from '../componentbase/componentbase'; import { DialogProps } from '../dialog'; diff --git a/components/lib/confirmpopup/ConfirmPopup.js b/components/lib/confirmpopup/ConfirmPopup.js index ca428e8536..76c0ea8a9f 100644 --- a/components/lib/confirmpopup/ConfirmPopup.js +++ b/components/lib/confirmpopup/ConfirmPopup.js @@ -1,10 +1,9 @@ import * as React from 'react'; -import { useOnEscapeKey } from '../../lib/hooks/Hooks'; import PrimeReact, { PrimeReactContext, localeOption } from '../api/Api'; import { Button } from '../button/Button'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; -import { useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { OverlayService } from '../overlayservice/OverlayService'; import { Portal } from '../portal/Portal'; import { DomHandler, IconUtils, ObjectUtils, ZIndexUtils, classNames, mergeProps } from '../utils/Utils'; @@ -57,9 +56,16 @@ export const ConfirmPopup = React.memo( const acceptLabel = getPropValue('acceptLabel') || localeOption('accept'); const rejectLabel = getPropValue('rejectLabel') || localeOption('reject'); + const displayOrder = useDisplayOrder('dialog', visibleState); - useOnEscapeKey(overlayRef, props.dismissable && props.closeOnEscape, (event) => { - hide('hide'); + useGlobalOnEscapeKey({ + callback: () => { + if (props.dismissable && props.closeOnEscape) { + hide('hide'); + } + }, + when: visibleState, + priority: [ESC_KEY_HANDLING_PRIORITIES.DIALOG, displayOrder] }); const [bindOverlayListener, unbindOverlayListener] = useOverlayListener({ diff --git a/components/lib/dialog/Dialog.js b/components/lib/dialog/Dialog.js index cfb02ed60f..9b49ad603a 100644 --- a/components/lib/dialog/Dialog.js +++ b/components/lib/dialog/Dialog.js @@ -1,9 +1,8 @@ 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'; -import { useEventListener, useMountEffect, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useEventListener, useGlobalOnEscapeKey, useMountEffect, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { TimesIcon } from '../icons/times'; import { WindowMaximizeIcon } from '../icons/windowmaximize'; import { WindowMinimizeIcon } from '../icons/windowminimize'; @@ -37,6 +36,7 @@ export const Dialog = React.forwardRef((inProps, ref) => { const focusElementOnHide = React.useRef(null); const maximized = props.onMaximize ? props.maximized : maximizedState; const shouldBlockScroll = visibleState && (props.blockScroll || (props.maximizable && maximized)); + const displayOrder = useDisplayOrder('dialog', visibleState); const { ptm, cx, sx, isUnstyled } = DialogBase.setMetaData({ props, @@ -50,18 +50,14 @@ export const Dialog = React.forwardRef((inProps, ref) => { useHandleStyle(DialogBase.css.styles, isUnstyled, { name: 'dialog' }); - useOnEscapeKey(maskRef, props.closable && props.closeOnEscape, (event) => { - const currentTarget = event.currentTarget; - - if (!currentTarget || !currentTarget.primeDialogParams) { - return; - } - - const params = currentTarget.primeDialogParams; - const paramLength = params.length; - - onClose(event); - params.splice(paramLength - 1, 1); + useGlobalOnEscapeKey({ + callback: (event) => { + if (props.closable && props.closeOnEscape) { + onClose(event); + } + }, + when: visibleState, + priority: [ESC_KEY_HANDLING_PRIORITIES.DIALOG, displayOrder] }); const [bindDocumentKeyDownListener, unbindDocumentKeyDownListener] = useEventListener({ type: 'keydown', listener: (event) => onKeyDown(event) }); @@ -319,12 +315,10 @@ export const Dialog = React.forwardRef((inProps, ref) => { const enableDocumentSettings = () => { bindGlobalListeners(); - updateGlobalDialogsRegistry(true); }; const disableDocumentSettings = () => { unbindGlobalListeners(); - updateGlobalDialogsRegistry(false); }; const updateScrollBlocker = () => { @@ -339,7 +333,7 @@ export const Dialog = React.forwardRef((inProps, ref) => { }; const updateGlobalDialogsRegistry = (isMounted) => { - // Update current dialog info in global registry if it is mounted : + // Update current dialog info in global registry if it is mounted and visible: if (isMounted && visibleState) { const newParam = { id: idState, hasBlockScroll: shouldBlockScroll }; @@ -356,7 +350,7 @@ export const Dialog = React.forwardRef((inProps, ref) => { document.primeDialogParams = document.primeDialogParams.toSpliced(currentDialogIndexInRegistry, 1, newParam); } } - // Or remove it from global registry if unmounted: + // Or remove it from global registry if unmounted or invisible: else { document.primeDialogParams = document.primeDialogParams && document.primeDialogParams.filter((param) => param.id !== idState); } @@ -411,6 +405,8 @@ export const Dialog = React.forwardRef((inProps, ref) => { }; useMountEffect(() => { + updateGlobalDialogsRegistry(true); + if (props.visible) { setMaskVisibleState(true); } @@ -452,10 +448,11 @@ export const Dialog = React.forwardRef((inProps, ref) => { useUpdateEffect(() => { updateGlobalDialogsRegistry(true); - }, [shouldBlockScroll]); + }, [shouldBlockScroll, visibleState]); useUnmountEffect(() => { disableDocumentSettings(); + updateGlobalDialogsRegistry(false); DomHandler.removeInlineStyle(styleElement.current); ZIndexUtils.clear(maskRef.current); }); diff --git a/components/lib/hooks/Hooks.js b/components/lib/hooks/Hooks.js index 857a3ca542..d4ee76fa8e 100644 --- a/components/lib/hooks/Hooks.js +++ b/components/lib/hooks/Hooks.js @@ -1,8 +1,10 @@ import { useClickOutside } from './useClickOutside'; import { useCounter } from './useCounter'; import { useDebounce } from './useDebounce'; +import { useDisplayOrder } from './useDisplayOrder'; import { useEventListener } from './useEventListener'; import { useFavicon } from './useFavicon'; +import { ESC_KEY_HANDLING_PRIORITIES, useGlobalOnEscapeKey } from './useGlobalOnEscapeKey'; import { useIntersectionObserver } from './useIntersectionObserver'; import { useInterval } from './useInterval'; import { useMatchMedia } from './useMatchMedia'; @@ -14,34 +16,35 @@ import { useOverlayScrollListener } from './useOverlayScrollListener'; import { usePrevious } from './usePrevious'; import { useResizeListener } from './useResizeListener'; import { useLocalStorage, useSessionStorage, useStorage } from './useStorage'; +import { useStyle } from './useStyle'; import { useTimeout } from './useTimeout'; import { useUnmountEffect } from './useUnmountEffect'; import { useUpdateEffect } from './useUpdateEffect'; -import { useStyle } from './useStyle'; -import { useOnEscapeKey } from './useOnEscapeKey'; export { - usePrevious, - useMountEffect, - useUpdateEffect, - useUnmountEffect, + ESC_KEY_HANDLING_PRIORITIES, + useClickOutside, + useCounter, + useDebounce, + useDisplayOrder, useEventListener, + useFavicon, + useGlobalOnEscapeKey, + useIntersectionObserver, + useInterval, + useLocalStorage, + useMatchMedia, + useMountEffect, + useMouse, + useMove, useOverlayListener, useOverlayScrollListener, + usePrevious, useResizeListener, - useIntersectionObserver, - useInterval, + useSessionStorage, useStorage, useStyle, - useLocalStorage, - useSessionStorage, useTimeout, - useCounter, - useFavicon, - useMouse, - useMove, - useClickOutside, - useDebounce, - useMatchMedia, - useOnEscapeKey + useUnmountEffect, + useUpdateEffect }; diff --git a/components/lib/hooks/hooks.d.ts b/components/lib/hooks/hooks.d.ts index 89f6127bd0..ec3228ccbf 100644 --- a/components/lib/hooks/hooks.d.ts +++ b/components/lib/hooks/hooks.d.ts @@ -292,8 +292,12 @@ export declare function useClickOutside(ref: React.RefObject, callback: */ export declare function useMatchMedia(query: string, when?: boolean): boolean; /** - * Custom hook to use detect escape button click. - * @param {React.RefObject} ref - The ref of the element to detect escape button click. - * @param {*} callback - The callback to run when escape button clicked. + * Custom hook to use detect global escape button click. */ -export declare function useOnEscapeKey(ref: React.RefObject, callback: any): void; +export declare function useGlobalOnEscapeKey(props: { callback: (event: KeyboardEvent) => void; when: boolean; priority: [number, number] }): void; +/** + * Custom hook to use display order of component of one and the same group + * @param {string} group + * @param {boolean} [isVisible] + */ +export declare function useDisplayOrder(group: string, isVisible?: boolean): number | undefined; diff --git a/components/lib/hooks/useOnEscapeKey.js b/components/lib/hooks/useOnEscapeKey.js deleted file mode 100644 index 9f5cd2d874..0000000000 --- a/components/lib/hooks/useOnEscapeKey.js +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react'; -import { useEventListener } from './useEventListener'; - -export const useOnEscapeKey = (ref, condition, callback) => { - const handleEsc = (event) => { - if (event.key === 'Esc' || event.key === 'Escape') { - event.stopImmediatePropagation(); - callback(event); - } - - return; - }; - - const [bindKeyDownListener, unbindKeyDownListener] = useEventListener({ - type: 'keydown', - listener: handleEsc - }); - - React.useEffect(() => { - if (!condition) { - return; - } - - if (!ref.current) { - return; - } - - bindKeyDownListener(); - - return () => { - unbindKeyDownListener(); - }; - }); - - return [ref, callback]; -}; diff --git a/components/lib/image/Image.js b/components/lib/image/Image.js index 61cc1365c8..45236ee0c9 100644 --- a/components/lib/image/Image.js +++ b/components/lib/image/Image.js @@ -1,9 +1,8 @@ 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'; -import { useUnmountEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useGlobalOnEscapeKey, useUnmountEffect } from '../hooks/Hooks'; import { DownloadIcon } from '../icons/download'; import { EyeIcon } from '../icons/eye'; import { RefreshIcon } from '../icons/refresh'; @@ -32,11 +31,6 @@ export const Image = React.memo( const previewButton = React.useRef(null); const zoomOutDisabled = scaleState <= 0.5; const zoomInDisabled = scaleState >= 1.5; - - useOnEscapeKey(maskRef, props.closeOnEscape, () => { - hide(); - }); - const { ptm, cx, sx, isUnstyled } = ImageBase.setMetaData({ props, state: { @@ -47,6 +41,21 @@ export const Image = React.memo( } }); + useGlobalOnEscapeKey({ + callback: () => { + if (props.closeOnEscape) { + hide(); + } + }, + when: maskVisibleState, + priority: [ + ESC_KEY_HANDLING_PRIORITIES.IMAGE, + // Assume that there could be only one image mask activated, so it's safe + // to provide one and the same priority all the time: + 0 + ] + }); + useHandleStyle(ImageBase.css.styles, isUnstyled, { name: 'image' }); const show = () => { diff --git a/components/lib/menu/Menu.js b/components/lib/menu/Menu.js index 37542c885c..ec217e110e 100644 --- a/components/lib/menu/Menu.js +++ b/components/lib/menu/Menu.js @@ -2,12 +2,11 @@ import * as React from 'react'; import PrimeReact, { PrimeReactContext } from '../api/Api'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; -import { useMountEffect, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; import { OverlayService } from '../overlayservice/OverlayService'; import { Portal } from '../portal/Portal'; import { DomHandler, IconUtils, ObjectUtils, UniqueComponentId, ZIndexUtils, classNames, mergeProps } from '../utils/Utils'; import { MenuBase } from './MenuBase'; -import { useOnEscapeKey } from '../../lib/hooks/Hooks'; export const Menu = React.memo( React.forwardRef((inProps, ref) => { @@ -31,9 +30,14 @@ export const Menu = React.memo( const menuRef = React.useRef(null); const listRef = React.useRef(null); const targetRef = React.useRef(null); + const popupMenuDisplayOrder = useDisplayOrder('menu', !!(visibleState && props.popup)); - useOnEscapeKey(targetRef, props.popup && props.closeOnEscape, (event) => { - hide(event); + useGlobalOnEscapeKey({ + callback: (event) => { + hide(event); + }, + when: visibleState && props.popup && props.closeOnEscape, + priority: [ESC_KEY_HANDLING_PRIORITIES.MENU, popupMenuDisplayOrder] }); const [bindOverlayListener, unbindOverlayListener] = useOverlayListener({ diff --git a/components/lib/overlaypanel/OverlayPanel.js b/components/lib/overlaypanel/OverlayPanel.js index 040576ac39..1095f52377 100644 --- a/components/lib/overlaypanel/OverlayPanel.js +++ b/components/lib/overlaypanel/OverlayPanel.js @@ -1,9 +1,8 @@ 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'; -import { useMountEffect, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; import { TimesIcon } from '../icons/times'; import { OverlayService } from '../overlayservice/OverlayService'; import { Portal } from '../portal/Portal'; @@ -54,8 +53,14 @@ export const OverlayPanel = React.forwardRef((inProps, ref) => { when: visibleState }); - useOnEscapeKey(overlayEventListener, props.closeOnEscape, () => { - hide(); + const overlayPanelDisplayOrder = useDisplayOrder('overlay-panel', visibleState); + + useGlobalOnEscapeKey({ + callback: () => { + hide(); + }, + when: visibleState && props.closeOnEscape, + priority: [ESC_KEY_HANDLING_PRIORITIES.OVERLAY_PANEL, overlayPanelDisplayOrder] }); const isOutsideClicked = (target) => { diff --git a/components/lib/password/Password.js b/components/lib/password/Password.js index 8cb3829d95..171d7ef498 100644 --- a/components/lib/password/Password.js +++ b/components/lib/password/Password.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PrimeReact, { PrimeReactContext, localeOption } from '../api/Api'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; -import { useMountEffect, useOnEscapeKey, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useOverlayListener, useUnmountEffect } from '../hooks/Hooks'; import { EyeIcon } from '../icons/eye'; import { EyeSlashIcon } from '../icons/eyeslash'; import { InputText } from '../inputtext/InputText'; @@ -46,10 +46,15 @@ export const Password = React.memo( useHandleStyle(PasswordBase.css.styles, isUnstyled, { name: 'password' }); - useOnEscapeKey(overlayRef, props.feedback, (event) => { - hide(); - }); + const passwordDisplayOrder = useDisplayOrder('password', overlayVisibleState); + useGlobalOnEscapeKey({ + callback: () => { + hide(); + }, + when: overlayVisibleState && props.feedback, + priority: [ESC_KEY_HANDLING_PRIORITIES.PASSWORD, passwordDisplayOrder] + }); const [bindOverlayListener, unbindOverlayListener] = useOverlayListener({ target: elementRef, overlay: overlayRef, diff --git a/components/lib/sidebar/Sidebar.js b/components/lib/sidebar/Sidebar.js index a547a6d898..0a09b627bb 100644 --- a/components/lib/sidebar/Sidebar.js +++ b/components/lib/sidebar/Sidebar.js @@ -1,9 +1,8 @@ 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'; -import { useEventListener, useMountEffect, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useEventListener, useGlobalOnEscapeKey, useMountEffect, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { TimesIcon } from '../icons/times'; import { Portal } from '../portal/Portal'; import { Ripple } from '../ripple/Ripple'; @@ -28,11 +27,14 @@ export const Sidebar = React.forwardRef((inProps, ref) => { const sidebarRef = React.useRef(null); const maskRef = React.useRef(null); const closeIconRef = React.useRef(null); + const sidebarDisplayOrder = useDisplayOrder('sidebar', visibleState); - useOnEscapeKey(maskRef, props.closeOnEscape, (event) => { - if (ZIndexUtils.get(maskRef.current) === ZIndexUtils.getCurrent('modal', (context && context.autoZIndex) || PrimeReact.autoZIndex)) { + useGlobalOnEscapeKey({ + callback: (event) => { onClose(event); - } + }, + when: visibleState && props.closeOnEscape, + priority: [ESC_KEY_HANDLING_PRIORITIES.SIDEBAR, sidebarDisplayOrder] }); const [bindDocumentClickListener, unbindDocumentClickListener] = useEventListener({ diff --git a/components/lib/slidemenu/SlideMenu.js b/components/lib/slidemenu/SlideMenu.js index 4ed06def15..f59ad4056c 100644 --- a/components/lib/slidemenu/SlideMenu.js +++ b/components/lib/slidemenu/SlideMenu.js @@ -2,14 +2,13 @@ import * as React from 'react'; import PrimeReact, { PrimeReactContext } from '../api/Api'; import { useHandleStyle } from '../componentbase/ComponentBase'; import { CSSTransition } from '../csstransition/CSSTransition'; -import { useMountEffect, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useOverlayListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { ChevronLeftIcon } from '../icons/chevronleft'; import { OverlayService } from '../overlayservice/OverlayService'; import { Portal } from '../portal/Portal'; import { DomHandler, IconUtils, UniqueComponentId, ZIndexUtils, mergeProps } from '../utils/Utils'; import { SlideMenuBase } from './SlideMenuBase'; import { SlideMenuSub } from './SlideMenuSub'; -import { useOnEscapeKey } from '../../lib/hooks/Hooks'; export const SlideMenu = React.memo( React.forwardRef((inProps, ref) => { @@ -34,9 +33,14 @@ export const SlideMenu = React.memo( const targetRef = React.useRef(null); const backward = React.useRef(null); const slideMenuContent = React.useRef(null); + const slideMenuDisplayOrder = useDisplayOrder('slide-menu', visibleState); - useOnEscapeKey(targetRef, props.popup && props.closeOnEscape, (event) => { - hide(event); + useGlobalOnEscapeKey({ + callback: (event) => { + hide(event); + }, + when: visibleState && props.popup && props.closeOnEscape, + priority: [ESC_KEY_HANDLING_PRIORITIES.SLIDE_MENU, slideMenuDisplayOrder] }); const [bindOverlayListener, unbindOverlayListener] = useOverlayListener({ diff --git a/components/lib/speeddial/SpeedDial.js b/components/lib/speeddial/SpeedDial.js index 0a78391a90..acd01457cc 100644 --- a/components/lib/speeddial/SpeedDial.js +++ b/components/lib/speeddial/SpeedDial.js @@ -2,7 +2,7 @@ import * as React from 'react'; import { PrimeReactContext } from '../api/Api'; import { Button } from '../button/Button'; import { useHandleStyle } from '../componentbase/ComponentBase'; -import { useEventListener, useMountEffect, useOnEscapeKey, useUpdateEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useEventListener, useGlobalOnEscapeKey, useMountEffect, useUpdateEffect } from '../hooks/Hooks'; import { MinusIcon } from '../icons/minus'; import { PlusIcon } from '../icons/plus'; import { Ripple } from '../ripple/Ripple'; @@ -15,9 +15,13 @@ export const SpeedDial = React.memo( const [idState, setIdState] = React.useState(null); const [focused, setFocused] = React.useState(false); const [focusedOptionIndex, setFocusedOptionIndex] = React.useState(-1); + const isItemClicked = React.useRef(false); + const elementRef = React.useRef(null); + const listRef = React.useRef(null); const context = React.useContext(PrimeReactContext); const props = SpeedDialBase.getProps(inProps, context); const visible = props.onVisibleChange ? props.visible : visibleState; + const speedDialDisplayOrder = useDisplayOrder('speed-dial', visible); const metaData = { props, state: { @@ -27,10 +31,14 @@ export const SpeedDial = React.memo( const { ptm, cx, sx, isUnstyled } = SpeedDialBase.setMetaData(metaData); useHandleStyle(SpeedDialBase.css.styles, isUnstyled, { name: 'speeddial' }); - useOnEscapeKey(elementRef, visible, () => hide()); - const isItemClicked = React.useRef(false); - const elementRef = React.useRef(null); - const listRef = React.useRef(null); + + useGlobalOnEscapeKey({ + callback: () => { + hide(); + }, + when: visible, + priority: [ESC_KEY_HANDLING_PRIORITIES.SPEED_DIAL, speedDialDisplayOrder] + }); const [bindDocumentClickListener, unbindDocumentClickListener] = useEventListener({ type: 'click', diff --git a/components/lib/splitbutton/SplitButton.js b/components/lib/splitbutton/SplitButton.js index 0a20214100..77940871cd 100644 --- a/components/lib/splitbutton/SplitButton.js +++ b/components/lib/splitbutton/SplitButton.js @@ -2,7 +2,7 @@ import * as React from 'react'; import PrimeReact, { PrimeReactContext } from '../api/Api'; import { Button } from '../button/Button'; import { useHandleStyle } from '../componentbase/ComponentBase'; -import { useMountEffect, useOnEscapeKey, useUnmountEffect } from '../hooks/Hooks'; +import { ESC_KEY_HANDLING_PRIORITIES, useDisplayOrder, useGlobalOnEscapeKey, useMountEffect, useUnmountEffect } from '../hooks/Hooks'; import { ChevronDownIcon } from '../icons/chevrondown'; import { OverlayService } from '../overlayservice/OverlayService'; import { TieredMenu } from '../tieredmenu/TieredMenu'; @@ -21,6 +21,7 @@ export const SplitButton = React.memo( const menuRef = React.useRef(null); const defaultButtonRef = React.useRef(null); const overlayRef = React.useRef(null); + const overlayDisplayOrder = useDisplayOrder('split-button-tooltip', overlayVisibleState); const metaData = { props, state: { @@ -32,7 +33,14 @@ export const SplitButton = React.memo( const { ptm, cx, isUnstyled } = SplitButtonBase.setMetaData(metaData); useHandleStyle(SplitButtonBase.css.styles, isUnstyled, { name: 'splitbutton' }); - useOnEscapeKey(overlayRef, overlayVisibleState, () => hide()); + + useGlobalOnEscapeKey({ + callback: () => { + hide(); + }, + when: overlayVisibleState, + priority: [ESC_KEY_HANDLING_PRIORITIES.SPLIT_BUTTON, overlayDisplayOrder] + }); const onPanelClick = (event) => { OverlayService.emit('overlay-click', { diff --git a/components/templates/templateFeaturesAnimation/index.js b/components/templates/templateFeaturesAnimation/index.js index b40daaf977..7c88af6684 100644 --- a/components/templates/templateFeaturesAnimation/index.js +++ b/components/templates/templateFeaturesAnimation/index.js @@ -1,9 +1,9 @@ -import React, { useRef } from 'react' +import React, { useRef } from 'react'; import useAnimatedFeatures from './useAnimatedFeatures'; import TemplateFeaturesAnimationInline from './TemplateFeaturesAnimationInline'; const TemplateFeaturesAnimation = ({ featuresData, title, animationSeconds = 5000 }) => { - const animationRef = useRef(null) + const animationRef = useRef(null); const { selectedID, handleClick } = useAnimatedFeatures(animationRef, featuresData.length, animationSeconds); return ( @@ -44,6 +44,6 @@ const TemplateFeaturesAnimation = ({ featuresData, title, animationSeconds = 500 ); -} +}; -export default TemplateFeaturesAnimation \ No newline at end of file +export default TemplateFeaturesAnimation; diff --git a/pages/templates/index.js b/pages/templates/index.js index 3f073a4957..f0c03cad6f 100644 --- a/pages/templates/index.js +++ b/pages/templates/index.js @@ -18,7 +18,7 @@ const TemplatesPage = () => { Preview - + Learn More