{"version":3,"file":"predictive-search-180906cd.js","sources":["../../../../src/scripts/coveo/components/predictive-search.tsx"],"sourcesContent":["import React, { useId, useState, useEffect, useRef } from 'react';\nimport { buildSearchEngine, buildStandaloneSearchBox } from '@coveo/headless';\nimport { rovingIndex } from 'roving-ux';\nimport { createDataLayerString } from '../../helpers/helpers';\nimport { ExtendedWindowType } from '../engine';\nimport { secureStorage } from '../../helpers/global-storage';\n\nconst wrapper = document.getElementsByClassName('coveo-predictive-search')[0];\n\nconst { dataset } = wrapper as HTMLElement;\n\nconst coveoData = JSON.parse(dataset.coveo as string);\nconst optionsData = JSON.parse(dataset.options as string);\n\nconst config = {\n organizationId: coveoData.OrganizationId,\n accessToken: coveoData.ApiKey,\n search: {\n searchHub: coveoData.SearchHubPipeline,\n pipeline: coveoData.SearchHubPipeline\n }\n};\n\nconst engine = buildSearchEngine({\n configuration: config\n});\n\nconst controller = buildStandaloneSearchBox(engine, {\n options: {\n ...optionsData,\n highlightOptions: {\n exactMatchDelimiters: {\n open: '',\n close: ''\n }\n }\n }\n});\n\ntype PredictiveSearchProps = {\n placeholder: string;\n containerClass?: string;\n fieldClass?: string;\n submitLabel: string;\n storageKey: string;\n viewAllLabel: string;\n layer?: string;\n clickDataLayer?: string;\n viewDataLayer?: string;\n clearLabel?: string;\n};\n\nfunction PredictiveSearch({\n placeholder,\n fieldClass,\n submitLabel,\n containerClass,\n storageKey,\n viewAllLabel,\n layer,\n clickDataLayer,\n viewDataLayer,\n clearLabel\n}: PredictiveSearchProps) {\n const id = useId();\n const [state, setState] = useState(controller.state);\n const [value, setValue] = useState(controller.state.value);\n const [showingSuggestions, setShowingSuggestions] = useState(false);\n const [focus, setFocus] = useState(false);\n const listRef = useRef(null);\n const input = useRef(null);\n const clickDataLayerObj = clickDataLayer\n ? JSON.parse(clickDataLayer)\n : undefined;\n const viewDataLayerObj = viewDataLayer\n ? JSON.parse(viewDataLayer)\n : undefined;\n\n const isEnterKey = (e: React.KeyboardEvent) =>\n e.key === 'Enter';\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (input.current === document.activeElement) {\n if (isEnterKey(e)) {\n e.preventDefault();\n controller.updateText(value);\n controller.submit();\n setFocus(false);\n }\n\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n if (listRef.current) {\n if (e.key === 'ArrowDown') {\n const firstElement = listRef.current.querySelector('li');\n if (firstElement) {\n firstElement.querySelector('button')?.focus();\n setFocus(true);\n }\n } else {\n const lastElement = listRef.current.querySelector('li:last-child');\n if (lastElement) {\n (lastElement as HTMLLIElement).querySelector('button')?.focus();\n setFocus(true);\n }\n }\n }\n }\n\n if (e.key === 'Escape') {\n e.preventDefault();\n input.current?.blur();\n setFocus(false);\n }\n } else {\n if (e.key === 'Escape') {\n e.preventDefault();\n input.current?.focus();\n setFocus(false);\n }\n if (\n (e.key === 'ArrowDown' || e.key === 'ArrowUp') &&\n e.currentTarget.querySelector('.field--search')\n ) {\n e.preventDefault();\n }\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent) => {\n controller.updateText(e.target.value);\n setValue(e.target.value);\n setFocus(true);\n };\n\n const handleSuggestionClick = (value: string) => {\n setValue(value);\n controller.selectSuggestion(value);\n };\n\n const handleMouseDown = (e: Event) => {\n if ((e.target as HTMLElement)?.closest('.predictive-search__inner')) {\n return;\n } else {\n setFocus(false);\n }\n };\n\n const handleClear = () => {\n setValue('');\n controller.updateText('');\n };\n\n const handleInputBlur = (e: React.FocusEvent) => {\n if (\n !(e.relatedTarget as HTMLElement)?.closest('.predictive-search__inner')\n ) {\n setFocus(false);\n }\n };\n\n useEffect(() => {\n controller.subscribe(() => setState(controller.state));\n }, []);\n\n useEffect(() => {\n if (listRef.current) {\n rovingIndex({\n element: listRef.current,\n target: '.predictive-search__item'\n });\n\n setShowingSuggestions(true);\n } else {\n setShowingSuggestions(false);\n }\n }, [state.suggestions]);\n\n useEffect(() => {\n if (input.current) {\n input.current.focus();\n }\n\n window.addEventListener('mousedown', e => handleMouseDown(e));\n return () => {\n window.removeEventListener('mousedown', e => handleMouseDown(e));\n };\n }, [input.current]);\n\n useEffect(() => {\n if (showingSuggestions) {\n const global = window as ExtendedWindowType;\n\n global.dataLayer?.push(viewDataLayerObj);\n }\n }, [showingSuggestions]);\n\n if (!state) {\n return null;\n }\n\n if (state.redirectTo) {\n const { redirectTo, value, analytics } = state;\n const data = JSON.stringify({ value, analytics });\n secureStorage.set(storageKey, data);\n window.location.href = redirectTo;\n }\n\n const getViewAllDataLayer = () => {\n if (clickDataLayerObj) {\n clickDataLayerObj.event_attributes.search_term =\n viewAllLabel.toLowerCase();\n }\n\n return clickDataLayerObj;\n };\n\n return (\n {\n e.preventDefault();\n }}\n onKeyDown={e => handleKeyDown(e)}\n >\n
\n \n
\n setFocus(true)}\n onBlur={e => handleInputBlur(e)}\n />\n {state.suggestions.length > 0 && state.value && focus && (\n setFocus(true)}\n onBlur={handleInputBlur}\n >\n {state.suggestions.map(suggestion => {\n const value = suggestion.rawValue;\n\n if (clickDataLayerObj) {\n clickDataLayerObj.event_attributes.search_term =\n value.toLowerCase();\n }\n\n const dataLayer = clickDataLayerObj;\n return (\n
  • \n handleSuggestionClick(value)}\n dangerouslySetInnerHTML={{\n __html: suggestion.highlightedValue\n }}\n data-layer={\n dataLayer\n ? createDataLayerString([dataLayer])\n : undefined\n }\n />\n
  • \n );\n })}\n
  • \n {\n controller.updateText(value);\n controller.submit();\n }}\n onFocus={() => {\n setFocus(true);\n }}\n data-layer={\n clickDataLayerObj\n ? createDataLayerString([getViewAllDataLayer()])\n : undefined\n }\n >\n {viewAllLabel}\n \n
  • \n \n )}\n
    \n\n {state.value.length > 0 && (\n \n )}\n
    \n {\n controller.updateText(value);\n controller.submit();\n }}\n {...(layer && { 'data-layer': layer })}\n >\n {submitLabel}\n \n \n );\n}\n\nexport default PredictiveSearch;\n"],"names":["wrapper","dataset","coveoData","optionsData","config","engine","buildSearchEngine","controller","buildStandaloneSearchBox","PredictiveSearch","placeholder","fieldClass","submitLabel","containerClass","storageKey","viewAllLabel","layer","clickDataLayer","viewDataLayer","clearLabel","id","useId","state","setState","useState","value","setValue","showingSuggestions","setShowingSuggestions","focus","setFocus","listRef","useRef","input","clickDataLayerObj","viewDataLayerObj","isEnterKey","handleKeyDown","firstElement","_a","lastElement","_b","_c","_d","handleInputChange","handleSuggestionClick","handleMouseDown","handleClear","handleInputBlur","useEffect","rovingIndex","redirectTo","analytics","data","secureStorage","getViewAllDataLayer","React","suggestion","dataLayer","createDataLayerString"],"mappings":"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"}