diff --git a/src/Geosuggest.tsx b/src/Geosuggest.tsx index 417643c..59676f4 100644 --- a/src/Geosuggest.tsx +++ b/src/Geosuggest.tsx @@ -372,10 +372,12 @@ export default class GeoSuggest extends React.Component { suggests.push({ ...fixture, isFixture: true, - matchedSubstrings: { - length: userInput.length, - offset: fixture.label.indexOf(userInput) - }, + matchedSubstrings: [ + { + length: userInput.length, + offset: fixture.label.search(regex) + } + ], placeId: fixture.placeId || fixture.label }); } @@ -390,7 +392,7 @@ export default class GeoSuggest extends React.Component { label: this.props.getSuggestLabel ? this.props.getSuggestLabel(suggest) : '', - matchedSubstrings: suggest.matched_substrings[0], + matchedSubstrings: suggest.matched_substrings, placeId: suggest.place_id }); } diff --git a/src/suggest-item.tsx b/src/suggest-item.tsx index 5b89373..8d2386a 100644 --- a/src/suggest-item.tsx +++ b/src/suggest-item.tsx @@ -43,12 +43,8 @@ export default class SuggestItem extends React.PureComponent { /** * Makes a text bold */ - makeBold(element: string, key: string): JSX.Element { - return ( - - {element} - - ); + makeBold(element: string) { + return {element}; } /** @@ -59,31 +55,30 @@ export default class SuggestItem extends React.PureComponent { return suggest.label; } - const start: number = suggest.matchedSubstrings.offset; - const length: number = suggest.matchedSubstrings.length; - const end: number = start + length; - const boldPart = this.makeBold( - suggest.label.substring(start, end), - suggest.label - ); + const parts = []; - let pre = ''; - let post = ''; + let previousEnd = 0; + + for (const {offset: start, length} of suggest.matchedSubstrings) { + // Add non-matching substring before and between matches + if (start > previousEnd) { + parts.push(suggest.label.substring(previousEnd, start)); + } - if (start > 0) { - pre = suggest.label.slice(0, start); + // Add matching substring as bold text + const end = start + length; + const match = this.makeBold(suggest.label.substring(start, end)); + parts.push(match); + + previousEnd = end; } - if (end < suggest.label.length) { - post = suggest.label.slice(end); + + // Add non-matching substring after matches + if (previousEnd < suggest.label.length) { + parts.push(suggest.label.substring(previousEnd)); } - return ( - - {pre} - {boldPart} - {post} - - ); + return {parts}; } /** diff --git a/src/types/suggest.ts b/src/types/suggest.ts index 6f86d64..2dc02b7 100644 --- a/src/types/suggest.ts +++ b/src/types/suggest.ts @@ -13,6 +13,6 @@ export interface Suggest { readonly matchedSubstrings?: { offset: number; length: number; - }; + }[]; readonly className?: string; } diff --git a/test/Geosuggest_spec.tsx b/test/Geosuggest_spec.tsx index 65fc1c4..c8d0dc4 100644 --- a/test/Geosuggest_spec.tsx +++ b/test/Geosuggest_spec.tsx @@ -870,13 +870,28 @@ describe('Component: Geosuggest', () => { expect(matchedText).to.have.lengthOf.at.least(1); }); - it('should render a match with minial nodes', () => { + it('should highlight multiple matched substrings', () => { const geoSuggestInput = component.container.querySelector( '.geosuggest__input' ) as HTMLInputElement; fireEvent.change(geoSuggestInput, {target: {value: 'Newa'}}); geoSuggestInput.focus(); + const geoSuggestItems = + component.container.getElementsByClassName('geosuggest__item'); + const matchedText = geoSuggestItems[0].getElementsByClassName( + 'geosuggest__item__matched-text' + ); + expect(matchedText).to.have.lengthOf(2); + }); + + it('should render a match with minimal nodes', () => { + const geoSuggestInput = component.container.querySelector( + '.geosuggest__input' + ) as HTMLInputElement; + fireEvent.change(geoSuggestInput, {target: {value: 'New Jersey'}}); + geoSuggestInput.focus(); + const geoSuggestItems = component.container.getElementsByClassName('geosuggest__item'); expect(geoSuggestItems).to.have.lengthOf(1); diff --git a/test/fixtures/predictions.ts b/test/fixtures/predictions.ts index 02a6ed1..060290c 100644 --- a/test/fixtures/predictions.ts +++ b/test/fixtures/predictions.ts @@ -149,6 +149,10 @@ export default function predictions(): google.maps.places.AutocompletePrediction { length: 2, offset: 0 + }, + { + length: 2, + offset: 8 } ], place_id: 'ChIJHQ6aMnBTwokRc-T-3CrcvOE',