diff --git a/examples/_shared/defaultListbox.js b/examples/_shared/defaultListbox.js index 017968c..24c389d 100644 --- a/examples/_shared/defaultListbox.js +++ b/examples/_shared/defaultListbox.js @@ -1,4 +1,4 @@ -const defaultListbox = [ +export const defaultListbox = [ { name: 'Recent Searches', displayField: 'name', data: [ { name: 'New Orleans, Louisiana, United States', coords: '29.95465,-90.07507' }, { name: 'Chicago, Illinois, United States', coords: '41.85003,-87.65005' }, @@ -17,4 +17,13 @@ const defaultListbox = [ } ] -export default defaultListbox \ No newline at end of file +export const defaultListboxNoRecentSearches = [ + { name: 'Popular Cities', displayField: 'name', data: [ + { name: 'Paris, France', coords: '48.86425, 2.29416' }, + { name: 'Rome, Italy', coords: '41.89205, 12.49209' }, + { name: 'Orlando, Florida, United States', coords: '28.53781, -81.38592' }, + { name: 'London, England', coords: '51.50420, -0.12426' }, + { name: 'Barcelona, Spain', coords: '41.40629, 2.17555' } + ] + } +] \ No newline at end of file diff --git a/examples/geo/App.jsx b/examples/geo/App.jsx index 7486afa..058644e 100644 --- a/examples/geo/App.jsx +++ b/examples/geo/App.jsx @@ -2,9 +2,10 @@ import React, { useCallback, useState } from 'react' import Turnstone from '../../src/lib' import styles from './styles/App.module.css' import autocompleteStyles from './styles/autocomplete.module.css' -import defaultListbox from '../_shared/defaultListbox' +import { defaultListboxNoRecentSearches } from '../_shared/defaultListbox' import ItemContents from './components/itemContents/itemContents' import GroupName from './components/groupName/groupName' +import recentSearchesPlugin from '../../plugins/turnstone-recent-searches' import undef from '../../src/lib/utils/undef' const maxItems = 10 @@ -39,7 +40,6 @@ const App = () => { const onSelect = useCallback( (item, displayField) => { - console.log({item, displayField}) setSelected({item, displayField}) }, [] ) @@ -65,7 +65,7 @@ const App = () => { autoFocus={false} clearButton={true} debounceWait={250} - defaultListbox={defaultListbox} + defaultListbox={defaultListboxNoRecentSearches} defaultListboxIsImmutable={false} errorMessage={'Sorry, something has broken!'} id='autocomplete' @@ -78,6 +78,7 @@ const App = () => { onEnter={onEnter} onTab={onTab} placeholder={placeholder} + plugins={[[recentSearchesPlugin, {ratio: 2, name: 'Recent'}]]} styles={autocompleteStyles} GroupName={GroupName} ItemContents={ItemContents} diff --git a/plugins/turnstone-recent-searches/index.jsx b/plugins/turnstone-recent-searches/index.jsx new file mode 100644 index 0000000..b652df9 --- /dev/null +++ b/plugins/turnstone-recent-searches/index.jsx @@ -0,0 +1,45 @@ +import { useCallback } from 'react' +import { useLocalStorage } from 'react-use' + +const recentSearchesPlugin = (Container, containerProps = {}, pluginProps = {}) => { + const { + ratio = 1, + id, + name = 'Recent Searches' + } = pluginProps + const [recentSearches, setRecentSearches] = useLocalStorage('recentSearches', []) + + const buildDefaultListBox = (recentSearches) => { + return [ + {id, name, displayField: '_displayField', data: recentSearches, ratio}, + ...containerProps.defaultListbox + ] + } + + const onSelect = useCallback( + (selectedResult, displayField) => { + if(selectedResult) { + selectedResult._displayField = selectedResult[displayField] + const searches = [ + selectedResult, + ...recentSearches.filter( + item => item._displayField !== selectedResult._displayField + ) + ] + setRecentSearches(searches) + } + + if (typeof containerProps.onSelect === 'function') + containerProps.onSelect(selectedResult, displayField) + }, [] + ) + + const newContainerProps = { + ...containerProps, + ...{defaultListbox: buildDefaultListBox(recentSearches), onSelect} + } + + return [Container, newContainerProps] +} + +export default recentSearchesPlugin \ No newline at end of file diff --git a/src/lib/reducers/reducer.test.js b/src/lib/reducers/reducer.test.js index e630093..f8e1d06 100644 --- a/src/lib/reducers/reducer.test.js +++ b/src/lib/reducers/reducer.test.js @@ -2,7 +2,7 @@ import { describe, expect, test } from 'vitest' import reducer from './reducer' import * as actions from '../actions/actions' import undef from '../utils/undef' -import defaultListbox from '../../../examples/_shared/defaultListbox' +import { defaultListbox } from '../../../examples/_shared/defaultListbox' describe('SET_QUERY action', () => { test('produces expected new state', () => {