1import { useCallback, useRef, useState } from "react";
2
3import type { ComposerTrigger } from "../../composer-logic";
4
5/** Keep a dismissed suggestion closed until the caret leaves its token. */
6export function useComposerTriggerState(initialTrigger: () => ComposerTrigger | null) {
7 const [trigger, setActiveTrigger] = useState(initialTrigger);
8 const dismissedTriggerRef = useRef<ComposerTrigger | null>(null);
9
10 const resolveTrigger = useCallback((candidate: ComposerTrigger | null) => {
11 const dismissed = dismissedTriggerRef.current;
12 return candidate &&
13 dismissed &&
14 candidate.kind === dismissed.kind &&
15 candidate.rangeStart === dismissed.rangeStart
16 ? null
17 : candidate;
18 }, []);
19
20 const setTrigger = useCallback(
21 (candidate: ComposerTrigger | null) => {
22 const activeTrigger = resolveTrigger(candidate);
23 if (candidate === null || activeTrigger !== null) {
24 dismissedTriggerRef.current = null;
25 }
26 setActiveTrigger(activeTrigger);
27 },
28 [resolveTrigger],
29 );
30
31 const dismissTrigger = useCallback((candidate: ComposerTrigger | null) => {
32 dismissedTriggerRef.current = candidate;
33 setActiveTrigger(null);
34 }, []);
35
36 const resetTrigger = useCallback((candidate: ComposerTrigger | null) => {
37 dismissedTriggerRef.current = null;
38 setActiveTrigger(candidate);
39 }, []);
40
41 return { trigger, setTrigger, resolveTrigger, dismissTrigger, resetTrigger };
42}