diff --git a/examples/geo/components/itemContents/itemContents.jsx b/examples/geo/components/itemContents/itemContents.jsx index 5efebc6..59e0c83 100644 --- a/examples/geo/components/itemContents/itemContents.jsx +++ b/examples/geo/components/itemContents/itemContents.jsx @@ -26,11 +26,15 @@ export default function ItemContents(props) { index, item, query, - searchType = 'startswith' + searchType = 'startswith', + setSelected, + totalItems } = props const globalMatch = searchType === 'contains' + const isNYC = item.name === 'New York City, New York, United States' + const matchedText = (includeSeparator) => { return ( { - return item.name === 'New York City, New York, United States' - ?
{item.name}
+ return isNYC + ?
{item.name}
: void 0 } + const SubLocations = () => { + if(totalItems <= 5 && (item.neighbourhoods || item.attractions)) { + const neighbourhoods = (totalItems > 1) ? item.neighbourhoods.slice(0,5) : item.neighbourhoods + const attractions = (totalItems > 1) ? item.attractions.slice(0,5) : item.attractions + + return ( +
+ + +
+ ) + } + return null + } + + const SubLocationList = (props) => { + const { title, data } = props + + if(!data || !data.length) return null + + return ( +
+
{title}
+ <> + { + data.map( + (value, index) => + + {value.name.split(',')[0]} + + ) + } + +
+ ) + } + + const SubLocation = (props) => { + const { children, value } = props + + const handleClick = (evt, value) => { + evt.stopPropagation() + setSelected(value, 'name') + } + + return ( +
+
handleClick(evt, value)}> + {children} +
+
+ ) + } + const firstItem = () => { return (
{img()} -
{matchedText(false)}
+
{matchedText(false)}
+ {SubLocations()}
) } diff --git a/examples/geo/components/itemContents/itemContents.module.css b/examples/geo/components/itemContents/itemContents.module.css index 1f72e4b..ccc972a 100644 --- a/examples/geo/components/itemContents/itemContents.module.css +++ b/examples/geo/components/itemContents/itemContents.module.css @@ -1,4 +1,5 @@ -.first > div { +.first > .imgContainer, +.first > .nameContainer { display: inline-block; height: 50px; vertical-align: middle; @@ -25,4 +26,36 @@ .match { font-weight: 600; color: #000; +} + +.sublocations { + display: block; + padding-top: 10px; + padding-left: 48px; +} + +.sublocationList { + display: inline-block; + margin-right: 40px; + font-size: 15px; +} + +.subLocationTitle { + text-transform: uppercase; + font-size: 0.8em; + color: #777; + margin-bottom: 3px; + margin-left: 10px; +} + +.sublocation { + display:inline-block; + padding: 2px 10px 3px; + color: rgb(118, 58, 214); +} + +.sublocation:hover { + color: #fff; + background: rgb(118, 58, 214); + border-radius: 15px; } \ No newline at end of file diff --git a/package.json b/package.json index 734806e..f8edccb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "turnstone", - "version": "0.4.2", + "version": "0.5.0", "description": "In development. React multi-search autocomplete component.", "author": "Tom Southall", "keywords": [], diff --git a/src/lib/actions/actions.js b/src/lib/actions/actions.js index 5b3615d..df4436c 100644 --- a/src/lib/actions/actions.js +++ b/src/lib/actions/actions.js @@ -51,11 +51,11 @@ export const highlightNext = () => { } } -export const setSelected = (index) => { - return { - type: types.SET_SELECTED, - index - } +export const setSelected = (i) => { + const type = types.SET_SELECTED + return (typeof i === 'object') + ? { type, item: i } + : { type, index: i } } export const clearSelected = () => { diff --git a/src/lib/actions/actions.test.js b/src/lib/actions/actions.test.js index 3e8ef72..3493684 100644 --- a/src/lib/actions/actions.test.js +++ b/src/lib/actions/actions.test.js @@ -61,12 +61,21 @@ describe('Actions', () => { }) }) - test('setSelected returns expected action', () => { - const action = actions.setSelected(0) + test('setSelected returns expected actions', () => { + const item = {value: {name: 'foobar'}, text: 'foobar'} + let action = actions.setSelected(0) + expect(action).toEqual({ type: 'SET_SELECTED', index: 0 }) + + action = actions.setSelected(item) + + expect(action).toEqual({ + type: 'SET_SELECTED', + item + }) }) test('clearSelected returns expected action', () => { diff --git a/src/lib/components/item.jsx b/src/lib/components/item.jsx index 5968007..6479647 100644 --- a/src/lib/components/item.jsx +++ b/src/lib/components/item.jsx @@ -37,6 +37,14 @@ export default function Item(props) { dispatch(setSelected(index)) } + const setCustomSelected = (value, displayField) => { + dispatch(setSelected({ + value, + displayField, + text: value[displayField] + })) + } + const itemContents = (ItemContents) ? : (state.props.matchText diff --git a/src/lib/reducers/reducer.js b/src/lib/reducers/reducer.js index 182abec..63712ee 100644 --- a/src/lib/reducers/reducer.js +++ b/src/lib/reducers/reducer.js @@ -1,5 +1,6 @@ import * as types from '../actions/actionTypes' import undef from '../utils/undef' +import isUndefined from '../utils/isUndefined' const highlightedItem = (index, items) => { if(!items[index]) return undef @@ -8,7 +9,7 @@ const highlightedItem = (index, items) => { const reducer = (state, action) => { const newState = (() => { - let newState + let newState, item switch (action.type) { case types.SET_QUERY: @@ -66,10 +67,8 @@ const reducer = (state, action) => { ? { highlighted: highlightedItem(state.highlighted.index + 1, state.items) } : {} case types.SET_SELECTED: - return { - selected: state.items[action.index], - query: state.items[action.index].text, - } + item = isUndefined(action.index) ? action.item : state.items[action.index] + return { selected: item, query: item.text } default: throw new Error('Invalid action type passed to reducer') }