import { from , fromEvent , merge , Observable , Subscribable } from 'rxjs' ; import { filter , map , switchMap , tap } from 'rxjs/operators' ; import { convertCodeElementIdempotent , DiffPart , DOMFunctions , HoveredToken , locateTarget } from './token_position' ; import { isPosition } from './types' ; export type SupportedMouseEvent = 'click' | 'mousemove' | 'mouseover' ; export interface PositionEvent { /**
     * The event object
     */ event : MouseEvent ; /**
     * The type of mouse event that caused this to emit.
     */ eventType : SupportedMouseEvent ; /**
     * The position of the token that the event occured at.
     * or undefined when a target was hovered/clicked that does not correspond to a position (e.g. after the end of the line)
     */ position : HoveredToken | undefined ; /**
     * The current code view.
     */ codeView : HTMLElement ; } export { DOMFunctions , DiffPart } ; export const findPositionsFromEvents = ( { domFunctions , tokenize = true , } ) => ( elements ) : Observable < PositionEvent > => merge ( from ( elements ) . pipe ( switchMap ( element => merge ( fromEvent < MouseEvent > ( element , 'mouseover' ) , fromEvent < MouseEvent > ( element , 'mousemove' ) ) ) , map ( event => ( { event , eventType : event . type as 'mouseover' | 'mousemove' } ) ) , filter ( ( { event } ) => event . currentTarget !== null ) , map ( ( { event , ... rest } ) => ( { event , target : event . target as HTMLElement , codeView : event . currentTarget as HTMLElement , ... rest , } ) ) , tap ( ( { target } ) => { if ( ! tokenize ) { return ; } const code = domFunctions . getCodeElementFromTarget ( target ) ; if ( code ) { convertCodeElementIdempotent ( code ) ; } } ) ) , from ( elements ) . pipe ( switchMap ( element => fromEvent < MouseEvent > ( element , 'click' ) ) , map ( event => ( { event , eventType : 'click' as const } ) ) , filter ( ( ) => { const selection = window . getSelection ( ) ; return selection === null || selection . toString ( ) === '' ; } ) , filter ( ( { event } ) => event . currentTarget !== null ) , map ( ( { event , ... rest } ) => ( { event , target : event . target as HTMLElement , codeView : event . currentTarget as HTMLElement , ... rest , } ) ) ) ) . pipe ( map ( ( { target , codeView , ... rest } ) => { const hoveredToken = locateTarget ( target , domFunctions ) ; const position = isPosition ( hoveredToken ) ? hoveredToken : undefined ; return { position , codeView , ... rest } ; } ) ) ;