From fbd9e72ee20b225e574aa32e16e24e0252339f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Chalifour?= Date: Sun, 7 Feb 2021 11:47:36 +0100 Subject: [PATCH] feat(plugin): add `transformSource` API This updates the plugins' API to allow complete source override, as opposed to only templates override. ## Why Users might want to override the behavior of the original source (e.g., keep the panel open on select). This wasn't possible with the previous API, which only allow to modify the template. ## API ```tsx const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ key: 'search', limit: 3, transformSource({ source, onRemove }) { return { ...source, getItemUrl({ item }) { return `https://google.com?q=${item.query}`; }, }; }, }); const querySuggestionsPlugin = createQuerySuggestionsPlugin({ searchClient, indexName: 'instant_search_demo_query_suggestions', transformSource({ source, onTapAhead }) { return { ...source, onSelect({ setIsOpen }) { setIsOpen(true); }, getItemUrl({ item }) { return `https://google.com?q=${item.query}`; }, templates: { ...source.templates, item(params) { const { item } = params; return ( {source.templates.item(params)} ); }, }, }; }, }); ``` --- .../src/createQuerySuggestionsPlugin.ts | 65 ++++++++++--------- .../createLocalStorageRecentSearchesPlugin.ts | 6 +- .../src/createRecentSearchesPlugin.ts | 61 ++++++++--------- .../createLocalStorageRecentSearchesPlugin.md | 52 +++++++++++++++ .../docs/createQuerySuggestionsPlugin.md | 54 +++++++++++++++ .../docs/createRecentSearchesPlugin.md | 52 +++++++++++++++ 6 files changed, 227 insertions(+), 63 deletions(-) diff --git a/packages/autocomplete-plugin-query-suggestions/src/createQuerySuggestionsPlugin.ts b/packages/autocomplete-plugin-query-suggestions/src/createQuerySuggestionsPlugin.ts index 517baa1a8..50fd25030 100644 --- a/packages/autocomplete-plugin-query-suggestions/src/createQuerySuggestionsPlugin.ts +++ b/packages/autocomplete-plugin-query-suggestions/src/createQuerySuggestionsPlugin.ts @@ -2,14 +2,11 @@ import { AutocompletePlugin, AutocompleteState, } from '@algolia/autocomplete-core'; -import { getAlgoliaHits, SourceTemplates } from '@algolia/autocomplete-js'; +import { AutocompleteSource, getAlgoliaHits } from '@algolia/autocomplete-js'; import { SearchOptions } from '@algolia/client-search'; import { SearchClient } from 'algoliasearch/lite'; -import { - getTemplates as defaultGetTemplates, - GetTemplatesParams, -} from './getTemplates'; +import { getTemplates } from './getTemplates'; import { QuerySuggestionsHit } from './types'; export type CreateQuerySuggestionsPluginParams< @@ -18,7 +15,10 @@ export type CreateQuerySuggestionsPluginParams< searchClient: SearchClient; indexName: string; getSearchParams?(params: { state: AutocompleteState }): SearchOptions; - getTemplates?(params: GetTemplatesParams): SourceTemplates; + transformSource?(params: { + source: AutocompleteSource; + onTapAhead(item: TItem): void; + }): AutocompleteSource; }; export function createQuerySuggestionsPlugin< @@ -27,38 +27,43 @@ export function createQuerySuggestionsPlugin< searchClient, indexName, getSearchParams = () => ({}), - getTemplates = defaultGetTemplates, + transformSource = ({ source }) => source, }: CreateQuerySuggestionsPluginParams): AutocompletePlugin< TItem, undefined > { return { getSources({ query, setQuery, refresh, state }) { + function onTapAhead(item: TItem) { + setQuery(item.query); + refresh(); + } + + const templates = getTemplates({ onTapAhead }); + return [ - { - sourceId: 'querySuggestionsPlugin', - getItemInputValue({ item }) { - return item.query; - }, - getItems() { - return getAlgoliaHits({ - searchClient, - queries: [ - { - indexName, - query, - params: getSearchParams({ state }), - }, - ], - }); - }, - templates: getTemplates({ - onTapAhead(item) { - setQuery(item.query); - refresh(); + transformSource({ + source: { + sourceId: 'querySuggestionsPlugin', + getItemInputValue({ item }) { + return item.query; + }, + getItems() { + return getAlgoliaHits({ + searchClient, + queries: [ + { + indexName, + query, + params: getSearchParams({ state }), + }, + ], + }); }, - }), - }, + templates, + }, + onTapAhead, + }), ]; }, }; diff --git a/packages/autocomplete-plugin-recent-searches/src/createLocalStorageRecentSearchesPlugin.ts b/packages/autocomplete-plugin-recent-searches/src/createLocalStorageRecentSearchesPlugin.ts index 21632dd74..e7b63ff1a 100644 --- a/packages/autocomplete-plugin-recent-searches/src/createLocalStorageRecentSearchesPlugin.ts +++ b/packages/autocomplete-plugin-recent-searches/src/createLocalStorageRecentSearchesPlugin.ts @@ -38,7 +38,7 @@ export type CreateRecentSearchesLocalStorageOptions< type LocalStorageRecentSearchesPluginOptions< TItem extends RecentSearchesItem -> = Pick, 'getTemplates'> & +> = Pick, 'transformSource'> & CreateRecentSearchesLocalStorageOptions; export function createLocalStorageRecentSearchesPlugin< @@ -46,7 +46,7 @@ export function createLocalStorageRecentSearchesPlugin< >({ key, limit = 5, - getTemplates, + transformSource, search = defaultSearch, }: LocalStorageRecentSearchesPluginOptions): AutocompletePlugin< TItem, @@ -59,7 +59,7 @@ export function createLocalStorageRecentSearchesPlugin< }); return createRecentSearchesPlugin({ - getTemplates, + transformSource, storage, }); } diff --git a/packages/autocomplete-plugin-recent-searches/src/createRecentSearchesPlugin.ts b/packages/autocomplete-plugin-recent-searches/src/createRecentSearchesPlugin.ts index 666e1b57f..ea3a2d248 100644 --- a/packages/autocomplete-plugin-recent-searches/src/createRecentSearchesPlugin.ts +++ b/packages/autocomplete-plugin-recent-searches/src/createRecentSearchesPlugin.ts @@ -1,19 +1,12 @@ import { AutocompletePlugin } from '@algolia/autocomplete-core'; -import { SourceTemplates } from '@algolia/autocomplete-js'; -import { MaybePromise, warn } from '@algolia/autocomplete-shared'; +import { AutocompleteSource } from '@algolia/autocomplete-js'; +import { createRef, MaybePromise, warn } from '@algolia/autocomplete-shared'; import { SearchOptions } from '@algolia/client-search'; import { createStore, RecentSearchesStorage } from './createStore'; -import { - getTemplates as defaultGetTemplates, - GetTemplatesParams, -} from './getTemplates'; +import { getTemplates } from './getTemplates'; import { RecentSearchesItem } from './types'; -type Ref = { - current: TType; -}; - export type RecentSearchesPluginData = { getAlgoliaSearchParams(params?: SearchOptions): SearchOptions; }; @@ -22,18 +15,21 @@ export type CreateRecentSearchesPluginParams< TItem extends RecentSearchesItem > = { storage: RecentSearchesStorage; - getTemplates?(params: GetTemplatesParams): SourceTemplates; + transformSource?(params: { + source: AutocompleteSource; + onRemove(id: string): void; + }): AutocompleteSource; }; export function createRecentSearchesPlugin({ storage, - getTemplates = defaultGetTemplates, + transformSource = ({ source }) => source, }: CreateRecentSearchesPluginParams): AutocompletePlugin< TItem, RecentSearchesPluginData > { - const store = createStore(storage); - const lastItemsRef: Ref> = { current: [] }; + const store = createStore(storage); + const lastItemsRef = createRef>([]); return { subscribe({ onSelect }) { @@ -44,7 +40,7 @@ export function createRecentSearchesPlugin({ store.add({ id: inputValue, query: inputValue, - } as TItem); + } as any); } }); }, @@ -55,33 +51,38 @@ export function createRecentSearchesPlugin({ store.add({ id: query, query, - } as TItem); + } as any); } }, getSources({ query, refresh }) { lastItemsRef.current = store.getAll(query); + function onRemove(id: string) { + store.remove(id); + refresh(); + } + + const templates = getTemplates({ onRemove }); + return Promise.resolve(lastItemsRef.current).then((items) => { if (items.length === 0) { return []; } return [ - { - sourceId: 'recentSearchesPlugin', - getItemInputValue({ item }) { - return item.query; - }, - getItems() { - return items; - }, - templates: getTemplates({ - onRemove(id) { - store.remove(id); - refresh(); + transformSource({ + source: { + sourceId: 'recentSearchesPlugin', + getItemInputValue({ item }) { + return item.query; }, - }), - }, + getItems() { + return items; + }, + templates, + }, + onRemove, + }), ]; }); }, diff --git a/packages/website/docs/createLocalStorageRecentSearchesPlugin.md b/packages/website/docs/createLocalStorageRecentSearchesPlugin.md index 9e3729c62..21835171c 100644 --- a/packages/website/docs/createLocalStorageRecentSearchesPlugin.md +++ b/packages/website/docs/createLocalStorageRecentSearchesPlugin.md @@ -110,6 +110,58 @@ function search({ query, items, limit }) { } ``` +### `transformSource` + +> `(params: { source: AutocompleteSource, onRemove: () => void })` + +#### Example + +Keeping the panel open on select: + +```tsx +const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ + key: 'navbar', + transformSource({ source, onRemove }) { + return { + ...source, + onSelect({ setIsOpen }) { + setIsOpen(true); + }, + }; + }, +}); +``` + +Opening a link: + +```tsx +const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ + key: 'navbar', + transformSource({ source, onRemove }) { + return { + ...source, + getItemUrl({ item }) { + return `https://google.com?q=${item.query}`; + }, + templates: { + ...source.templates, + item(params) { + const { item } = params; + return ( + + {source.templates.item(params)} + + ); + }, + }, + }; + }, +}); +``` + ## Returns ### `data` diff --git a/packages/website/docs/createQuerySuggestionsPlugin.md b/packages/website/docs/createQuerySuggestionsPlugin.md index 6b03066b7..254e4416e 100644 --- a/packages/website/docs/createQuerySuggestionsPlugin.md +++ b/packages/website/docs/createQuerySuggestionsPlugin.md @@ -73,3 +73,57 @@ import { createQuerySuggestionsPlugin } from '@algolia/autocomplete-plugin-query ### `getSearchParams` > [`() => SearchParameters`](https://www.algolia.com/doc/api-reference/search-api-parameters/) + +### `transformSource` + +> `(params: { source: AutocompleteSource, onTapAhead: () => void })` + +#### Example + +Keeping the panel open on select: + +```tsx +const querySuggestionsPlugin = createQuerySuggestionsPlugin({ + searchClient, + indexName: 'instant_search_demo_query_suggestions', + transformSource({ source, onTapAhead }) { + return { + ...source, + onSelect({ setIsOpen }) { + setIsOpen(true); + }, + }; + }, +}); +``` + +Opening a link: + +```tsx +const querySuggestionsPlugin = createQuerySuggestionsPlugin({ + searchClient, + indexName: 'instant_search_demo_query_suggestions', + transformSource({ source, onTapAhead }) { + return { + ...source, + getItemUrl({ item }) { + return `https://google.com?q=${item.query}`; + }, + templates: { + ...source.templates, + item(params) { + const { item } = params; + return ( + + {source.templates.item(params)} + + ); + }, + }, + }; + }, +}); +``` diff --git a/packages/website/docs/createRecentSearchesPlugin.md b/packages/website/docs/createRecentSearchesPlugin.md index e37ee9d90..a1b9d72d0 100644 --- a/packages/website/docs/createRecentSearchesPlugin.md +++ b/packages/website/docs/createRecentSearchesPlugin.md @@ -83,6 +83,58 @@ type RecentSearchesStorage = { }; ``` +### `transformSource` + +> `(params: { source: AutocompleteSource, onRemove: () => void })` + +#### Example + +Keeping the panel open on select: + +```tsx +const recentSearchesPlugin = createRecentSearchesPlugin({ + storage, + transformSource({ source, onRemove }) { + return { + ...source, + onSelect({ setIsOpen }) { + setIsOpen(true); + }, + }; + }, +}); +``` + +Opening a link: + +```tsx +const recentSearchesPlugin = createRecentSearchesPlugin({ + storage, + transformSource({ source, onRemove }) { + return { + ...source, + getItemUrl({ item }) { + return `https://google.com?q=${item.query}`; + }, + templates: { + ...source.templates, + item(params) { + const { item } = params; + return ( + + {source.templates.item(params)} + + ); + }, + }, + }; + }, +}); +``` + ## Returns ### `data`