@yext/search-ui-react
Version:
A library of React Components for powering Yext Search integrations
1,286 lines (1,243 loc) • 200 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
AlternativeVerticals: () => AlternativeVerticals,
AnalyticsProvider: () => AnalyticsProvider,
AppliedFilters: () => AppliedFilters,
ApplyFiltersButton: () => ApplyFiltersButton,
ComponentsContentPath: () => ComponentsContentPath,
DirectAnswer: () => DirectAnswer,
DropdownItem: () => DropdownItem,
Facets: () => Facets,
FilterDivider: () => FilterDivider,
FilterSearch: () => FilterSearch,
GenerativeDirectAnswer: () => GenerativeDirectAnswer,
Geolocation: () => Geolocation,
HierarchicalFacet: () => HierarchicalFacet,
HierarchicalFacets: () => HierarchicalFacets,
LocationBias: () => LocationBias,
MapboxMap: () => MapboxMap,
NumericalFacet: () => NumericalFacet,
NumericalFacets: () => NumericalFacets,
Pagination: () => Pagination,
ResultsCount: () => ResultsCount,
SearchBar: () => SearchBar,
SpellCheck: () => SpellCheck,
StandardCard: () => StandardCard,
StandardFacet: () => StandardFacet,
StandardFacets: () => StandardFacets,
StandardSection: () => StandardSection,
StaticFilters: () => StaticFilters,
ThumbsFeedback: () => ThumbsFeedback,
UniversalResults: () => UniversalResults,
VerticalResults: () => VerticalResults,
executeAutocomplete: () => executeAutocomplete,
executeGenerativeDirectAnswer: () => executeGenerativeDirectAnswer,
executeSearch: () => executeSearch,
getSearchIntents: () => getSearchIntents,
getUserLocation: () => getUserLocation,
isCtaData: () => isCtaData,
renderHighlightedValue: () => renderHighlightedValue,
updateLocationIfNeeded: () => updateLocationIfNeeded,
useAnalytics: () => useAnalytics,
useCardAnalyticsCallback: () => useCardAnalyticsCallback,
useCardFeedbackCallback: () => useCardFeedbackCallback,
useComposedCssClasses: () => useComposedCssClasses
});
module.exports = __toCommonJS(index_exports);
// src/components/SearchBar.tsx
var import_search_headless_react7 = require("@yext/search-headless-react");
var import_classnames = __toESM(require("classnames"));
var import_react26 = __toESM(require("react"));
// src/hooks/useEntityPreviews.tsx
var import_react3 = require("react");
// src/hooks/useComponentMountStatus.tsx
var import_react = require("react");
function useComponentMountStatus() {
const isMountedRef = (0, import_react.useRef)(false);
(0, import_react.useEffect)(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
return isMountedRef;
}
// src/hooks/useDebouncedFunction.ts
var import_react2 = require("react");
function useDebouncedFunction(func, milliseconds) {
const timeoutIdRef = (0, import_react2.useRef)();
if (!func) {
return void 0;
}
const debounced = (...args) => {
return new Promise((resolve) => {
if (timeoutIdRef.current !== void 0) {
clearTimeout(timeoutIdRef.current);
}
timeoutIdRef.current = window.setTimeout(() => {
resolve(func(...args));
timeoutIdRef.current = void 0;
}, milliseconds);
});
};
return debounced;
}
// src/hooks/useEntityPreviews.tsx
function useEntityPreviews(entityPreviewSearcher, debounceTime) {
const isMountedRef = useComponentMountStatus();
const [
verticalKeyToResults,
setVerticalKeyToResults
] = (0, import_react3.useState)({});
const debouncedUniversalSearch = useDebouncedFunction(async () => {
if (!entityPreviewSearcher) {
return;
}
await entityPreviewSearcher.executeUniversalQuery();
if (!isMountedRef.current) {
return;
}
const results = entityPreviewSearcher.state.universal.verticals || [];
setVerticalKeyToResults(getVerticalKeyToResults(results));
setLoadingState(false);
}, debounceTime);
const [isLoading, setLoadingState] = (0, import_react3.useState)(false);
function executeEntityPreviewsQuery(query, universalLimit, restrictVerticals) {
if (!entityPreviewSearcher) {
return;
}
if (query === entityPreviewSearcher.state.query.input) {
return;
}
setLoadingState(true);
entityPreviewSearcher.setQuery(query);
entityPreviewSearcher.setRestrictVerticals(restrictVerticals);
entityPreviewSearcher.setUniversalLimit(universalLimit);
debouncedUniversalSearch?.();
}
return [{ verticalKeyToResults, isLoading }, executeEntityPreviewsQuery];
}
function getVerticalKeyToResults(verticalResultsArray) {
return verticalResultsArray.reduce((prev, current) => {
prev[current.verticalKey] = current;
return prev;
}, {});
}
// src/hooks/useRecentSearches.ts
var import_react4 = require("react");
var import_recent_searches = require("recent-searches");
function useRecentSearches(recentSearchesLimit, verticalKey) {
const recentSearchesKey = getRecentSearchesKey(verticalKey);
const [recentSearches, setRecentSeaches] = (0, import_react4.useState)(
new import_recent_searches.RecentSearches({
limit: recentSearchesLimit,
namespace: recentSearchesKey
})
);
const clearRecentSearches = (0, import_react4.useCallback)(() => {
localStorage.removeItem(recentSearchesKey);
setRecentSeaches(new import_recent_searches.RecentSearches({
limit: recentSearchesLimit,
namespace: recentSearchesKey
}));
localStorage.removeItem(recentSearchesKey);
}, [recentSearchesKey, recentSearchesLimit]);
const setRecentSearch = (0, import_react4.useCallback)((input) => {
recentSearches.setRecentSearch(input);
}, [recentSearches]);
(0, import_react4.useEffect)(() => {
setRecentSeaches(new import_recent_searches.RecentSearches({
limit: recentSearchesLimit,
namespace: recentSearchesKey
}));
}, [recentSearchesKey, recentSearchesLimit]);
return [recentSearches?.getRecentSearches(), setRecentSearch, clearRecentSearches];
}
function getRecentSearchesKey(verticalKey) {
if (verticalKey) {
return `__yxt_recent_searches_${verticalKey}__`;
} else {
return "__yxt_recent_searches_universal__";
}
}
// src/hooks/useSearchWithNearMeHandling.ts
var import_search_headless_react3 = require("@yext/search-headless-react");
// src/utils/search-operations.ts
var import_search_headless_react = require("@yext/search-headless-react");
async function executeSearch(searchActions) {
const isVertical = searchActions.state.meta.searchType === import_search_headless_react.SearchTypeEnum.Vertical;
try {
isVertical ? searchActions.executeVerticalQuery() : searchActions.executeUniversalQuery();
} catch (e) {
console.error(`Error occured executing a ${isVertical ? "vertical" : "universal"} search.
`, e);
}
}
async function executeAutocomplete(searchActions) {
const isVertical = searchActions.state.meta.searchType === import_search_headless_react.SearchTypeEnum.Vertical;
try {
return isVertical ? searchActions.executeVerticalAutocomplete() : searchActions.executeUniversalAutocomplete();
} catch (e) {
console.error(`Error occured executing a ${isVertical ? "vertical" : "universal"} autocomplete search.
`, e);
}
}
async function getSearchIntents(searchActions) {
const results = await executeAutocomplete(searchActions);
return results?.inputIntents;
}
async function executeGenerativeDirectAnswer(searchActions) {
try {
return await searchActions.executeGenerativeDirectAnswer();
} catch (e) {
console.error(`Error occured executing generative direct answer.
`, e);
}
}
// src/utils/location-operations.ts
var import_search_headless_react2 = require("@yext/search-headless-react");
var defaultGeolocationOptions = {
enableHighAccuracy: false,
timeout: 6e3,
maximumAge: 3e5
};
async function updateLocationIfNeeded(searchActions, intents, geolocationOptions) {
if (intents.includes(import_search_headless_react2.SearchIntent.NearMe) && !searchActions.state.location.userLocation) {
try {
const position = await getUserLocation(geolocationOptions);
searchActions.setUserLocation({
latitude: position.coords.latitude,
longitude: position.coords.longitude
});
} catch (e) {
console.error(e);
}
}
}
async function getUserLocation(geolocationOptions) {
return new Promise((resolve, reject) => {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
(position) => resolve(position),
(err) => {
console.error("Error occured using geolocation API. Unable to determine user's location.");
reject(err);
},
{ ...defaultGeolocationOptions, ...geolocationOptions }
);
} else {
reject("No access to geolocation API. Unable to determine user's location.");
}
});
}
// src/hooks/useSearchWithNearMeHandling.ts
var import_react5 = require("react");
function useSearchWithNearMeHandling(geolocationOptions, onSearch) {
const autocompletePromiseRef = (0, import_react5.useRef)();
const searchActions = (0, import_search_headless_react3.useSearchActions)();
async function executeQuery() {
try {
let intents = [];
if (!searchActions.state.location.userLocation) {
if (!autocompletePromiseRef.current) {
autocompletePromiseRef.current = executeAutocomplete(searchActions);
}
const autocompleteResponseBeforeSearch = await autocompletePromiseRef.current;
intents = autocompleteResponseBeforeSearch?.inputIntents || [];
await updateLocationIfNeeded(searchActions, intents, geolocationOptions);
}
} catch (e) {
console.error("Error executing autocomplete before search:", e);
await updateLocationIfNeeded(searchActions, [], geolocationOptions);
}
const verticalKey = searchActions.state.vertical.verticalKey ?? "";
const query = searchActions.state.query.input ?? "";
onSearch ? onSearch({ verticalKey, query }) : executeSearch(searchActions);
}
return [executeQuery, autocompletePromiseRef];
}
// src/hooks/useSynchronizedRequest.tsx
var import_react6 = require("react");
function useSynchronizedRequest(executeRequest, handleRejectedPromise) {
const executeRequestRef = (0, import_react6.useRef)(executeRequest);
const handleRejectedPromiseRef = (0, import_react6.useRef)(handleRejectedPromise);
const isMountedRef = useComponentMountStatus();
const networkIds = (0, import_react6.useRef)({ latestRequest: 0, responseInState: 0 });
const [synchronizedResponse, setSynchronizedResponse] = (0, import_react6.useState)();
const executeSynchronizedRequest = (0, import_react6.useCallback)(async (data) => {
const requestId = ++networkIds.current.latestRequest;
return new Promise(async (resolve) => {
let response = void 0;
try {
response = await executeRequestRef.current(data);
} catch (e) {
handleRejectedPromiseRef.current ? handleRejectedPromiseRef.current(e) : console.error(e);
}
if (requestId >= networkIds.current.responseInState) {
if (!isMountedRef.current) {
return;
}
setSynchronizedResponse(response);
networkIds.current.responseInState = requestId;
}
resolve(response);
});
}, [isMountedRef]);
const clearResponseData = (0, import_react6.useCallback)(() => {
setSynchronizedResponse(void 0);
}, [setSynchronizedResponse]);
(0, import_react6.useEffect)(() => {
executeRequestRef.current = executeRequest;
handleRejectedPromiseRef.current = handleRejectedPromise;
});
return [synchronizedResponse, executeSynchronizedRequest, clearResponseData];
}
// src/icons/VerticalDividerIcon.tsx
var import_react7 = __toESM(require("react"));
function VerticalDividerIcon({ className }) {
return /* @__PURE__ */ import_react7.default.createElement(
"svg",
{
className,
width: "1",
height: "24",
viewBox: "0 0 1 24",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
"aria-hidden": "true"
},
/* @__PURE__ */ import_react7.default.createElement("rect", { width: "1", height: "24", rx: "0.5", fill: "#E1E5E8" })
);
}
// src/icons/HistoryIcon.tsx
var import_react8 = __toESM(require("react"));
function HistoryIcon() {
return /* @__PURE__ */ import_react8.default.createElement("svg", { viewBox: "0 0 14 15", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true" }, /* @__PURE__ */ import_react8.default.createElement("path", { d: "M13.7813 7.75C13.7539 4.00391 10.7188 0.96875 7 0.96875C5.11328 0.96875 3.39063 1.76172 2.16016 2.99219L0.929688 1.76172C0.738281 1.57031 0.382813 1.70703 0.382813 2.00781L0.382813 5.45312C0.382813 5.64453 0.519531 5.78125 0.710938 5.78125L4.21094 5.78125C4.51172 5.78125 4.64844 5.42578 4.45703 5.23437L3.11719 3.92188C4.10156 2.91016 5.46875 2.28125 7 2.28125C10.0078 2.28125 12.4688 4.74219 12.4688 7.75C12.4688 10.7852 10.0078 13.2187 7 13.2188C5.57813 13.2188 4.32031 12.6992 3.33594 11.8516C3.22656 11.7422 3.00781 11.7422 2.89844 11.8516L2.43359 12.3164C2.29688 12.4531 2.29688 12.6719 2.43359 12.8086C3.63672 13.875 5.25 14.5586 7 14.5312C10.7188 14.5312 13.7813 11.4961 13.7813 7.75ZM9.1875 10.2109L9.59766 9.69141C9.67969 9.52734 9.65234 9.33594 9.51563 9.22656L7.65625 7.85937V3.92187C7.65625 3.75781 7.49219 3.59375 7.32813 3.59375H6.67188C6.48047 3.59375 6.34375 3.75781 6.34375 3.92187V8.54297L8.75 10.293C8.88672 10.4023 9.10547 10.375 9.1875 10.2109Z" }));
}
// src/icons/CloseIcon.tsx
var import_react9 = __toESM(require("react"));
function CloseIcon() {
return /* @__PURE__ */ import_react9.default.createElement("svg", { viewBox: "0 0 18 18", xmlns: "http://www.w3.org/2000/svg", fill: "currentColor", "aria-hidden": "true" }, /* @__PURE__ */ import_react9.default.createElement("path", { d: "M10.9095 9.00028L16.6786 3.2311L17.8684 2.04138C18.0439 1.86587 18.0439 1.58067 17.8684 1.40517L16.5954 0.132192C16.4199 -0.0433137 16.1347 -0.0433137 15.9592 0.132192L9.00028 7.0911L2.04138 0.131629C1.86587 -0.0438764 1.58067 -0.0438764 1.40517 0.131629L0.131629 1.40461C-0.0438764 1.58011 -0.0438764 1.86531 0.131629 2.04081L7.0911 9.00028L0.131629 15.9592C-0.0438764 16.1347 -0.0438764 16.4199 0.131629 16.5954L1.40461 17.8684C1.58011 18.0439 1.86531 18.0439 2.04081 17.8684L9.00028 10.9095L14.7695 16.6786L15.9592 17.8684C16.1347 18.0439 16.4199 18.0439 16.5954 17.8684L17.8684 16.5954C18.0439 16.4199 18.0439 16.1347 17.8684 15.9592L10.9095 9.00028Z", fill: "#6b7280" }));
}
// src/icons/MagnifyingGlassIcon.tsx
var import_react10 = __toESM(require("react"));
function MagnifyingGlassIcon() {
return /* @__PURE__ */ import_react10.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true" }, /* @__PURE__ */ import_react10.default.createElement("path", { d: "M0 0h24v24H0V0z", fill: "none" }), /* @__PURE__ */ import_react10.default.createElement(
"path",
{
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
}
));
}
// src/components/Dropdown/Dropdown.tsx
var import_react18 = __toESM(require("react"));
// src/components/Dropdown/DropdownContext.ts
var import_react11 = require("react");
var DropdownContext = (0, import_react11.createContext)(null);
function useDropdownContext() {
const dropdownContextInstance = (0, import_react11.useContext)(DropdownContext);
if (dropdownContextInstance === null) {
throw new Error("Tried to use DropdownContext when none exists.");
}
return dropdownContextInstance;
}
// src/components/Dropdown/InputContext.ts
var import_react12 = require("react");
var InputContext = (0, import_react12.createContext)(null);
function useInputContext() {
const inputContextInstance = (0, import_react12.useContext)(InputContext);
if (inputContextInstance === null) {
throw new Error("Tried to use InputContext when none exists.");
}
return inputContextInstance;
}
// src/components/Dropdown/Dropdown.tsx
var import_useRootClose = __toESM(require("@restart/ui/useRootClose"));
// src/components/Dropdown/FocusContext.ts
var import_react13 = require("react");
var FocusContext = (0, import_react13.createContext)(null);
function useFocusContext() {
const focusContextInstance = (0, import_react13.useContext)(FocusContext);
if (focusContextInstance === null) {
throw new Error("Tried to use FocusContext when none exists.");
}
return focusContextInstance;
}
// src/components/ScreenReader.tsx
var import_react14 = __toESM(require("react"));
function ScreenReader({
instructionsId,
instructions,
announcementKey,
announcementText
}) {
return /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement(
"div",
{
id: instructionsId,
className: "hidden"
},
instructions
), /* @__PURE__ */ import_react14.default.createElement(
"div",
{
className: "sr-only",
key: announcementKey,
"aria-live": "assertive"
},
announcementText
));
}
// src/components/utils/recursivelyMapChildren.ts
var import_react15 = require("react");
function recursivelyMapChildren(children, elementReplacer) {
return import_react15.Children.map(children, (c, index) => {
if (!(0, import_react15.isValidElement)(c)) {
return c;
}
const replacedElement = elementReplacer(c, index);
if (!replacedElement || !(0, import_react15.isValidElement)(replacedElement)) {
return replacedElement;
}
const grandchildren = replacedElement.props.children;
if (!grandchildren) {
return replacedElement;
}
const replacedGrandchildren = recursivelyMapChildren(grandchildren, elementReplacer);
return (0, import_react15.cloneElement)(replacedElement, {}, [replacedGrandchildren]);
});
}
// src/components/Dropdown/DropdownItem.tsx
var import_react16 = __toESM(require("react"));
// src/components/Dropdown/generateDropdownId.ts
function generateDropdownId(screenReaderUUID, index) {
if (!screenReaderUUID) return "";
return screenReaderUUID + "_" + index;
}
// src/components/Dropdown/DropdownItem.tsx
function DropdownItem(_props) {
return null;
}
function DropdownItemWithIndex(props) {
const {
children,
value,
index,
className,
focusedClassName,
itemData,
onClick,
ariaLabel
} = props;
const { toggleDropdown, onSelect, screenReaderUUID } = useDropdownContext();
const { focusedIndex, updateFocusedItem } = useFocusContext();
const { setValue, setLastTypedOrSubmittedValue } = useInputContext();
const isFocused = focusedIndex === index;
const handleClick = (0, import_react16.useCallback)(() => {
toggleDropdown(false);
updateFocusedItem(-1);
setLastTypedOrSubmittedValue(value);
setValue(value);
onSelect?.(value, index, itemData);
onClick?.(value, index, itemData);
}, [
index,
itemData,
onClick,
onSelect,
setLastTypedOrSubmittedValue,
setValue,
toggleDropdown,
updateFocusedItem,
value
]);
return /* @__PURE__ */ import_react16.default.createElement(
"div",
{
id: generateDropdownId(screenReaderUUID, index),
tabIndex: 0,
className: isFocused ? focusedClassName : className,
onClick: handleClick,
"aria-label": typeof ariaLabel === "function" ? ariaLabel(value) : ariaLabel
},
children
);
}
// src/hooks/useLayoutEffect.ts
var import_use_isomorphic_layout_effect = __toESM(require("use-isomorphic-layout-effect"));
var useLayoutEffect = typeof import_use_isomorphic_layout_effect.default === "function" ? import_use_isomorphic_layout_effect.default : import_use_isomorphic_layout_effect.default["default"];
// src/hooks/useId.ts
var import_react17 = __toESM(require("react"));
var serverHandoffComplete = false;
var id = 0;
function genId(baseName) {
++id;
return baseName + "-" + id.toString();
}
var maybeReactUseId = import_react17.default["useId".toString()];
function useId(baseName) {
if (maybeReactUseId !== void 0) {
return maybeReactUseId();
}
const initialId = serverHandoffComplete ? genId(baseName) : "";
const [id2, setId] = (0, import_react17.useState)(initialId);
useLayoutEffect(() => {
if (id2 === "") {
setId(genId(baseName));
}
}, [id2]);
(0, import_react17.useEffect)(() => {
if (serverHandoffComplete === false) {
serverHandoffComplete = true;
}
}, []);
return id2;
}
// src/components/Dropdown/Dropdown.tsx
var useRootClose = typeof import_useRootClose.default === "function" ? import_useRootClose.default : import_useRootClose.default["default"];
function Dropdown(props) {
const {
children,
screenReaderText,
screenReaderInstructions = "When autocomplete results are available, use up and down arrows to review and enter to select.",
onSelect,
onToggle,
className,
activeClassName,
parentQuery,
alwaysSelectOption = false
} = props;
const containerRef = (0, import_react18.useRef)(null);
const screenReaderUUID = useId("dropdown");
const [screenReaderKey, setScreenReaderKey] = (0, import_react18.useState)(0);
const [hasTyped, setHasTyped] = (0, import_react18.useState)(false);
const [childrenWithDropdownItemsTransformed, items] = (0, import_react18.useMemo)(() => {
return getTransformedChildrenAndItemData(children);
}, [children]);
const inputContext = useInputContextInstance();
const { value, setValue, lastTypedOrSubmittedValue, setLastTypedOrSubmittedValue } = inputContext;
const focusContext = useFocusContextInstance(
items,
lastTypedOrSubmittedValue,
setValue,
screenReaderKey,
setScreenReaderKey,
alwaysSelectOption
);
const { focusedIndex, focusedItemData, updateFocusedItem } = focusContext;
const dropdownContext = useDropdownContextInstance(
lastTypedOrSubmittedValue,
value,
focusedIndex,
focusedItemData,
screenReaderUUID,
setHasTyped,
onToggle,
onSelect
);
const { toggleDropdown, isActive } = dropdownContext;
useLayoutEffect(() => {
if (parentQuery !== void 0 && parentQuery !== lastTypedOrSubmittedValue) {
setLastTypedOrSubmittedValue(parentQuery);
updateFocusedItem(-1, parentQuery);
}
}, [
parentQuery,
lastTypedOrSubmittedValue,
updateFocusedItem,
setLastTypedOrSubmittedValue
]);
useRootClose(containerRef, () => {
toggleDropdown(false);
}, { disabled: !isActive });
function handleKeyDown(e) {
if (!isActive) {
return;
}
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
e.preventDefault();
}
if (e.key === "ArrowDown") {
if (alwaysSelectOption && focusedIndex === items.length - 1) {
updateFocusedItem(0);
} else {
updateFocusedItem(focusedIndex + 1);
}
} else if (e.key === "ArrowUp") {
if (alwaysSelectOption && focusedIndex === 0) {
updateFocusedItem(items.length - 1);
} else {
updateFocusedItem(focusedIndex - 1);
}
} else if (e.key === "Tab" && !e.shiftKey) {
if (items.length !== 0) {
if (focusedIndex >= items.length - 1) {
updateFocusedItem(-1);
toggleDropdown(false);
} else {
updateFocusedItem(focusedIndex + 1);
e.preventDefault();
}
}
} else if (e.key === "Tab" && e.shiftKey) {
if (focusedIndex > 0 || !alwaysSelectOption && focusedIndex === 0) {
updateFocusedItem(focusedIndex - 1);
e.preventDefault();
} else {
updateFocusedItem(-1);
toggleDropdown(false);
}
} else if (!hasTyped) {
setHasTyped(true);
}
}
return /* @__PURE__ */ import_react18.default.createElement("div", { ref: containerRef, className: isActive ? activeClassName : className, onKeyDown: handleKeyDown }, /* @__PURE__ */ import_react18.default.createElement(DropdownContext.Provider, { value: dropdownContext }, /* @__PURE__ */ import_react18.default.createElement(InputContext.Provider, { value: inputContext }, /* @__PURE__ */ import_react18.default.createElement(FocusContext.Provider, { value: focusContext }, childrenWithDropdownItemsTransformed))), /* @__PURE__ */ import_react18.default.createElement(
ScreenReader,
{
announcementKey: screenReaderKey,
announcementText: isActive && (hasTyped || items.length || value) ? screenReaderText : "",
instructionsId: screenReaderUUID,
instructions: screenReaderInstructions
}
));
}
function useInputContextInstance() {
const [value, setValue] = (0, import_react18.useState)("");
const [lastTypedOrSubmittedValue, setLastTypedOrSubmittedValue] = (0, import_react18.useState)("");
return {
value,
setValue,
lastTypedOrSubmittedValue,
setLastTypedOrSubmittedValue
};
}
function useFocusContextInstance(items, lastTypedOrSubmittedValue, setValue, screenReaderKey, setScreenReaderKey, alwaysSelectOption) {
const [focusedIndex, setFocusedIndex] = (0, import_react18.useState)(-1);
const [focusedValue, setFocusedValue] = (0, import_react18.useState)(null);
const [focusedItemData, setFocusedItemData] = (0, import_react18.useState)(void 0);
(0, import_react18.useEffect)(() => {
if (alwaysSelectOption) {
if (items.length > 0) {
const index = focusedIndex === -1 || focusedIndex >= items.length ? 0 : focusedIndex;
setFocusedIndex(index);
setFocusedValue(items[index].value);
setFocusedItemData(items[index].itemData);
} else {
setFocusedIndex(-1);
setFocusedValue(null);
setFocusedItemData(void 0);
}
}
}, [alwaysSelectOption, focusedIndex, items]);
function updateFocusedItem(updatedFocusedIndex, value) {
const numItems = items.length;
let updatedValue;
if (updatedFocusedIndex === -1 || updatedFocusedIndex >= numItems || numItems === 0) {
updatedValue = value ?? lastTypedOrSubmittedValue;
if (alwaysSelectOption && numItems !== 0) {
setFocusedIndex(0);
setFocusedItemData(items[0].itemData);
setScreenReaderKey(screenReaderKey + 1);
} else {
setFocusedIndex(-1);
setFocusedItemData(void 0);
setScreenReaderKey(screenReaderKey + 1);
}
} else if (updatedFocusedIndex < -1) {
const loopedAroundIndex = (numItems + updatedFocusedIndex + 1) % numItems;
updatedValue = value ?? items[loopedAroundIndex].value;
setFocusedIndex(loopedAroundIndex);
setFocusedItemData(items[loopedAroundIndex].itemData);
} else {
updatedValue = value ?? items[updatedFocusedIndex].value;
setFocusedIndex(updatedFocusedIndex);
setFocusedItemData(items[updatedFocusedIndex].itemData);
}
setFocusedValue(updatedValue);
setValue(alwaysSelectOption ? value ?? lastTypedOrSubmittedValue : updatedValue);
}
return {
focusedIndex,
focusedValue,
focusedItemData,
updateFocusedItem
};
}
function useDropdownContextInstance(prevValue, value, index, focusedItemData, screenReaderUUID, setHasTyped, onToggle, onSelect) {
const [isActive, _toggleDropdown] = (0, import_react18.useState)(false);
const toggleDropdown = (willBeOpen) => {
if (!willBeOpen) {
setHasTyped(false);
}
_toggleDropdown(willBeOpen);
onToggle?.(willBeOpen, prevValue, value, index, focusedItemData);
};
return {
isActive,
toggleDropdown,
onSelect,
screenReaderUUID
};
}
function getTransformedChildrenAndItemData(children) {
const items = [];
const childrenWithDropdownItemsTransformed = recursivelyMapChildren(children, (child) => {
if (!((0, import_react18.isValidElement)(child) && child.type === DropdownItem)) {
return child;
}
const props = child.props;
items.push({
value: props.value,
itemData: props.itemData
});
return (0, import_react18.createElement)(DropdownItemWithIndex, { ...props, index: items.length - 1 });
});
return [childrenWithDropdownItemsTransformed, items];
}
// src/components/Dropdown/DropdownInput.tsx
var import_react19 = __toESM(require("react"));
function DropdownInput(props) {
const {
className,
placeholder,
ariaLabel,
onSubmit,
onFocus,
onChange,
submitCriteria
} = props;
const inputRef = (0, import_react19.useRef)(null);
const { toggleDropdown, onSelect, screenReaderUUID } = useDropdownContext();
const { value = "", setLastTypedOrSubmittedValue } = useInputContext();
const {
focusedIndex = -1,
focusedItemData,
focusedValue,
updateFocusedItem
} = useFocusContext();
const [isTyping, setIsTyping] = (0, import_react19.useState)(true);
const handleChange = (0, import_react19.useCallback)((e) => {
setIsTyping(true);
toggleDropdown(true);
onChange?.(e.target.value);
updateFocusedItem(-1, e.target.value);
setLastTypedOrSubmittedValue(e.target.value);
}, [onChange, setLastTypedOrSubmittedValue, toggleDropdown, updateFocusedItem]);
const handleKeyDown = (0, import_react19.useCallback)((e) => {
if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Tab") {
setIsTyping(false);
}
if (e.key === "Enter" && (!submitCriteria || submitCriteria(focusedIndex))) {
updateFocusedItem(focusedIndex);
toggleDropdown(false);
inputRef.current?.blur();
onSubmit?.(value, focusedIndex, focusedItemData);
if (focusedIndex >= 0) {
onSelect?.(value, focusedIndex, focusedItemData);
}
updateFocusedItem(-1, focusedValue ?? void 0);
}
}, [
focusedIndex,
focusedValue,
focusedItemData,
onSelect,
onSubmit,
submitCriteria,
toggleDropdown,
updateFocusedItem,
value
]);
const handleFocus = (0, import_react19.useCallback)(() => {
toggleDropdown(true);
updateFocusedItem(-1);
onFocus?.(value);
}, [onFocus, toggleDropdown, updateFocusedItem, value]);
return /* @__PURE__ */ import_react19.default.createElement(
"input",
{
ref: inputRef,
className,
placeholder,
value,
onChange: handleChange,
onKeyDown: handleKeyDown,
onFocus: handleFocus,
id: generateDropdownId(screenReaderUUID, -1),
autoComplete: "off",
"aria-describedby": screenReaderUUID,
"aria-activedescendant": isTyping ? "" : generateDropdownId(screenReaderUUID, focusedIndex),
"aria-label": ariaLabel
}
);
}
// src/components/Dropdown/DropdownMenu.tsx
var import_react20 = __toESM(require("react"));
function DropdownMenu({ children }) {
const { isActive } = useDropdownContext();
if (!isActive) {
return null;
}
return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, children);
}
// src/hooks/useComposedCssClasses.tsx
var import_react21 = require("react");
var import_tailwind_merge = require("tailwind-merge");
var twMerge = (0, import_tailwind_merge.extendTailwindMerge)({
classGroups: {
form: ["input", "checkbox", "textarea", "select", "multiselect", "radio"].map((v) => "form-" + v)
}
});
function useComposedCssClasses(builtInClasses, customClasses, disableBuiltInClasses = false) {
return (0, import_react21.useMemo)(() => {
if (disableBuiltInClasses && customClasses) {
return customClasses;
}
const mergedCssClasses = { ...builtInClasses };
if (!customClasses) {
return mergedCssClasses;
}
Object.keys(customClasses).forEach((key) => {
const builtIn = builtInClasses[key];
const custom = customClasses[key];
if (!builtIn || !custom) {
mergedCssClasses[key] = custom || builtIn;
} else {
mergedCssClasses[key] = twMerge(builtIn, custom);
}
});
return mergedCssClasses;
}, [builtInClasses, customClasses, disableBuiltInClasses]);
}
// src/components/SearchButton.tsx
var import_react22 = __toESM(require("react"));
function SearchButton({ handleClick, className }) {
return /* @__PURE__ */ import_react22.default.createElement(
"button",
{
className,
onClick: handleClick,
"aria-label": "Submit Search"
},
/* @__PURE__ */ import_react22.default.createElement(MagnifyingGlassIcon, null)
);
}
// src/components/utils/processTranslation.ts
function processTranslation(args) {
if (args.count != null && args.pluralForm && args.count !== 1) {
return args.pluralForm;
} else {
return args.phrase;
}
}
// src/components/utils/renderHighlightedValue.tsx
var import_react23 = __toESM(require("react"));
var defaultCssClasses = {
highlighted: "font-normal",
nonHighlighted: "font-semibold"
};
function renderHighlightedValue(highlightedValueOrString, customCssClasses) {
const { value = "", matchedSubstrings } = typeof highlightedValueOrString === "string" ? { value: highlightedValueOrString, matchedSubstrings: [] } : highlightedValueOrString;
const cssClasses = { ...defaultCssClasses, ...customCssClasses };
if (!matchedSubstrings || matchedSubstrings.length === 0) {
return /* @__PURE__ */ import_react23.default.createElement("span", null, value);
}
const substrings = [...matchedSubstrings];
substrings.sort((a, b) => a.offset - b.offset);
const highlightedJSX = [];
let curr = 0;
for (const { offset, length } of substrings) {
if (offset > curr) {
highlightedJSX.push(
/* @__PURE__ */ import_react23.default.createElement("span", { key: curr, className: cssClasses.nonHighlighted }, value.substring(curr, offset))
);
}
highlightedJSX.push(
/* @__PURE__ */ import_react23.default.createElement("span", { key: offset, className: cssClasses.highlighted }, value.substring(offset, offset + length))
);
curr = offset + length;
}
if (curr < value.length) {
highlightedJSX.push(
/* @__PURE__ */ import_react23.default.createElement("span", { key: curr, className: cssClasses.nonHighlighted }, value.substring(curr))
);
}
return /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, highlightedJSX);
}
// src/components/utils/renderAutocompleteResult.tsx
var import_react24 = __toESM(require("react"));
var builtInCssClasses = {
option: "whitespace-no-wrap max-w-full px-3 text-neutral-dark truncate",
icon: "w-6 h-full flex-shrink-0 text-gray-400"
};
function renderAutocompleteResult(result, cssClasses = {}, Icon, ariaLabel) {
return /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, Icon && /* @__PURE__ */ import_react24.default.createElement("div", { className: cssClasses.icon }, /* @__PURE__ */ import_react24.default.createElement(Icon, null)), /* @__PURE__ */ import_react24.default.createElement("div", { "aria-label": ariaLabel || "", className: cssClasses.option }, renderHighlightedValue(result, cssClasses)));
}
// src/hooks/useAnalytics.ts
var import_react25 = require("react");
var AnalyticsContext = (0, import_react25.createContext)(null);
function useAnalytics() {
return (0, import_react25.useContext)(AnalyticsContext);
}
// src/hooks/useSearchBarAnalytics.ts
var import_search_headless_react4 = require("@yext/search-headless-react");
function useSearchBarAnalytics() {
const analytics = useAnalytics();
const verticalKey = (0, import_search_headless_react4.useSearchState)((state) => state.vertical.verticalKey);
const queryId = (0, import_search_headless_react4.useSearchState)((state) => state.query.queryId);
const reportAutocompleteEvent = (suggestedSearchText) => {
analytics?.report({
type: "AUTO_COMPLETE_SELECTION",
...queryId && { queryId },
suggestedSearchText
});
};
const reportSearchClearEvent = () => {
if (!queryId) {
console.error("Unable to report a search clear event. Missing field: queryId.");
return;
}
analytics?.report({
type: "SEARCH_CLEAR_BUTTON",
queryId,
verticalKey
});
};
const reportAnalyticsEvent = (analyticsEventType, suggestedSearchText) => {
if (!analytics) {
return;
}
analyticsEventType === "AUTO_COMPLETE_SELECTION" ? reportAutocompleteEvent(suggestedSearchText || "") : reportSearchClearEvent();
};
return reportAnalyticsEvent;
}
// src/models/verticalLink.ts
var isVerticalLink = (obj) => {
return typeof obj === "object" && !!obj && "verticalKey" in obj;
};
// src/utils/filterutils.tsx
var import_search_headless_react6 = require("@yext/search-headless-react");
var import_isEqual = __toESM(require("lodash/isEqual.js"));
// src/models/NumberRangeFilter.ts
var import_search_headless_react5 = require("@yext/search-headless-react");
function isNumberRangeFilter(unknownFilter = {}) {
const filter = unknownFilter;
return filter.matcher === import_search_headless_react5.Matcher.Between && isNumberRangeValue(filter.value);
}
// src/utils/filterutils.tsx
function isNearFilterValue(obj) {
return typeof obj === "object" && !!obj && "radius" in obj && "lat" in obj && "long" in obj;
}
function isNumberRangeValue(obj) {
return typeof obj === "object" && !!obj && ("start" in obj || "end" in obj);
}
function isStringFacet(facet) {
return facet.options.length > 0 && typeof facet.options[0].value === "string";
}
function isNumericalFacet(facet) {
return facet.options.length > 0 && facet.options.some((option) => isNumberRangeFilter(option));
}
function isDuplicateFieldValueFilter(thisFilter, otherFilter) {
if (thisFilter.fieldId !== otherFilter.fieldId) {
return false;
}
if (thisFilter.matcher !== otherFilter.matcher) {
return false;
}
return (0, import_isEqual.default)(thisFilter.value, otherFilter.value);
}
function isDuplicateStaticFilter(thisFilter, otherFilter) {
if (thisFilter.kind === "fieldValue") {
return otherFilter.kind === "fieldValue" ? isDuplicateFieldValueFilter(thisFilter, otherFilter) : false;
}
if (otherFilter.kind === "fieldValue") {
return false;
}
return thisFilter.combinator === otherFilter.combinator && thisFilter.filters.length === otherFilter.filters.length && thisFilter.filters.every((t) => otherFilter.filters.some((o) => isDuplicateStaticFilter(t, o))) && otherFilter.filters.every((o) => thisFilter.filters.some((t) => isDuplicateStaticFilter(o, t)));
}
function findSelectableFieldValueFilter(filter, selectableFilters) {
return selectableFilters.find((selectableFilter) => {
const { displayName: _2, ...storedFilter } = selectableFilter;
return isDuplicateFieldValueFilter(storedFilter, filter);
});
}
function parseNumberRangeInput(minRangeInput, maxRangeInput) {
const minRange = parseNumber(minRangeInput);
const maxRange = parseNumber(maxRangeInput);
return {
...minRange !== void 0 && {
start: {
matcher: import_search_headless_react6.Matcher.GreaterThanOrEqualTo,
value: minRange
}
},
...maxRange !== void 0 && {
end: {
matcher: import_search_headless_react6.Matcher.LessThanOrEqualTo,
value: maxRange
}
}
};
}
function parseNumber(num) {
const parsedNum = parseFloat(num);
if (isNaN(parsedNum)) {
return void 0;
}
return parsedNum;
}
function clearStaticRangeFilters(searchActions, fieldIds) {
const selectedStaticRangeFilters = searchActions.state?.filters?.static?.filter(
(filter) => isNumberRangeFilter(filter) && filter.selected === true && (!fieldIds || fieldIds.has(filter.fieldId))
);
selectedStaticRangeFilters?.forEach((filter) => {
searchActions.setFilterOption({
...filter,
selected: false
});
});
}
function getSelectedNumericalFacetFields(searchActions) {
const selectedNumericalFacets = searchActions.state.filters.facets?.filter(
(f) => isNumericalFacet(f) && f.options.some((o) => o.selected)
) ?? [];
return new Set(selectedNumericalFacets.map((f) => f.fieldId));
}
function getSelectableFieldValueFilters(staticFilters) {
return staticFilters.map((s) => {
const { filter: { kind, ...filterFields }, ...displayFields } = s;
if (kind === "fieldValue") {
return {
...displayFields,
...filterFields
};
}
return void 0;
}).filter((s) => !!s);
}
function getDefaultFilterDisplayName(numberRange) {
const start = numberRange.start;
const end = numberRange.end;
if (start && end) {
return `${start.value} - ${end.value}`;
} else if (start && !end) {
return `Over ${start.value}`;
} else if (end && !start) {
return `Up to ${end.value}`;
}
return "";
}
// src/components/SearchBar.tsx
var builtInCssClasses2 = {
searchBarContainer: "h-12 mb-6",
inputDivider: "border-t border-gray-200 mx-2.5",
inputElement: "outline-none flex-grow border-none h-11 pl-5 pr-2 text-neutral-dark text-base placeholder:text-neutral-light",
searchButtonContainer: " w-8 h-full mx-2 flex flex-col justify-center items-center",
searchButton: "h-7 w-7",
focusedOption: "bg-gray-100",
clearButton: "h-3 w-3 mr-3.5",
verticalDivider: "mr-0.5",
recentSearchesIcon: "w-5 mr-1 flex-shrink-0 h-full text-gray-400",
recentSearchesOption: "whitespace-no-wrap max-w-full px-3 text-neutral-dark truncate",
recentSearchesNonHighlighted: "font-normal",
// Swap this to semibold once we apply highlighting to recent searches
verticalLink: "ml-12 pl-1 text-neutral italic",
entityPreviewsDivider: "h-px bg-gray-200 mt-1 mb-4 mx-3.5",
...builtInCssClasses
};
function SearchBar({
placeholder,
geolocationOptions,
hideRecentSearches,
visualAutocompleteConfig,
showVerticalLinks = false,
onSelectVerticalLink,
verticalKeyToLabel,
recentSearchesLimit = 5,
customCssClasses,
onSearch
}) {
const {
entityPreviewSearcher,
renderEntityPreviews,
includedVerticals,
universalLimit,
entityPreviewsDebouncingTime = 500
} = visualAutocompleteConfig ?? {};
const searchActions = (0, import_search_headless_react7.useSearchActions)();
const searchUtilities = (0, import_search_headless_react7.useSearchUtilities)();
const reportAnalyticsEvent = useSearchBarAnalytics();
const query = (0, import_search_headless_react7.useSearchState)((state) => state.query.input) ?? "";
const cssClasses = useComposedCssClasses(builtInCssClasses2, customCssClasses);
const isVertical = (0, import_search_headless_react7.useSearchState)((state) => state.meta.searchType) === import_search_headless_react7.SearchTypeEnum.Vertical;
const verticalKey = (0, import_search_headless_react7.useSearchState)((state) => state.vertical.verticalKey);
const debouncedExecuteAutocompleteSearch = useDebouncedFunction(() => executeAutocomplete(searchActions), 200);
const [autocompleteResponse, executeAutocomplete2, clearAutocompleteData] = useSynchronizedRequest(
async () => {
return debouncedExecuteAutocompleteSearch ? debouncedExecuteAutocompleteSearch() : void 0;
}
);
const [
executeQueryWithNearMeHandling,
autocompletePromiseRef
] = useSearchWithNearMeHandling(geolocationOptions, onSearch);
const [
recentSearches,
setRecentSearch,
clearRecentSearches
] = useRecentSearches(recentSearchesLimit, verticalKey);
const filteredRecentSearches = recentSearches?.filter(
(search) => searchUtilities.isCloseMatch(search.query, query)
);
(0, import_react26.useEffect)(() => {
if (hideRecentSearches) {
clearRecentSearches();
}
}, [clearRecentSearches, hideRecentSearches]);
const clearAutocomplete = (0, import_react26.useCallback)(() => {
clearAutocompleteData();
autocompletePromiseRef.current = void 0;
}, [autocompletePromiseRef, clearAutocompleteData]);
const executeQuery = (0, import_react26.useCallback)(() => {
if (!hideRecentSearches) {
const input = searchActions.state.query.input;
input && setRecentSearch(input);
}
executeQueryWithNearMeHandling();
}, [
searchActions.state.query.input,
executeQueryWithNearMeHandling,
hideRecentSearches,
setRecentSearch
]);
const handleSubmit = (0, import_react26.useCallback)((value, index, itemData) => {
value !== void 0 && searchActions.setQuery(value);
searchActions.setOffset(0);
searchActions.setFacets([]);
clearStaticRangeFilters(searchActions);
if (itemData && isVerticalLink(itemData.verticalLink) && onSelectVerticalLink) {
onSelectVerticalLink({ verticalLink: itemData.verticalLink, querySource: import_search_headless_react7.QuerySource.Autocomplete });
} else {
executeQuery();
}
if (typeof index === "number" && index >= 0 && !itemData?.isEntityPreview) {
reportAnalyticsEvent("AUTO_COMPLETE_SELECTION", value);
}
}, [searchActions, executeQuery, onSelectVerticalLink, reportAnalyticsEvent]);
const [
entityPreviewsState,
executeEntityPreviewsQuery
] = useEntityPreviews(entityPreviewSearcher, entityPreviewsDebouncingTime);
const { verticalKeyToResults, isLoading: entityPreviewsLoading } = entityPreviewsState;
const entityPreviews = renderEntityPreviews?.(
entityPreviewsLoading,
verticalKeyToResults,
{ onClick: handleSubmit, ariaLabel: getAriaLabel }
);
const updateEntityPreviews = (0, import_react26.useCallback)((query2) => {
if (!renderEntityPreviews || !includedVerticals) {
return;
}
executeEntityPreviewsQuery(query2, universalLimit ?? {}, includedVerticals);
}, [executeEntityPreviewsQuery, renderEntityPreviews, includedVerticals, universalLimit]);
const handleInputFocus = (0, import_react26.useCallback)((value = "") => {
searchActions.setQuery(value);
updateEntityPreviews(value);
autocompletePromiseRef.current = executeAutocomplete2();
}, [searchActions, autocompletePromiseRef, executeAutocomplete2, updateEntityPreviews]);
const handleInputChange = (0, import_react26.useCallback)((value = "") => {
searchActions.setQuery(value);
updateEntityPreviews(value);
autocompletePromiseRef.current = executeAutocomplete2();
}, [searchActions, autocompletePromiseRef, executeAutocomplete2, updateEntityPreviews]);
const handleClickClearButton = (0, import_react26.useCallback)(() => {
updateEntityPreviews("");
searchActions.setQuery("");
reportAnalyticsEvent("SEARCH_CLEAR_BUTTON");
}, [handleSubmit, reportAnalyticsEvent, updateEntityPreviews]);
function renderInput() {
return /* @__PURE__ */ import_react26.default.createElement(
DropdownInput,
{
className: cssClasses.inputElement,
placeholder,
onSubmit: handleSubmit,
onFocus: handleInputFocus,
onChange: handleInputChange,
ariaLabel: "Conduct a search"
}
);
}
function renderRecentSearches() {
const recentSearchesCssClasses = {
icon: cssClasses.recentSearchesIcon,
option: cssClasses.recentSearchesOption,
nonHighlighted: cssClasses.recentSearchesNonHighlighted
};
return filteredRecentSearches?.map((result, i) => /* @__PURE__ */ import_react26.default.createElement(
DropdownItem,
{
className: "flex items-center h-6.5 px-3.5 py-1.5 cursor-pointer hover:bg-gray-100",
focusedClassName: twMerge("flex items-center h-6.5 px-3.5 py-1.5 cursor-pointer hover:bg-gray-100", cssClasses.focusedOption),
key: i,
value: result.query,
onClick: handleSubmit
},
renderAutocompleteResult(
{ value: result.query, inputIntents: [] },
recentSearchesCssClasses,
HistoryIcon,
`recent search: ${result.query}`
)
));
}
const itemDataMatrix = (0, import_react26.useMemo)(() => {
return autocompleteResponse?.results.map((result) => {
return result.verticalKeys?.map((verticalKey2) => ({
verticalLink: { verticalKey: verticalKey2, query: result.value }
})) ?? [];
}) ?? [];
}, [autocompleteResponse?.results]);
function renderQuerySuggestions() {
return autocompleteResponse?.results.map((result, i) => /* @__PURE__ */ import_react26.default.createElement(import_react26.Fragment, { key: i }, /* @__PURE__ */ import_react26.default.createElement(
DropdownItem,
{
className: "flex items-stretch py-1.5 px-3.5 cursor-pointer hover:bg-gray-100",
focusedClassName: twMerge("flex items-stretch py-1.5 px-3.5 cursor-pointer hover:bg-gray-100", cssClasses.focusedOption),
value: result.value,
onClick: handleSubmit
},
renderAutocompleteResult(
result,
cssClasses,
MagnifyingGlassIcon,
`auto