@mitodl/course-search-utils
Version:
JS utils for interacting with MIT Open Course search
141 lines (140 loc) • 5.55 kB
TypeScript
import React from "react";
import type { History as HHistory } from "history";
import { Facets, SortParam, SearchParams } from "./url_utils";
export * from "./constants";
export * from "./url_utils";
export { buildSearchQuery, SearchQueryParams } from "./search";
export interface Bucket {
key: string;
doc_count: number;
}
export declare type Aggregation = {
doc_count_error_upper_bound?: number;
sum_other_doc_count?: number;
buckets: Bucket[];
};
export declare type Aggregations = Map<string, Aggregation>;
export declare type GetSearchPageSize = (ui: string | null) => number;
export declare const mergeFacetResults: (...args: Aggregation[]) => Aggregation;
export declare const useFacetOptions: (aggregations: Aggregations, activeFacets: Facets) => (group: string) => Aggregation | null;
declare type UseSearchInputsResult = {
/**
* Parameters to be used for a search query.
*
* Typically, these are the parameters of the previous search query. Thus,
* `searchParams.text` may be different from `text` if the has typed new text
* without submitting the search.
*/
searchParams: SearchParams;
setSearchParams: React.Dispatch<React.SetStateAction<SearchParams>>;
/**
* `text` displayed in the UI.
*
* May be different from `searchParams.text` if user has typed new text
* without submitting the search.
*/
text: string;
setText: (text: string) => void;
/**
* Reset `searchParams` and `text`.
*/
clearAllFilters: () => void;
/**
* Toggle a single facet; also sets text -> searchParams.text.
*/
toggleFacet: (name: string, value: string, isEnbaled: boolean) => void;
/**
* Toggle multiple facets; also sets text -> searchParams.text.
*/
toggleFacets: (facets: [string, string, boolean][]) => void;
/**
* Event handler for toggling a single facet; also sets text -> searchParams.text.
*/
onUpdateFacet: ({ target }: {
target: Pick<HTMLInputElement, "value" | "checked" | "name">;
}) => void;
/**
* Input handler for updating `text` (des NOT update `searchParams.text`).
*/
updateText: (event: {
target: {
value: string;
};
}) => void;
/**
* Event handler for clearing `text`; also clears searchParams.text.
*/
clearText: () => void;
/**
* Event handler for updating `searchParams.sort`; also sets text -> searchParams.text.
*/
updateSort: (event: {
target: {
value: string;
};
}) => void;
/**
* Updates `searchParams.sort`; also sets text -> searchParams.text.
*/
updateUI: (newUI: string | null) => void;
/**
* Set `searchParams.text` to the current value of `text`.
*/
submitText: () => void;
};
/**
* Provides state and event handlers for learning resources search UI; state
* includes data for facets, query text, sort order, ui variant (e.g.,
* 'compact').
*
* Note that there are two different state values for search text, `text` and
* `searchParams.text`. In the typical setup:
* - `text` represents the text currently displayed in the UI and updates
* frequently (e.g., on every keypress).
* - `searchParams.text` represents the text used for the currently displayed
* search results and updates less often (e.g., when a user presses "submit"
* or on debounced keypresses).
*
* The provided event handlers for updating other search parameters (sort, ui,
* facets) sync `text` -> `searchParams.text`.
*/
export declare const useSearchInputs: (history: HHistory) => UseSearchInputsResult;
/**
* Sync changes to URL search parameters with `searchParams`, and vice versa.
*
* Pushes a new entry to the history stack every time the URL would change.
*/
export declare const useSyncUrlAndSearch: (history: HHistory, { searchParams, setSearchParams, setText }: Pick<UseSearchInputsResult, "searchParams" | "setSearchParams" | "setText">) => void;
interface PreventableEvent {
preventDefault?: () => void;
type?: string;
}
interface CourseSearchResult {
facetOptions: (group: string) => Aggregation | null;
clearAllFilters: UseSearchInputsResult["clearAllFilters"];
toggleFacet: UseSearchInputsResult["toggleFacet"];
toggleFacets: UseSearchInputsResult["toggleFacets"];
onUpdateFacets: UseSearchInputsResult["onUpdateFacet"];
updateText: UseSearchInputsResult["updateText"];
clearText: React.MouseEventHandler;
updateSort: UseSearchInputsResult["updateSort"];
acceptSuggestion: (suggestion: string) => void;
loadMore: () => void;
incremental: boolean;
text: string;
sort: SortParam | null;
activeFacets: Facets;
/**
* Callback that handles search submission. Pass this to your search input
* submission event target, e.g., `<form onSubmit={onSubmit} />` or
* `<button onClick={onSubmit} />`.
*
* The event target does not need to emit submit events, but if it does, the
* default form action will be prevented.
*/
onSubmit: (e: PreventableEvent) => void;
from: number;
updateUI: (newUI: string | null) => void;
ui: string | null;
}
export declare const useCourseSearch: (runSearch: (text: string, searchFacets: Facets, nextFrom: number, sort?: SortParam | null, ui?: string | null) => Promise<void>, clearSearch: () => void, aggregations: Aggregations, loaded: boolean, searchPageSize: number | GetSearchPageSize, history: HHistory) => CourseSearchResult;