import { useCallback , useMemo , useState } from 'react' ; import { MentionAtomChangeHandler , MentionAtomExtension , MentionAtomNodeAttributes , } from '@remirror/extension-mention-atom' ; import { ChangeReason , SuggestChangeHandlerProps } from '@remirror/pm/suggest' ; import { useExtension , useHelpers } from '@remirror/react-core' ; import { MenuNavigationOptions , useMenuNavigation , UseMenuNavigationReturn , } from './use-menu-navigation' ; export interface MentionAtomState < Data extends MentionAtomNodeAttributes = MentionAtomNodeAttributes > extends Pick < SuggestChangeHandlerProps , 'name' | 'query' | 'text' | 'range' > { /**
     * The reason for the change.
     */ reason : ChangeReason ; /**
     * A command that will update the current matching region with the provided
     * attributes. To see what can be accomplished please inspect the type of the attrs which should be passed through.
     */ command : ( attrs : Data ) => void ; } export interface UseMentionAtomReturn < Data extends MentionAtomNodeAttributes = MentionAtomNodeAttributes > extends UseMenuNavigationReturn < Data > { state : MentionAtomState < Data > | null ; } param props export function useMentionAtom < Data extends MentionAtomNodeAttributes = MentionAtomNodeAttributes > ( props ) { const { ignoreMatchesOnDismiss = true , items , direction , dismissKeys , focusOnClick , submitKeys , } = props ; const [ state , setState ] = useState < MentionAtomState < Data > | null > ( null ) ; const helpers = useHelpers ( ) ; const isOpen = ! ! state ; const onDismiss = useCallback ( ( ) => { if ( ! state ) { return false ; } const { range , name } = state ; if ( ignoreMatchesOnDismiss ) { helpers . getSuggestMethods ( ) . addIgnored ( { from : range . from , name , specific : true } ) ; } setState ( null ) ; return true ; } , [ helpers , ignoreMatchesOnDismiss , state ] ) ; const onSubmit = useCallback ( ( item ) => { if ( ! state ) { return false ; } state . command ( item ) ; return true ; } , [ state ] ) ; const menu = useMenuNavigation < Data > ( { items , isOpen , onDismiss , onSubmit , direction , dismissKeys , focusOnClick , submitKeys , } ) ; const { setIndex } = menu ; /**
     * The is the callback for when a suggestion is changed.
     */ const onChange = useCallback ( ( props , command ) => { const { query , range , name , exitReason , changeReason , text } = props ; if ( exitReason ) { setState ( null ) ; return ; } if ( ! changeReason ) { return ; } if ( changeReason !== ChangeReason . Move ) { setIndex ( 0 ) ; } setState ( { query , range , name , reason : changeReason , text , command : ( attrs ) => { command ( attrs ) ; setState ( null ) ; } , } ) ; } , [ setIndex ] ) ; useExtension ( MentionAtomExtension , ( { addHandler } ) => addHandler ( 'onChange' , onChange ) , [ onChange , ] ) ; return useMemo ( ( ) => ( { ... menu , state } ) , [ menu , state ] ) ; } export interface UseMentionAtomProps < Data extends MentionAtomNodeAttributes = MentionAtomNodeAttributes > extends MenuNavigationOptions { /**
     * The list of data from which an index can be calculated. Must include at
     * least an `id` and a `label`.
     */ items : Data [ ] ; default ignoreMatchesOnDismiss ? : boolean ; } export type { MentionAtomNodeAttributes } ;