UNPKG

@rc-component/trigger

Version:

base abstract trigger component for react

55 lines (54 loc) 1.86 kB
import React from 'react'; import { useEvent } from '@rc-component/util'; /** * Control the state of popup bind target: * 1. When set `target`. Do show the popup. * 2. When `target` is removed. Do hide the popup. * 3. When `target` change to another one: * a. We wait motion finish of previous popup. * b. Then we set new target and show the popup. * 4. During appear/enter animation, cache new options and apply after animation completes. */ export default function useTargetState() { const [options, setOptions] = React.useState(null); const [open, setOpen] = React.useState(false); const [isAnimating, setIsAnimating] = React.useState(false); const pendingOptionsRef = React.useRef(null); const trigger = useEvent(nextOptions => { if (nextOptions === false) { // Clear pending options when hiding pendingOptionsRef.current = null; setOpen(false); } else { if (isAnimating && open) { // If animating (appear or enter), cache new options pendingOptionsRef.current = nextOptions; } else { setOpen(true); // Set new options setOptions(nextOptions); pendingOptionsRef.current = null; // Only mark as animating when transitioning from closed to open if (!open) { setIsAnimating(true); } } } }); const onVisibleChanged = useEvent(visible => { if (visible) { // Animation enter completed, check if there are pending options setIsAnimating(false); if (pendingOptionsRef.current) { // Apply pending options setOptions(pendingOptionsRef.current); pendingOptionsRef.current = null; } } else { // Animation leave completed setIsAnimating(false); pendingOptionsRef.current = null; } }); return [trigger, open, options, onVisibleChanged]; }