All files / src/utils state.ts

84.61% Statements 22/26
59.37% Branches 19/32
85.71% Functions 6/7
84% Lines 21/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114      4x 4x                                                         4x                     60x         37x 1x     36x                               241x               60x   176x   176x 37x 37x 139x 139x                 99x 99x   99x                 3x 3x   3x        
import { InputSearchQuery, SearchResult } from "../api/search/generated"
import { AutocompleteConfig } from "../config"
import { History } from "./history"
import { Cancellable, makeCancellable } from "./promise"
import { search } from "../search"
import { SearchAutocompleteOptions } from "../autocomplete"
 
/**
 * @group Autocomplete
 * @category Core
 */
export interface DefaultState {
    /**
     * The current search query object.
     */
    query?: InputSearchQuery
    /**
     * The current search response.
     */
    response?: SearchResult
    /**
     * The history items.
     */
    history?: { item: string }[]
}
 
export type StateActions<State> = {
    updateState(inputValue?: string): PromiseLike<State>
    addHistoryItem(item: string): PromiseLike<State>
    removeHistoryItem(item: string): PromiseLike<State>
    clearHistory(): PromiseLike<State>
}
 
export const getStateActions = <State>({
    config,
    history,
    input,
}: {
    config: Required<AutocompleteConfig<State>>
    history?: History
    input: HTMLInputElement
}): StateActions<State> => {
    let cancellable: Cancellable<State> | undefined
 
    const fetchState = (
        value: string,
        config: AutocompleteConfig<State>,
        options?: SearchAutocompleteOptions
    ): PromiseLike<State> => {
        if (typeof config.fetch === "function") {
            return config.fetch(value)
        } else {
            // @ts-expect-error type mismatch
            return search(
                {
                    query: value,
                    ...config.fetch,
                },
                {
                    track: config.nostoAnalytics ? "autocomplete" : undefined,
                    redirect: false,
                    ...options,
                }
            )
        }
    }
 
    function getHistoryState(query: string): PromiseLike<State> {
        // @ts-expect-error type mismatch
        return Promise.resolve({
            query: {
                query,
            },
            history: history?.getItems(),
        })
    }
 
    return {
        updateState: (inputValue?: string, options?: SearchAutocompleteOptions): PromiseLike<State> => {
            cancellable?.cancel()
 
            if (inputValue && inputValue.length >= config.minQueryLength) {
                cancellable = makeCancellable(fetchState(inputValue, config, options))
                return cancellable.promise
            } else if (history) {
                return getHistoryState(inputValue ?? "")
            }
 
            return (
                // @ts-expect-error type mismatch
                cancellable?.promise ?? Promise.resolve<State>({})
            )
        },
        addHistoryItem: (item: string) => {
            if (history) {
                history.add(item)
            }
            return getHistoryState(input.value)
        },
        removeHistoryItem: (item: string) => {
            Iif (history) {
                history.remove(item)
            }
            return getHistoryState(input.value)
        },
        clearHistory: () => {
            if (history) {
                history.clear()
            }
            return getHistoryState(input.value)
        },
    }
}