| 15 | import {useLayoutEffect} from './useLayoutEffect'; |
| 16 | |
| 17 | export function useSlot( |
| 18 | initialState: boolean | (() => boolean) = true |
| 19 | ): [RefCallback<any>, boolean] { |
| 20 | // Initial state is typically based on the parent having an aria-label or aria-labelledby. |
| 21 | // If it does, this value should be false so that we don't update the state and cause a rerender when we go through the layoutEffect |
| 22 | let [hasSlot, setHasSlot] = useState(initialState); |
| 23 | let hasRun = useRef(false); |
| 24 | |
| 25 | // A callback ref which will run when the slotted element mounts. |
| 26 | // This should happen before the useLayoutEffect below. |
| 27 | let ref = useCallback((el: any) => { |
| 28 | hasRun.current = true; |
| 29 | setHasSlot(!!el); |
| 30 | }, []); |
| 31 | |
| 32 | // If the callback hasn't been called, then reset to false. |
| 33 | useLayoutEffect(() => { |
| 34 | if (!hasRun.current) { |
| 35 | setHasSlot(false); |
| 36 | } |
| 37 | }, []); |
| 38 | |
| 39 | return [ref, hasSlot]; |
| 40 | } |
| 41 | |
| 42 | interface SlotAria { |
| 43 | id: string | undefined; |