import React from "react" ; import { useRefValue , useStateRef } from "../hooks/ReactHooks" ; import { BlockIDStr , useBlocksStore } from "./store/BlocksStore" ; import { observer } from "mobx-react-lite" ; export interface ICommand { /**
     * Handle the action with the following types:
     *
     * replace: replace the text in the editor with the selected action text.
     *
     */ readonly type : 'replace' ; } export interface IActionMenuItem { /**
     * A unique id for the action so that we can handle it on the callback.
     */ readonly id : string ; readonly text : string ; readonly action : ( id : BlockIDStr ) => ICommand | undefined ; } export interface IActionMenuPosition { readonly top : number ; readonly left : number ; } export type TriggerStr = string [ 1 ] | string [ 2 ] ; /**
 * Provide a list of action items we should execute and provide a prompt to
 * filter the results such that the set of actions is applicable to the prompt.
 */ export type ActionMenuItemProvider = ( prompt : string ) => ReadonlyArray < IActionMenuItem > ; interface IProps { readonly id : BlockIDStr ; /**
     * The trigger string (may be 1 or two characters in length);
     */ readonly trigger : TriggerStr ; /**
     * A provider for resolving the items that the user can select form their input.
     */ readonly itemsProvider : ActionMenuItemProvider ; readonly children : JSX . Element ; } export const NoteActionMenu = observer ( function NoteActionMenu ( props ) { interface NoteMenuItemProps extends IActionMenuItem { readonly menuID : number ; } const NoteActionMenuItem = React . memo ( function NoteActionMenuItem ( props ) { const { menuID } = props ; return null ; } ) ; return props . children ; } ) ; /**
 * The trigger handler determines when the action menu is triggered / activated
 * when the user is typing and their specific trigger string is used.
 */ function createTriggerHandler ( trigger ) { let last ; return ( event ) : boolean => { try { switch ( trigger . length ) { case 1 : return event . key === trigger [ 0 ] ; case 2 : return last === trigger [ 0 ] && event . key === trigger [ 1 ] ; } } finally { last = event . key ; } return false ; } ; } interface IPrompt { /**
     * The RAW prompt with no trigger removal
     */ readonly raw : string ; /**
     * The prompt with the trigger removed.
     */ readonly prompt : string ; } interface PromptManager { readonly reset : ( ) => void ; /**
     * Update the prompt and return the current value.
     */ readonly update : ( event : KeyboardEvent ) => IPrompt ; } /**
 * The prompt manager takes events form the keyboard, and construct them to
 * build a snapshot of what the ckeditor text should be at the cursor prompt
 * without having to deal with ckeditor nonsense
 */ function usePromptManager ( trigger ) { const promptRef = React . useRef ( "" ) ; const reset = React . useCallback ( ( ) => { promptRef . current = '' ; } , [ ] ) ; const update = React . useCallback ( ( event ) => { switch ( event . key ) { case 'Backspace' : if ( promptRef . current !== '' ) { promptRef . current = promptRef . current . substr ( 0 , promptRef . current . length - 1 ) ; } break ; case 'Escape' : case 'Command' : case 'Enter' : case 'ArrowUp' : case 'ArrowDown' : case 'Shift' : console . log ( "FIXME 111" ) ; break ; default : promptRef . current = promptRef . current + event . key ; break ; } function computeResultWithoutTrigger ( ) { const start = trigger . length ; const raw = promptRef . current ; if ( raw . length < start ) { return { raw , prompt : "" } ; } const prompt = raw . substring ( start ) ; return { raw , prompt } ; } return computeResultWithoutTrigger ( ) ; } , [ trigger ] ) ; return React . useMemo ( ( ) : PromptManager => ( { reset , update } ) , [ reset , update ] ) ; }