import { Control as LeafletControl, ControlPosition, FeatureGroup, FitBoundsOptions, Marker, MarkerOptions, PopupOptions, ZoomPanOptions, Map as LeafletMap } from 'leaflet'; import SearchElement from './SearchElement'; import ResultList from './resultList'; import { SearchArgument, SearchResult } from './providers/provider'; import { Provider } from './providers/index'; /** a provider and the name the provider select shows for it */ export interface ProviderChoice { label: string; provider: Provider; } /** a provider of the control and its place in `providers` */ export interface ProviderInfo extends ProviderChoice { index: number; } /** what the provider select is set to, one provider or all of them */ export type SelectedProvider = ProviderInfo | { index: 'all'; label: string; }; interface SearchControlProps { /** the provider to use for searching */ provider: Provider; /** * several providers instead of one. With more than one, a select next to * the input lets the user pick one of them, or all of them */ providers: ProviderChoice[]; /** * show the provider select. Hidden, the control still uses the providers, * e.g. for `fallback` * @default true */ showProviderSelect: boolean; /** * the name of the select option that searches all providers at once. * `false` leaves the option out, the first provider is selected then * @default 'All' */ allProvidersLabel: string | false; /** * the accessible name of the provider select * @default 'Search with' */ providerSelectLabel: string; /** * when the selected provider fails ('error'), or also when it finds * nothing ('empty'), search the next provider in `providers` * @default false */ fallback: false | 'error' | 'empty'; /** the leaflet position to render the element in */ position: ControlPosition; /** * the stye of the search element * @default bar **/ style: 'button' | 'bar'; marker: MarkerOptions; maxMarkers: number; showMarker: boolean; showPopup: boolean; /** * give the marker a popup with the result. Off, the marker has no popup * and showPopup is ignored * @default true */ markerPopup: boolean; /** * where the result list opens. 'auto' opens it above the input when the * control sits in a bottom corner of the map * @default 'below' */ resultListPosition: 'below' | 'above' | 'auto'; /** * the colors of the control. 'auto' follows the dark or light color scheme * of the system. The colors are css variables, see the docs to set your own * @default 'light' */ theme: 'light' | 'dark' | 'auto'; /** * passed to Leaflet's bindPopup, e.g. `{ maxWidth: 200, className: 'my-popup' }` * @default {} */ popupOptions: PopupOptions; popupFormat(args: { query: Selection; result: SearchResult; /** the provider that found the result */ provider?: ProviderInfo; }): string; resultFormat(args: { result: SearchResult; /** the provider that found the result */ provider?: ProviderInfo; }): string; searchLabel: string; clearSearchLabel: string; notFoundMessage: string; messageHideDelay: number; animateZoom: boolean; /** * fly to a result with Leaflet's flyTo and flyToBounds instead of jumping * there. An object is passed to them, e.g. `{ duration: 1.5 }` * @default false */ flyTo: boolean | ZoomPanOptions; zoomLevel: number; retainZoomLevel: boolean; /** * fit the map to the bounds of a result that has them. Off, every result * is shown at `zoomLevel` * @default true */ zoomToBounds: boolean; /** * passed to Leaflet's fitBounds, e.g. `{ maxZoom: 16, padding: [50, 50] }` * @default {} */ fitBoundsOptions: FitBoundsOptions; /** * when a draggable marker is dropped, look up the address at its new * position with the provider that found the result, and update the popup * (and the input with keepResult). Fires geosearch/marker/reverse * @default false */ reverseOnDragEnd: boolean; classNames: { container: string; button: string; resetButton: string; msgbox: string; form: string; input: string; resultlist: string; item: string; notfound: string; providerSelect: string; }; autoComplete: boolean; autoCompleteDelay: number; maxSuggestions: number; autoClose: boolean; keepResult: boolean; updateMap: boolean; resetButton: string; /** * html of the search button instead of the magnifying glass, e.g. an svg. * Use currentColor, so it follows the theme. It is put into the page as * html, so don't pass text from users * @default '' */ searchIcon: string; /** * search the provider again when a suggestion is picked, even if the * suggestion already has coordinates (the previous behaviour) * @default false */ requeryOnSelect: boolean; /** * the number of characters to type before autocomplete searches * @default 1 */ minQueryLength: number; /** * how many search results to keep in memory, so the same text isn't * requested twice. 0 disables the cache * @default 0 */ cacheSize: number; /** * pressing enter shows the result list to pick from, instead of jumping * to the first result. Works with autoComplete off too, so the provider * is only searched on enter * @default false */ showResultListOnSubmit: boolean; } /** the texts of the control that setLabels can change */ export interface SearchControlLabels { searchLabel: string; clearSearchLabel: string; notFoundMessage: string; providerSelectLabel: string; } export type SearchControlOptions = Partial & ({ provider: Provider; } | { providers: ProviderChoice[]; }); interface Selection { query: string; data?: SearchResult; } interface SearchOutcome { results: SearchResult[]; errors: { error: unknown; provider: ProviderInfo; }[]; } interface SearchControl { options: Omit & { provider?: SearchControlProps['provider']; providers?: SearchControlProps['providers']; }; /** the providers in the order of `providers`, or the single `provider` */ choices: ProviderInfo[]; /** index of the selected provider, or 'all' */ selection: number | 'all'; providerSelect?: HTMLSelectElement; /** which provider found a result, for the formatters and events */ sources: WeakMap; /** theme and list position classes, also used by the bar container */ modifierClasses: string[]; /** the latest reverse lookup of each marker, older answers are dropped */ reverseIds?: WeakMap; markers: FeatureGroup; searchElement: SearchElement; resultList: ResultList; classNames: SearchControlProps['classNames']; container: HTMLDivElement; input: HTMLInputElement; button: HTMLAnchorElement; resetButton: HTMLAnchorElement; map: LeafletMap; /** text of the last autocomplete search, to skip repeats */ lastQuery: string; /** increments whenever pending autocomplete results become stale */ searchId: number; abortController?: AbortController; /** recent results by query text, oldest first (see cacheSize) */ cache?: Map; setup(options: SearchControlOptions): void; onSubmit(result: Selection): void; open(): void; close(): void; onClick(event: Event): void; clearResults(event?: KeyboardEvent | null, force?: boolean): void; autoSearch(event: KeyboardEvent): void; suggest(query: string): Promise; cancelSearch(): void; searchProvider(choice: ProviderInfo, args: SearchArgument & { data?: SearchResult; }, useCache?: boolean): Promise; runSearch(args: SearchArgument & { data?: SearchResult; }, only?: ProviderInfo): Promise; reportErrors(outcome: SearchOutcome, query: string, source: 'autocomplete' | 'submit'): void; handleError(error: unknown, query: string, source: 'autocomplete' | 'submit', provider?: ProviderInfo): void; /** select a provider by its index in `providers`, or 'all' */ selectProvider(index: number | 'all'): void; getSelectedProvider(): SelectedProvider; /** the providers of the control, in the order of `providers` */ getProviders(): ProviderInfo[]; setProviderSelectVisible(visible: boolean): void; /** clears the input, the results and the markers, and drops running searches */ reset(): void; /** puts text into the input without searching */ setQuery(query: string): void; /** changes the texts of the control, e.g. when the language changes */ setLabels(labels: Partial): void; formatResult(args: { result: SearchResult; }): string; selectResult(event: KeyboardEvent): void; showResult(result: SearchResult, query: Selection): void; addMarker(result: SearchResult, selection: Selection): void; reverseMarker(marker: Marker, result: SearchResult): Promise; centerMap(result: SearchResult): void; closeResults(): void; getZoom(): number; onAdd(map: LeafletMap): HTMLDivElement; onRemove(): SearchControl; } interface SearchControlConstructor { new (...options: any[]): SearchControl & LeafletControl; (...options: any[]): SearchControl & LeafletControl; } declare const SearchControl: SearchControlConstructor; export default SearchControl;