UNPKG

@opencage/geosearch-core

Version:
236 lines (212 loc) 7.08 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const isString = (value) => { const type = typeof value; return type === 'string'; }; const checkResponseStatus = (res) => { if (res.ok) { return res; } const err = new Error( `The HTTP status of the reponse: ${res.status} (${res.statusText})` ); err.status = res.status; err.statusText = res.statusText; throw err; }; const debouncePromise = (fn, time) => { let timerId; return (...args) => { if (timerId) { clearTimeout(timerId); } return new Promise((resolve) => { timerId = setTimeout(() => resolve(fn(...args)), time); }); }; }; const uniqByKeepFirst = (a, key) => { const seen = new Set(); return a.filter((item) => { const k = key(item); return seen.has(k) ? false : seen.add(k); }); }; const htmlFooter = ` <div style="display:flex;flex-direction:column;align-items:flex-end;"> <div style="display:flex;align-items:center;justify-content:center;font-family: sans-serif;font-size:0.7em;color:#009966;"> <span><a href="https://opencagedata.com/geosearch" target="_blank" rel="noreferrer"><img src="https://assets.opencagedata.com/opencage-20x21.png" height="21" width="20" border="0" alt="OpenCage" style="display:inline;" /></a></span> <span>&nbsp;&nbsp;Made by <a href="https://opencagedata.com/geosearch" target="_blank" rel="noreferrer" style="text-decoration:none;color:#009966;">OpenCage</a>.</span> <span>&nbsp;&copy;&nbsp;<a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noreferrer" style="text-decoration:none;color:#009966;">OpenStreetMap</a>,</span> <span>&nbsp;<a href="https://opencagedata.com/credits" target="_blank" rel="noreferrer" style="text-decoration:none;color:#009966;">others</a>.</span> </div> </div> `; const SOURCE_ID = 'opencage'; const AWAIT_LABEL = '. . .'; const AWAIT_USER_INPUT = { results: [{ formatted: AWAIT_LABEL }] }; const fn = () => {}; const handleResult = ( { results: returnedResults }, { onActive = fn, onSelect = fn, noResults = 'No results.' } = {} ) => { // filter, to dedupe , results on the attribute `formatted` const results = uniqByKeepFirst(returnedResults, (it) => it.formatted); return [ { sourceId: SOURCE_ID, // // ---- getItems // type: (params: { query: string, state: AutocompleteState, ...setters }) => Item[] | Promise<Item[]> getItems() { return results; }, // // ---- getItemUrl // type: (params: { item: Item, state: AutocompleteState }) => string | undefined // getItemUrl() { // } // // ---- getItemInputValue // type: (params: { item, state: AutocompleteState }) => string` | defaults to `({ state }) => state.query getItemInputValue({ item }) { return item.formatted; }, // // ---- onSelect // type: (params: { state: AutocompleteState, ...setters, event: Event, item: TItem, itemInputValue: string, itemUrl: string, source: AutocompleteSource }) => void` | defaults to `({ setIsOpen }) => setIsOpen(false) onSelect, // // ---- onActive // type: (params: { state: AutocompleteState, ...setters, event: Event, item: TItem, itemInputValue: string, itemUrl: string, source: AutocompleteSource }) => void onActive, // ---- templates: { item({ item }) { return `${item.formatted}`; }, noResults() { return noResults; }, footer({ createElement }) { // type: (params: { state: AutocompleteState<TItem>, source: AutocompleteSource<TItem>, items: TItem[], createElement: Pragma, Fragment: PragmaFrag }) => VNode | string return createElement('div', { dangerouslySetInnerHTML: { __html: htmlFooter, }, }); }, }, // ... }, ]; }; const buildURL = (url, options) => { let result = url; if (!options) return result; // if (options.key) { // result = `${result}&key=${options.key}`; // } if (options.limit) { result = `${result}&limit=${options.limit}`; } if (options.countrycode) { result = `${result}&countrycode=${options.countrycode}`; } if (options.language) { result = `${result}&language=${options.language}`; } if (options.bounds) { result = `${result}&bounds=${options.bounds}`; } return result; }; const OpenCageGeoSearchPlugin = ( options = { debounce: 300, noResults: 'No results.' }, events = {} ) => { const fn = () => {}; let selectedItem = null; const onSelect = (params) => { selectedItem = params.item; if (events.onSelect) events.onSelect(params); }; const onActive = events.onActive || fn; const onSubmit = events.onSubmit || fn; const debouncedFetch = debouncePromise(fetch, options.debounce); return { async getSources({ query }) { // if (!window.fetch) { // console.warn('Please Contact the developer of this website!'); // } if (query === '') { selectedItem = null; return []; } if (!isString(query)) { console.debug('Not a string'); selectedItem = null; return []; } if (query.length < 3) { console.debug('Query is too short'); selectedItem = null; return handleResult(AWAIT_USER_INPUT, { noResults: options.noResults, onActive, onSelect, }); } if (selectedItem) return handleResult( { results: [selectedItem] }, { noResults: options.noResults, onActive, onSelect } ); const url = buildURL( `https://api.opencagedata.com/geosearch?q=${query}`, options ); const headers = { 'OpenCage-Geosearch-Key': options.key, }; return debouncedFetch(url, { headers, mode: 'cors' }) .then(checkResponseStatus) .then((response) => { if (response.ok) return response.json(); console.log(response.statusText); throw response.statusText; }) .then((apiResponse) => handleResult(apiResponse, { noResults: options.noResults, onActive, onSelect, }) ) .catch((err) => { console.error(`[Opencage GeoSearch error]: ${err.message}`); console.error(`[error] status: ${err.status}`); console.error(`[error] statusText: ${err.statusText}`); return []; }); }, // ---- onSubmit // type: (params: { state: AutocompleteState, event: Event, ...setters }) => void onSubmit, // ---- onReset // type: (params: { state: AutocompleteState, event: Event, ...setters: AutocompleteSetters }) => void onReset: () => { selectedItem = null; }, }; }; var index = { OpenCageGeoSearchPlugin }; exports.OpenCageGeoSearchPlugin = OpenCageGeoSearchPlugin; exports.default = index;