UNPKG

@momentum-ui/react-collaboration

Version:

Cisco Momentum UI Framework for React Collaboration Applications

69 lines (58 loc) 2.44 kB
import { useEffect, useLayoutEffect, useState } from 'react'; import * as PopoverEvents from '../components/Popover/Popover.events'; /** * A custom React hook that manages the ability to close a component which can contain Popovers when the escape key is pressed. * * The hook listens for custom events indicating the addition or removal of tippy instances * that should close when Esc is pressed (e.g., instances with `hideOnEsc = true`). * It maintains a set of such instances and provides a `shouldCloseOnEsc` boolean that determines * whether the parent component should close on Esc press. * * The hook leverages two custom events defined in `Popover.events`: * - `EventType.TIPPY_INSTANCE_ADDED`: Indicates a new Popover instance has been added. * - `EventType.TIPPY_INSTANCE_REMOVED`: Indicates a Popover instance has been removed. * * Each Popover instance is expected to dispatch these events with the instance itself when it is shown and hidden. * * @returns An object containing a single property `shouldCloseOnEsc`, which is `true` if no Popover instances * are currently active (i.e., all have been hidden), and `false` otherwise. * */ export const useShouldCloseOnEsc = (): { shouldCloseOnEsc: boolean } => { const [popoverInstances, setPopoverInstances] = useState(new Set()); const [shouldCloseOnEsc, setShouldCloseOnEsc] = useState(true); const add = (e: CustomEvent) => { setPopoverInstances((prev) => { const newSet = new Set(prev); newSet.add(e); return newSet; }); }; const remove = (e: CustomEvent) => { setPopoverInstances((prev) => { const newSet = new Set(prev); newSet.delete(e); return newSet; }); }; useLayoutEffect(() => { const addId = PopoverEvents.addListener(PopoverEvents.EventType.TIPPY_INSTANCE_ADDED, add); const removeId = PopoverEvents.addListener( PopoverEvents.EventType.TIPPY_INSTANCE_REMOVED, remove ); return () => { PopoverEvents.removeListener(PopoverEvents.EventType.TIPPY_INSTANCE_ADDED, addId); PopoverEvents.removeListener(PopoverEvents.EventType.TIPPY_INSTANCE_REMOVED, removeId); }; }, []); useEffect(() => { const newShouldCloseOnEsc = popoverInstances.size === 0; if (newShouldCloseOnEsc !== shouldCloseOnEsc) { setShouldCloseOnEsc(newShouldCloseOnEsc); } }, [popoverInstances]); return { shouldCloseOnEsc, }; };