import { Observable , Subject , combineLatest , delay , distinctUntilChanged , distinctUntilKeyChanged , filter , finalize , fromEvent , map , merge , shareReplay , startWith , take , takeLast , takeUntil , tap } from "rxjs" ; import { translation } from "~/_" ; import { getLocation , setToggle , watchElementFocus } from "~/browser" ; import { SearchMessageType , SearchQueryMessage , SearchWorker , defaultTransform , isSearchReadyMessage } from "~/integrations" ; import { Component } from "../../_" ; /**
 * Search query
 */ export interface SearchQuery { value : string ; focus : boolean ; } param el param worker returns export function watchSearchQuery ( el , { rx$ } ) { const fn = __search ?. transform || defaultTransform ; const { searchParams } = getLocation ( ) ; if ( searchParams . has ( "q" ) ) setToggle ( "search" , true ) ; const param$ = rx$ . pipe ( filter ( isSearchReadyMessage ) , take ( 1 ) , map ( ( ) => searchParams . get ( "q" ) || "" ) ) ; param$ . subscribe ( value => { if ( value ) el . value = value ; } ) ; const focus$ = watchElementFocus ( el ) ; const value$ = merge ( fromEvent ( el , "keyup" ) , fromEvent ( el , "focus" ) . pipe ( delay ( 1 ) ) , param$ ) . pipe ( map ( ( ) => fn ( el . value ) ) , startWith ( "" ) , distinctUntilChanged ( ) ) ; return combineLatest ( [ value$ , focus$ ] ) . pipe ( map ( ( [ value , focus ] ) => ( { value , focus } ) ) , shareReplay ( 1 ) ) ; } param el param worker returns export function mountSearchQuery ( el , { tx$ , rx$ } ) { const push$ = new Subject < SearchQuery > ( ) ; push$ . pipe ( distinctUntilKeyChanged ( "value" ) , map ( ( { value } ) : SearchQueryMessage => ( { type : SearchMessageType . QUERY , data : value } ) ) ) . subscribe ( tx$ . next . bind ( tx$ ) ) ; push$ . pipe ( distinctUntilKeyChanged ( "focus" ) ) . subscribe ( ( { focus } ) => { if ( focus ) { setToggle ( "search" , focus ) ; el . placeholder = "" ; } else { el . placeholder = translation ( "search.placeholder" ) ; } } ) ; fromEvent ( el . form ! , "reset" ) . pipe ( takeUntil ( push$ . pipe ( takeLast ( 1 ) ) ) ) . subscribe ( ( ) => el . focus ( ) ) ; return watchSearchQuery ( el , { tx$ , rx$ } ) . pipe ( tap ( state => push$ . next ( state ) ) , finalize ( ( ) => push$ . complete ( ) ) , map ( state => ( { ref : el , ... state } ) ) ) ; }