import { HighlightedValue } from '@yext/search-headless-react'; import React from 'react'; const defaultCssClasses: HighlightedValueCssClasses = { highlighted: 'font-normal', nonHighlighted: 'font-semibold' }; /** * The CSS class interface for {@link renderHighlightedValue}. * * @public */ export interface HighlightedValueCssClasses { highlighted?: string, nonHighlighted?: string } /** * Renders a HighlightedValue with highlighting based on its matchedSubstrings. * @returns React.JSX.Element * * @public * * @param highlightedValueOrString - the text to add highlight to. * @param customCssClasses - css classes use for the non-highlighted and highlighted text. */ export function renderHighlightedValue( highlightedValueOrString: Partial | string, customCssClasses?: HighlightedValueCssClasses ): React.JSX.Element { const { value = '', matchedSubstrings } = typeof highlightedValueOrString === 'string' ? { value: highlightedValueOrString, matchedSubstrings: [] } : highlightedValueOrString; const cssClasses = { ...defaultCssClasses, ...customCssClasses }; if (!matchedSubstrings || matchedSubstrings.length === 0) { return {value}; } const substrings = [...matchedSubstrings]; substrings.sort((a, b) => a.offset - b.offset); const highlightedJSX: React.JSX.Element[] = []; let curr = 0; for (const { offset, length } of substrings) { if (offset > curr) { highlightedJSX.push( {value.substring(curr, offset)} ); } highlightedJSX.push( {value.substring(offset, offset + length)} ); curr = offset + length; } if (curr < value.length) { highlightedJSX.push( {value.substring(curr)} ); } return <>{highlightedJSX}; }