@seekora-ai/ui-sdk-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Breadcrumb.d.ts +43 -0
- package/dist/components/Breadcrumb.d.ts.map +1 -0
- package/dist/components/Breadcrumb.js +119 -0
- package/dist/components/ClearRefinements.d.ts +42 -0
- package/dist/components/ClearRefinements.d.ts.map +1 -0
- package/dist/components/ClearRefinements.js +80 -0
- package/dist/components/CurrentRefinements.d.ts +41 -0
- package/dist/components/CurrentRefinements.d.ts.map +1 -0
- package/dist/components/CurrentRefinements.js +83 -0
- package/dist/components/Facets.d.ts +53 -0
- package/dist/components/Facets.d.ts.map +1 -0
- package/dist/components/Facets.js +195 -0
- package/dist/components/FederatedDropdown.d.ts +92 -0
- package/dist/components/FederatedDropdown.d.ts.map +1 -0
- package/dist/components/FederatedDropdown.js +510 -0
- package/dist/components/HierarchicalMenu.d.ts +55 -0
- package/dist/components/HierarchicalMenu.d.ts.map +1 -0
- package/dist/components/HierarchicalMenu.js +168 -0
- package/dist/components/Highlight.d.ts +51 -0
- package/dist/components/Highlight.d.ts.map +1 -0
- package/dist/components/Highlight.js +155 -0
- package/dist/components/HitsPerPage.d.ts +41 -0
- package/dist/components/HitsPerPage.d.ts.map +1 -0
- package/dist/components/HitsPerPage.js +72 -0
- package/dist/components/InfiniteHits.d.ts +56 -0
- package/dist/components/InfiniteHits.d.ts.map +1 -0
- package/dist/components/InfiniteHits.js +181 -0
- package/dist/components/MobileFilters.d.ts +71 -0
- package/dist/components/MobileFilters.d.ts.map +1 -0
- package/dist/components/MobileFilters.js +242 -0
- package/dist/components/Pagination.d.ts +44 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +142 -0
- package/dist/components/QuerySuggestions.d.ts +38 -0
- package/dist/components/QuerySuggestions.d.ts.map +1 -0
- package/dist/components/QuerySuggestions.js +86 -0
- package/dist/components/QuerySuggestionsDropdown.d.ts +86 -0
- package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -0
- package/dist/components/QuerySuggestionsDropdown.js +395 -0
- package/dist/components/RangeInput.d.ts +58 -0
- package/dist/components/RangeInput.d.ts.map +1 -0
- package/dist/components/RangeInput.js +203 -0
- package/dist/components/RangeSlider.d.ts +51 -0
- package/dist/components/RangeSlider.d.ts.map +1 -0
- package/dist/components/RangeSlider.js +193 -0
- package/dist/components/Recommendations.d.ts +90 -0
- package/dist/components/Recommendations.d.ts.map +1 -0
- package/dist/components/Recommendations.js +270 -0
- package/dist/components/RichQuerySuggestions.d.ts +77 -0
- package/dist/components/RichQuerySuggestions.d.ts.map +1 -0
- package/dist/components/RichQuerySuggestions.js +492 -0
- package/dist/components/SearchBar.d.ts +40 -0
- package/dist/components/SearchBar.d.ts.map +1 -0
- package/dist/components/SearchBar.js +217 -0
- package/dist/components/SearchBarWithSuggestions.d.ts +99 -0
- package/dist/components/SearchBarWithSuggestions.d.ts.map +1 -0
- package/dist/components/SearchBarWithSuggestions.js +275 -0
- package/dist/components/SearchLayout.d.ts +35 -0
- package/dist/components/SearchLayout.d.ts.map +1 -0
- package/dist/components/SearchLayout.js +56 -0
- package/dist/components/SearchProvider.d.ts +28 -0
- package/dist/components/SearchProvider.d.ts.map +1 -0
- package/dist/components/SearchProvider.js +43 -0
- package/dist/components/SearchResults.d.ts +51 -0
- package/dist/components/SearchResults.d.ts.map +1 -0
- package/dist/components/SearchResults.js +485 -0
- package/dist/components/SortBy.d.ts +44 -0
- package/dist/components/SortBy.d.ts.map +1 -0
- package/dist/components/SortBy.js +61 -0
- package/dist/components/Stats.d.ts +37 -0
- package/dist/components/Stats.d.ts.map +1 -0
- package/dist/components/Stats.js +52 -0
- package/dist/components/suggestions/AmazonDropdown.d.ts +30 -0
- package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/AmazonDropdown.js +529 -0
- package/dist/components/suggestions/GoogleDropdown.d.ts +31 -0
- package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/GoogleDropdown.js +370 -0
- package/dist/components/suggestions/MinimalDropdown.d.ts +24 -0
- package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/MinimalDropdown.js +314 -0
- package/dist/components/suggestions/MobileSheetDropdown.d.ts +31 -0
- package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/MobileSheetDropdown.js +485 -0
- package/dist/components/suggestions/PinterestDropdown.d.ts +29 -0
- package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/PinterestDropdown.js +450 -0
- package/dist/components/suggestions/ShopifyDropdown.d.ts +27 -0
- package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/ShopifyDropdown.js +451 -0
- package/dist/components/suggestions/SpotlightDropdown.d.ts +33 -0
- package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -0
- package/dist/components/suggestions/SpotlightDropdown.js +547 -0
- package/dist/components/suggestions/SuggestionSearchBar.d.ts +123 -0
- package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -0
- package/dist/components/suggestions/SuggestionSearchBar.js +652 -0
- package/dist/components/suggestions/index.d.ts +37 -0
- package/dist/components/suggestions/index.d.ts.map +1 -0
- package/dist/components/suggestions/index.js +59 -0
- package/dist/components/suggestions/styles/index.d.ts +11 -0
- package/dist/components/suggestions/styles/index.d.ts.map +1 -0
- package/dist/components/suggestions/styles/index.js +289 -0
- package/dist/components/suggestions/styles/responsive.d.ts +107 -0
- package/dist/components/suggestions/styles/responsive.d.ts.map +1 -0
- package/dist/components/suggestions/styles/responsive.js +237 -0
- package/dist/components/suggestions/types.d.ts +489 -0
- package/dist/components/suggestions/types.d.ts.map +1 -0
- package/dist/components/suggestions/types.js +6 -0
- package/dist/components/suggestions/utils.d.ts +213 -0
- package/dist/components/suggestions/utils.d.ts.map +1 -0
- package/dist/components/suggestions/utils.js +514 -0
- package/dist/hooks/useAnalytics.d.ts +20 -0
- package/dist/hooks/useAnalytics.d.ts.map +1 -0
- package/dist/hooks/useAnalytics.js +62 -0
- package/dist/hooks/useNaturalLanguageFilters.d.ts +48 -0
- package/dist/hooks/useNaturalLanguageFilters.d.ts.map +1 -0
- package/dist/hooks/useNaturalLanguageFilters.js +221 -0
- package/dist/hooks/useQuerySuggestions.d.ts +21 -0
- package/dist/hooks/useQuerySuggestions.d.ts.map +1 -0
- package/dist/hooks/useQuerySuggestions.js +68 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts +114 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.js +376 -0
- package/dist/hooks/useSearchState.d.ts +35 -0
- package/dist/hooks/useSearchState.d.ts.map +1 -0
- package/dist/hooks/useSearchState.js +68 -0
- package/dist/hooks/useSeekoraSearch.d.ts +20 -0
- package/dist/hooks/useSeekoraSearch.d.ts.map +1 -0
- package/dist/hooks/useSeekoraSearch.js +63 -0
- package/dist/hooks/useSmartSuggestions.d.ts +55 -0
- package/dist/hooks/useSmartSuggestions.d.ts.map +1 -0
- package/dist/hooks/useSmartSuggestions.js +236 -0
- package/dist/hooks/useSuggestionsAnalytics.d.ts +91 -0
- package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -0
- package/dist/hooks/useSuggestionsAnalytics.js +226 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +86 -0
- package/dist/index.umd.js +1 -0
- package/dist/src/index.d.ts +2849 -0
- package/dist/src/index.esm.js +11679 -0
- package/dist/src/index.esm.js.map +1 -0
- package/dist/src/index.js +11761 -0
- package/dist/src/index.js.map +1 -0
- package/dist/themes/createTheme.d.ts +8 -0
- package/dist/themes/createTheme.d.ts.map +1 -0
- package/dist/themes/createTheme.js +10 -0
- package/dist/themes/dark.d.ts +6 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +34 -0
- package/dist/themes/default.d.ts +6 -0
- package/dist/themes/default.d.ts.map +1 -0
- package/dist/themes/default.js +71 -0
- package/dist/themes/mergeThemes.d.ts +7 -0
- package/dist/themes/mergeThemes.d.ts.map +1 -0
- package/dist/themes/mergeThemes.js +6 -0
- package/dist/themes/minimal.d.ts +6 -0
- package/dist/themes/minimal.d.ts.map +1 -0
- package/dist/themes/minimal.js +34 -0
- package/dist/themes/suggestions.d.ts +216 -0
- package/dist/themes/suggestions.d.ts.map +1 -0
- package/dist/themes/suggestions.js +546 -0
- package/dist/themes/types.d.ts +7 -0
- package/dist/themes/types.d.ts.map +1 -0
- package/dist/themes/types.js +6 -0
- package/dist/types/index.d.ts +33 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/package.json +65 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Query Suggestions Hook
|
|
3
|
+
*
|
|
4
|
+
* Provides full support for query suggestions API including:
|
|
5
|
+
* - Basic suggestions
|
|
6
|
+
* - Dropdown recommendations (trending, top searches, related)
|
|
7
|
+
* - Filtered tabs with products
|
|
8
|
+
* - Recent searches (local storage)
|
|
9
|
+
* - Analytics tracking
|
|
10
|
+
*/
|
|
11
|
+
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
|
12
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Local Storage Helpers
|
|
15
|
+
// ============================================================================
|
|
16
|
+
const RECENT_SEARCHES_DEFAULT_KEY = 'seekora_recent_searches';
|
|
17
|
+
const MAX_RECENT_SEARCHES_DEFAULT = 10;
|
|
18
|
+
function getRecentSearchesFromStorage(key) {
|
|
19
|
+
if (typeof window === 'undefined')
|
|
20
|
+
return [];
|
|
21
|
+
try {
|
|
22
|
+
const stored = localStorage.getItem(key);
|
|
23
|
+
if (!stored)
|
|
24
|
+
return [];
|
|
25
|
+
return JSON.parse(stored);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function saveRecentSearchesToStorage(key, searches) {
|
|
32
|
+
if (typeof window === 'undefined')
|
|
33
|
+
return;
|
|
34
|
+
try {
|
|
35
|
+
localStorage.setItem(key, JSON.stringify(searches));
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
log.warn('Failed to save recent searches to localStorage', { error });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Transform API Response
|
|
43
|
+
// ============================================================================
|
|
44
|
+
function transformSuggestion(raw) {
|
|
45
|
+
const query = raw.query || raw.text || String(raw);
|
|
46
|
+
const highlighted = raw._highlightResult?.query?.value;
|
|
47
|
+
return {
|
|
48
|
+
query,
|
|
49
|
+
popularity: raw.popularity,
|
|
50
|
+
count: raw.instant_search?.exact_nb_hits ?? raw.popularity ?? raw.count,
|
|
51
|
+
objectID: raw.objectID,
|
|
52
|
+
highlightedQuery: highlighted ? parseHighlight(highlighted) : undefined,
|
|
53
|
+
categories: raw.categories?.map((c) => ({
|
|
54
|
+
value: c.value || c.name,
|
|
55
|
+
count: c.count,
|
|
56
|
+
path: c.path,
|
|
57
|
+
})),
|
|
58
|
+
facets: raw.instant_search?.facets || raw.facets,
|
|
59
|
+
metadata: raw,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function parseHighlight(highlighted) {
|
|
63
|
+
// Convert __ais-highlight__ markers to HTML
|
|
64
|
+
return highlighted
|
|
65
|
+
.replace(/__ais-highlight__/g, '<mark>')
|
|
66
|
+
.replace(/__\/ais-highlight__/g, '</mark>');
|
|
67
|
+
}
|
|
68
|
+
function transformProduct(raw) {
|
|
69
|
+
return {
|
|
70
|
+
id: raw.id || raw.objectID,
|
|
71
|
+
objectID: raw.objectID || raw.id,
|
|
72
|
+
title: raw.title || raw.name || raw.productName,
|
|
73
|
+
name: raw.name || raw.title,
|
|
74
|
+
image: raw.image || raw.imageUrl || raw.metadata?.image,
|
|
75
|
+
price: raw.price || raw.sellPrice || raw.metadata?.sellPrice,
|
|
76
|
+
currency: raw.currency || raw.metadata?.currency || '',
|
|
77
|
+
url: raw.url || raw.productId || raw.metadata?.url,
|
|
78
|
+
clicks: raw.clicks,
|
|
79
|
+
conversions: raw.conversions,
|
|
80
|
+
revenue: raw.revenue,
|
|
81
|
+
trend_score: raw.trend_score,
|
|
82
|
+
metadata: raw.metadata || raw,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function transformFilteredTab(raw) {
|
|
86
|
+
return {
|
|
87
|
+
id: raw.id,
|
|
88
|
+
label: raw.label,
|
|
89
|
+
filter: raw.filter,
|
|
90
|
+
products: raw.products?.map(transformProduct) || [],
|
|
91
|
+
nb_hits: raw.nb_hits,
|
|
92
|
+
processing_time_ms: raw.processing_time_ms,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Main Hook
|
|
97
|
+
// ============================================================================
|
|
98
|
+
export function useQuerySuggestionsEnhanced(options) {
|
|
99
|
+
const { client, query, enabled = true, debounceMs = 200, maxSuggestions = 10, minQueryLength = 1, includeDropdownRecommendations = false, includeCategories = false, includeFacets = false, maxCategories = 3, maxFacets = 5, filteredTabs, minPopularity, timeRange, disableTypoTolerance, analyticsTags, enableRecentSearches = true, maxRecentSearches = MAX_RECENT_SEARCHES_DEFAULT, recentSearchesKey = RECENT_SEARCHES_DEFAULT_KEY, onSuggestionsLoaded, onError, } = options;
|
|
100
|
+
// State
|
|
101
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
102
|
+
const [loading, setLoading] = useState(false);
|
|
103
|
+
const [error, setError] = useState(null);
|
|
104
|
+
const [dropdownRecommendations, setDropdownRecommendations] = useState(null);
|
|
105
|
+
const [recentSearches, setRecentSearches] = useState([]);
|
|
106
|
+
const [processingTimeMs, setProcessingTimeMs] = useState(null);
|
|
107
|
+
const [totalHits, setTotalHits] = useState(0);
|
|
108
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
109
|
+
const [totalPages, setTotalPages] = useState(0);
|
|
110
|
+
const [originalQuery, setOriginalQuery] = useState('');
|
|
111
|
+
// Refs
|
|
112
|
+
const debounceTimerRef = useRef(null);
|
|
113
|
+
const abortControllerRef = useRef(null);
|
|
114
|
+
const mountedRef = useRef(true);
|
|
115
|
+
// Load recent searches on mount
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (enableRecentSearches) {
|
|
118
|
+
const stored = getRecentSearchesFromStorage(recentSearchesKey);
|
|
119
|
+
setRecentSearches(stored.slice(0, maxRecentSearches));
|
|
120
|
+
}
|
|
121
|
+
return () => {
|
|
122
|
+
mountedRef.current = false;
|
|
123
|
+
};
|
|
124
|
+
}, [enableRecentSearches, recentSearchesKey, maxRecentSearches]);
|
|
125
|
+
// Fetch suggestions
|
|
126
|
+
const fetchSuggestions = useCallback(async (searchQuery) => {
|
|
127
|
+
if (!client || !searchQuery.trim()) {
|
|
128
|
+
setSuggestions([]);
|
|
129
|
+
setDropdownRecommendations(null);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// Cancel previous request
|
|
133
|
+
if (abortControllerRef.current) {
|
|
134
|
+
abortControllerRef.current.abort();
|
|
135
|
+
}
|
|
136
|
+
abortControllerRef.current = new AbortController();
|
|
137
|
+
setLoading(true);
|
|
138
|
+
setError(null);
|
|
139
|
+
try {
|
|
140
|
+
const response = await client.getSuggestions?.(searchQuery, {
|
|
141
|
+
hitsPerPage: maxSuggestions,
|
|
142
|
+
include_dropdown_recommendations: includeDropdownRecommendations || (filteredTabs && filteredTabs.length > 0),
|
|
143
|
+
include_categories: includeCategories,
|
|
144
|
+
include_facets: includeFacets,
|
|
145
|
+
max_categories: maxCategories,
|
|
146
|
+
max_facets: maxFacets,
|
|
147
|
+
filtered_tabs: filteredTabs,
|
|
148
|
+
min_popularity: minPopularity,
|
|
149
|
+
time_range: timeRange,
|
|
150
|
+
disable_typo_tolerance: disableTypoTolerance,
|
|
151
|
+
analytics_tags: analyticsTags,
|
|
152
|
+
returnFullResponse: true,
|
|
153
|
+
});
|
|
154
|
+
if (!mountedRef.current)
|
|
155
|
+
return;
|
|
156
|
+
// Transform suggestions
|
|
157
|
+
const rawSuggestions = response.suggestions || [];
|
|
158
|
+
const transformedSuggestions = rawSuggestions.map(transformSuggestion);
|
|
159
|
+
setSuggestions(transformedSuggestions);
|
|
160
|
+
// Extract dropdown recommendations from extensions
|
|
161
|
+
const extensions = (response.extensions || {});
|
|
162
|
+
const recommendations = {
|
|
163
|
+
trending_searches: Array.isArray(extensions.trending_searches) ? extensions.trending_searches : [],
|
|
164
|
+
top_searches: Array.isArray(extensions.top_searches) ? extensions.top_searches : [],
|
|
165
|
+
related_searches: Array.isArray(extensions.related_searches) ? extensions.related_searches : [],
|
|
166
|
+
trending_products: Array.isArray(extensions.trending_products) ? extensions.trending_products.map(transformProduct) : [],
|
|
167
|
+
item_recommendations: Array.isArray(extensions.item_recommendations) ? extensions.item_recommendations.map(transformProduct) : [],
|
|
168
|
+
popular_brands: Array.isArray(extensions.popular_brands) ? extensions.popular_brands : [],
|
|
169
|
+
filtered_tabs: Array.isArray(extensions.filtered_tabs) ? extensions.filtered_tabs.map(transformFilteredTab) : [],
|
|
170
|
+
processing_time_ms: typeof extensions.processing_time_ms === 'number' ? extensions.processing_time_ms : undefined,
|
|
171
|
+
cached_at: typeof extensions.cached_at === 'string' ? extensions.cached_at : undefined,
|
|
172
|
+
};
|
|
173
|
+
setDropdownRecommendations(recommendations);
|
|
174
|
+
// Extract metadata from raw response
|
|
175
|
+
const raw = response.raw;
|
|
176
|
+
const rawResultsArr = raw?.results;
|
|
177
|
+
const rawResult = (rawResultsArr?.[0] ?? raw ?? {});
|
|
178
|
+
const num = (v) => (typeof v === 'number' && !Number.isNaN(v) ? v : 0);
|
|
179
|
+
const str = (v) => (typeof v === 'string' ? v : '');
|
|
180
|
+
setProcessingTimeMs(typeof rawResult.processingTimeMS === 'number' ? rawResult.processingTimeMS : null);
|
|
181
|
+
setTotalHits(num(rawResult.nbHits) || transformedSuggestions.length);
|
|
182
|
+
setCurrentPage(num(rawResult.page) || 0);
|
|
183
|
+
setTotalPages(num(rawResult.nbPages) || 1);
|
|
184
|
+
setOriginalQuery(str(rawResult.query) || searchQuery);
|
|
185
|
+
// Callback
|
|
186
|
+
if (onSuggestionsLoaded) {
|
|
187
|
+
onSuggestionsLoaded({
|
|
188
|
+
suggestions: transformedSuggestions,
|
|
189
|
+
nbHits: num(rawResult.nbHits) || transformedSuggestions.length,
|
|
190
|
+
page: num(rawResult.page) || 0,
|
|
191
|
+
nbPages: num(rawResult.nbPages) || 1,
|
|
192
|
+
hitsPerPage: num(rawResult.hitsPerPage) || maxSuggestions,
|
|
193
|
+
processingTimeMS: typeof rawResult.processingTimeMS === 'number' ? rawResult.processingTimeMS : undefined,
|
|
194
|
+
query: str(rawResult.query) || searchQuery,
|
|
195
|
+
dropdownRecommendations: recommendations,
|
|
196
|
+
results: Array.isArray(response.results) ? response.results : undefined,
|
|
197
|
+
extensions,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
log.verbose('Query suggestions loaded', {
|
|
201
|
+
query: searchQuery,
|
|
202
|
+
suggestionsCount: transformedSuggestions.length,
|
|
203
|
+
hasRecommendations: Object.keys(recommendations).some(k => Array.isArray(recommendations[k]) && recommendations[k].length > 0),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
if (!mountedRef.current)
|
|
208
|
+
return;
|
|
209
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
210
|
+
if (error.name === 'AbortError')
|
|
211
|
+
return;
|
|
212
|
+
log.error('Failed to fetch query suggestions', { query: searchQuery, error: error.message });
|
|
213
|
+
setError(error);
|
|
214
|
+
setSuggestions([]);
|
|
215
|
+
setDropdownRecommendations(null);
|
|
216
|
+
if (onError) {
|
|
217
|
+
onError(error);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
if (mountedRef.current) {
|
|
222
|
+
setLoading(false);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}, [
|
|
226
|
+
client,
|
|
227
|
+
maxSuggestions,
|
|
228
|
+
includeDropdownRecommendations,
|
|
229
|
+
includeCategories,
|
|
230
|
+
includeFacets,
|
|
231
|
+
maxCategories,
|
|
232
|
+
maxFacets,
|
|
233
|
+
filteredTabs,
|
|
234
|
+
minPopularity,
|
|
235
|
+
timeRange,
|
|
236
|
+
disableTypoTolerance,
|
|
237
|
+
analyticsTags,
|
|
238
|
+
onSuggestionsLoaded,
|
|
239
|
+
onError,
|
|
240
|
+
]);
|
|
241
|
+
// Debounced fetch effect
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
if (debounceTimerRef.current) {
|
|
244
|
+
clearTimeout(debounceTimerRef.current);
|
|
245
|
+
}
|
|
246
|
+
if (!enabled || query.length < minQueryLength) {
|
|
247
|
+
setSuggestions([]);
|
|
248
|
+
setLoading(false);
|
|
249
|
+
setError(null);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
setLoading(true);
|
|
253
|
+
debounceTimerRef.current = setTimeout(() => {
|
|
254
|
+
fetchSuggestions(query);
|
|
255
|
+
}, debounceMs);
|
|
256
|
+
return () => {
|
|
257
|
+
if (debounceTimerRef.current) {
|
|
258
|
+
clearTimeout(debounceTimerRef.current);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}, [query, enabled, minQueryLength, debounceMs, fetchSuggestions]);
|
|
262
|
+
// Recent search management
|
|
263
|
+
const addRecentSearch = useCallback((searchQuery, resultsCount) => {
|
|
264
|
+
if (!enableRecentSearches || !searchQuery.trim())
|
|
265
|
+
return;
|
|
266
|
+
setRecentSearches(prev => {
|
|
267
|
+
// Remove existing entry for same query
|
|
268
|
+
const filtered = prev.filter(s => s.query.toLowerCase() !== searchQuery.toLowerCase());
|
|
269
|
+
// Add new entry at the beginning
|
|
270
|
+
const newSearch = {
|
|
271
|
+
query: searchQuery.trim(),
|
|
272
|
+
timestamp: Date.now(),
|
|
273
|
+
resultsCount,
|
|
274
|
+
};
|
|
275
|
+
const updated = [newSearch, ...filtered].slice(0, maxRecentSearches);
|
|
276
|
+
saveRecentSearchesToStorage(recentSearchesKey, updated);
|
|
277
|
+
return updated;
|
|
278
|
+
});
|
|
279
|
+
}, [enableRecentSearches, maxRecentSearches, recentSearchesKey]);
|
|
280
|
+
const removeRecentSearch = useCallback((searchQuery) => {
|
|
281
|
+
setRecentSearches(prev => {
|
|
282
|
+
const updated = prev.filter(s => s.query !== searchQuery);
|
|
283
|
+
saveRecentSearchesToStorage(recentSearchesKey, updated);
|
|
284
|
+
return updated;
|
|
285
|
+
});
|
|
286
|
+
}, [recentSearchesKey]);
|
|
287
|
+
const clearRecentSearches = useCallback(() => {
|
|
288
|
+
setRecentSearches([]);
|
|
289
|
+
saveRecentSearchesToStorage(recentSearchesKey, []);
|
|
290
|
+
}, [recentSearchesKey]);
|
|
291
|
+
// Manual refetch
|
|
292
|
+
const refetch = useCallback(async () => {
|
|
293
|
+
if (query.length >= minQueryLength) {
|
|
294
|
+
await fetchSuggestions(query);
|
|
295
|
+
}
|
|
296
|
+
}, [query, minQueryLength, fetchSuggestions]);
|
|
297
|
+
// Derived values
|
|
298
|
+
const trendingSearches = dropdownRecommendations?.trending_searches || [];
|
|
299
|
+
const topSearches = dropdownRecommendations?.top_searches || [];
|
|
300
|
+
const relatedSearches = dropdownRecommendations?.related_searches || [];
|
|
301
|
+
const popularBrands = dropdownRecommendations?.popular_brands || [];
|
|
302
|
+
const filteredTabsResult = dropdownRecommendations?.filtered_tabs || [];
|
|
303
|
+
const trendingProducts = dropdownRecommendations?.trending_products || [];
|
|
304
|
+
const hasContent = useMemo(() => {
|
|
305
|
+
return (suggestions.length > 0 ||
|
|
306
|
+
recentSearches.length > 0 ||
|
|
307
|
+
trendingSearches.length > 0 ||
|
|
308
|
+
topSearches.length > 0 ||
|
|
309
|
+
relatedSearches.length > 0 ||
|
|
310
|
+
popularBrands.length > 0 ||
|
|
311
|
+
filteredTabsResult.length > 0 ||
|
|
312
|
+
trendingProducts.length > 0);
|
|
313
|
+
}, [
|
|
314
|
+
suggestions,
|
|
315
|
+
recentSearches,
|
|
316
|
+
trendingSearches,
|
|
317
|
+
topSearches,
|
|
318
|
+
relatedSearches,
|
|
319
|
+
popularBrands,
|
|
320
|
+
filteredTabsResult,
|
|
321
|
+
trendingProducts,
|
|
322
|
+
]);
|
|
323
|
+
// Get all navigable items for keyboard navigation
|
|
324
|
+
const getAllNavigableItems = useCallback(() => {
|
|
325
|
+
const items = [];
|
|
326
|
+
let index = 0;
|
|
327
|
+
// Recent searches first (when query is empty)
|
|
328
|
+
if (query.length === 0 && recentSearches.length > 0) {
|
|
329
|
+
recentSearches.forEach(search => {
|
|
330
|
+
items.push({ type: 'recent', index: index++, data: search });
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// Suggestions
|
|
334
|
+
suggestions.forEach(suggestion => {
|
|
335
|
+
items.push({ type: 'suggestion', index: index++, data: suggestion });
|
|
336
|
+
});
|
|
337
|
+
// Trending searches
|
|
338
|
+
trendingSearches.forEach(trending => {
|
|
339
|
+
items.push({ type: 'trending', index: index++, data: trending });
|
|
340
|
+
});
|
|
341
|
+
// Products
|
|
342
|
+
trendingProducts.forEach(product => {
|
|
343
|
+
items.push({ type: 'product', index: index++, data: product });
|
|
344
|
+
});
|
|
345
|
+
// Brands
|
|
346
|
+
popularBrands.forEach(brand => {
|
|
347
|
+
items.push({ type: 'brand', index: index++, data: brand });
|
|
348
|
+
});
|
|
349
|
+
return items;
|
|
350
|
+
}, [query, recentSearches, suggestions, trendingSearches, trendingProducts, popularBrands]);
|
|
351
|
+
return {
|
|
352
|
+
suggestions,
|
|
353
|
+
loading,
|
|
354
|
+
error,
|
|
355
|
+
dropdownRecommendations,
|
|
356
|
+
trendingSearches,
|
|
357
|
+
topSearches,
|
|
358
|
+
relatedSearches,
|
|
359
|
+
popularBrands,
|
|
360
|
+
filteredTabs: filteredTabsResult,
|
|
361
|
+
trendingProducts,
|
|
362
|
+
recentSearches,
|
|
363
|
+
processingTimeMs,
|
|
364
|
+
totalHits,
|
|
365
|
+
currentPage,
|
|
366
|
+
totalPages,
|
|
367
|
+
originalQuery,
|
|
368
|
+
addRecentSearch,
|
|
369
|
+
removeRecentSearch,
|
|
370
|
+
clearRecentSearches,
|
|
371
|
+
refetch,
|
|
372
|
+
hasContent,
|
|
373
|
+
getAllNavigableItems,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
export default useQuerySuggestionsEnhanced;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSearchState Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for accessing and managing search state via SearchStateManager
|
|
5
|
+
* Provides reactive state and methods to update search parameters
|
|
6
|
+
*/
|
|
7
|
+
import type { SearchResponse } from '@seekora-ai/search-sdk';
|
|
8
|
+
import { SearchStateManager, type SearchState } from '@seekora-ai/ui-sdk-core';
|
|
9
|
+
export interface UseSearchStateReturn {
|
|
10
|
+
query: string;
|
|
11
|
+
refinements: Array<{
|
|
12
|
+
field: string;
|
|
13
|
+
value: string;
|
|
14
|
+
}>;
|
|
15
|
+
currentPage: number;
|
|
16
|
+
itemsPerPage: number;
|
|
17
|
+
sortBy?: string;
|
|
18
|
+
results: SearchState['results'];
|
|
19
|
+
loading: boolean;
|
|
20
|
+
error: Error | null;
|
|
21
|
+
setQuery: (query: string, triggerSearch?: boolean) => void;
|
|
22
|
+
addRefinement: (field: string, value: string, triggerSearch?: boolean) => void;
|
|
23
|
+
removeRefinement: (field: string, value: string, triggerSearch?: boolean) => void;
|
|
24
|
+
clearRefinements: (triggerSearch?: boolean) => void;
|
|
25
|
+
setPage: (page: number, triggerSearch?: boolean) => void;
|
|
26
|
+
setSortBy: (sortBy: string, triggerSearch?: boolean) => void;
|
|
27
|
+
search: (additionalOptions?: Parameters<SearchStateManager['search']>[0]) => Promise<SearchResponse | null>;
|
|
28
|
+
clear: () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hook to access and manage search state
|
|
32
|
+
* Automatically subscribes to state changes and re-renders when state updates
|
|
33
|
+
*/
|
|
34
|
+
export declare const useSearchState: () => UseSearchStateReturn;
|
|
35
|
+
//# sourceMappingURL=useSearchState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSearchState.d.ts","sourceRoot":"","sources":["../../src/hooks/useSearchState.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IAEnC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAGpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/E,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAClF,gBAAgB,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACpD,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACzD,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7D,MAAM,EAAE,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IAC5G,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,oBAkEjC,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSearchState Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for accessing and managing search state via SearchStateManager
|
|
5
|
+
* Provides reactive state and methods to update search parameters
|
|
6
|
+
*/
|
|
7
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
8
|
+
import { useSearchContext } from '../components/SearchProvider';
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access and manage search state
|
|
11
|
+
* Automatically subscribes to state changes and re-renders when state updates
|
|
12
|
+
*/
|
|
13
|
+
export const useSearchState = () => {
|
|
14
|
+
const { stateManager } = useSearchContext();
|
|
15
|
+
const [state, setState] = useState(stateManager.getState());
|
|
16
|
+
// Subscribe to state changes
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const unsubscribe = stateManager.subscribe((newState) => {
|
|
19
|
+
setState(newState);
|
|
20
|
+
});
|
|
21
|
+
return unsubscribe;
|
|
22
|
+
}, [stateManager]);
|
|
23
|
+
// Memoized action methods
|
|
24
|
+
const setQuery = useCallback((query, triggerSearch = true) => {
|
|
25
|
+
stateManager.setQuery(query, triggerSearch);
|
|
26
|
+
}, [stateManager]);
|
|
27
|
+
const addRefinement = useCallback((field, value, triggerSearch = true) => {
|
|
28
|
+
stateManager.addRefinement(field, value, triggerSearch);
|
|
29
|
+
}, [stateManager]);
|
|
30
|
+
const removeRefinement = useCallback((field, value, triggerSearch = true) => {
|
|
31
|
+
stateManager.removeRefinement(field, value, triggerSearch);
|
|
32
|
+
}, [stateManager]);
|
|
33
|
+
const clearRefinements = useCallback((triggerSearch = true) => {
|
|
34
|
+
stateManager.clearRefinements(triggerSearch);
|
|
35
|
+
}, [stateManager]);
|
|
36
|
+
const setPage = useCallback((page, triggerSearch = true) => {
|
|
37
|
+
stateManager.setPage(page, triggerSearch);
|
|
38
|
+
}, [stateManager]);
|
|
39
|
+
const setSortBy = useCallback((sortBy, triggerSearch = true) => {
|
|
40
|
+
stateManager.setSortBy(sortBy, triggerSearch);
|
|
41
|
+
}, [stateManager]);
|
|
42
|
+
const search = useCallback((additionalOptions) => {
|
|
43
|
+
return stateManager.search(additionalOptions);
|
|
44
|
+
}, [stateManager]);
|
|
45
|
+
const clear = useCallback(() => {
|
|
46
|
+
stateManager.clear();
|
|
47
|
+
}, [stateManager]);
|
|
48
|
+
return {
|
|
49
|
+
// State
|
|
50
|
+
query: state.query,
|
|
51
|
+
refinements: state.refinements,
|
|
52
|
+
currentPage: state.currentPage,
|
|
53
|
+
itemsPerPage: state.itemsPerPage,
|
|
54
|
+
sortBy: state.sortBy,
|
|
55
|
+
results: state.results,
|
|
56
|
+
loading: state.loading,
|
|
57
|
+
error: state.error,
|
|
58
|
+
// Actions
|
|
59
|
+
setQuery,
|
|
60
|
+
addRefinement,
|
|
61
|
+
removeRefinement,
|
|
62
|
+
clearRefinements,
|
|
63
|
+
setPage,
|
|
64
|
+
setSortBy,
|
|
65
|
+
search,
|
|
66
|
+
clear,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSeekoraSearch Hook
|
|
3
|
+
*
|
|
4
|
+
* Hook for performing searches with the Seekora SDK
|
|
5
|
+
*/
|
|
6
|
+
import type { SeekoraClient, SearchOptions, SearchResponse, SearchContext } from '@seekora-ai/search-sdk';
|
|
7
|
+
export interface UseSeekoraSearchOptions {
|
|
8
|
+
client: SeekoraClient;
|
|
9
|
+
autoTrack?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface UseSeekoraSearchReturn {
|
|
12
|
+
search: (options: SearchOptions) => Promise<SearchResponse | null>;
|
|
13
|
+
results: SearchResponse | null;
|
|
14
|
+
loading: boolean;
|
|
15
|
+
error: Error | null;
|
|
16
|
+
context: SearchContext | null;
|
|
17
|
+
clearResults: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare const useSeekoraSearch: ({ client, autoTrack, }: UseSeekoraSearchOptions) => UseSeekoraSearchReturn;
|
|
20
|
+
//# sourceMappingURL=useSeekoraSearch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSeekoraSearch.d.ts","sourceRoot":"","sources":["../../src/hooks/useSeekoraSearch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG1G,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACnE,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,gBAAgB,GAAI,wBAG9B,uBAAuB,KAAG,sBA8D5B,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSeekoraSearch Hook
|
|
3
|
+
*
|
|
4
|
+
* Hook for performing searches with the Seekora SDK
|
|
5
|
+
*/
|
|
6
|
+
import { useState, useCallback } from 'react';
|
|
7
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
8
|
+
export const useSeekoraSearch = ({ client, autoTrack = true, }) => {
|
|
9
|
+
const [results, setResults] = useState(null);
|
|
10
|
+
const [loading, setLoading] = useState(false);
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
const [context, setContext] = useState(null);
|
|
13
|
+
const search = useCallback(async (options) => {
|
|
14
|
+
setLoading(true);
|
|
15
|
+
setError(null);
|
|
16
|
+
const query = options.q || '';
|
|
17
|
+
log.verbose('useSeekoraSearch: Starting search', { query, options });
|
|
18
|
+
try {
|
|
19
|
+
const { q, ...restOptions } = options;
|
|
20
|
+
const query = typeof q === 'string' ? q : '';
|
|
21
|
+
const response = await client.search(query, restOptions);
|
|
22
|
+
log.info('useSeekoraSearch: Search completed', {
|
|
23
|
+
query,
|
|
24
|
+
resultsCount: Array.isArray(response?.results) ? response.results.length : 0,
|
|
25
|
+
hasContext: !!response?.context,
|
|
26
|
+
});
|
|
27
|
+
setResults(response);
|
|
28
|
+
// Extract context from response
|
|
29
|
+
if (response.context != null) {
|
|
30
|
+
setContext(response.context);
|
|
31
|
+
}
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
36
|
+
log.error('useSeekoraSearch: Search failed', {
|
|
37
|
+
query,
|
|
38
|
+
error: error.message,
|
|
39
|
+
stack: error.stack,
|
|
40
|
+
});
|
|
41
|
+
setError(error);
|
|
42
|
+
setResults(null);
|
|
43
|
+
setContext(null);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}
|
|
49
|
+
}, [client]);
|
|
50
|
+
const clearResults = useCallback(() => {
|
|
51
|
+
setResults(null);
|
|
52
|
+
setError(null);
|
|
53
|
+
setContext(null);
|
|
54
|
+
}, []);
|
|
55
|
+
return {
|
|
56
|
+
search,
|
|
57
|
+
results,
|
|
58
|
+
loading,
|
|
59
|
+
error,
|
|
60
|
+
context,
|
|
61
|
+
clearResults,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSmartSuggestions Hook
|
|
3
|
+
*
|
|
4
|
+
* AI-enhanced query suggestions with intent understanding
|
|
5
|
+
* Provides context-aware suggestions based on user behavior and query patterns
|
|
6
|
+
*/
|
|
7
|
+
export interface SmartSuggestion {
|
|
8
|
+
text: string;
|
|
9
|
+
type: 'query' | 'correction' | 'expansion' | 'related' | 'trending';
|
|
10
|
+
confidence: number;
|
|
11
|
+
metadata?: {
|
|
12
|
+
intent?: string;
|
|
13
|
+
category?: string;
|
|
14
|
+
correctedFrom?: string;
|
|
15
|
+
expandedTo?: string[];
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface SmartSuggestionsOptions {
|
|
19
|
+
/** Minimum query length */
|
|
20
|
+
minQueryLength?: number;
|
|
21
|
+
/** Maximum suggestions to return */
|
|
22
|
+
maxSuggestions?: number;
|
|
23
|
+
/** Debounce delay in ms */
|
|
24
|
+
debounceMs?: number;
|
|
25
|
+
/** Enable spell correction */
|
|
26
|
+
enableSpellCorrection?: boolean;
|
|
27
|
+
/** Enable query expansion */
|
|
28
|
+
enableQueryExpansion?: boolean;
|
|
29
|
+
/** Enable intent detection */
|
|
30
|
+
enableIntentDetection?: boolean;
|
|
31
|
+
/** Include trending queries when query is empty */
|
|
32
|
+
includeTrending?: boolean;
|
|
33
|
+
/** User context for personalization */
|
|
34
|
+
userContext?: {
|
|
35
|
+
recentSearches?: string[];
|
|
36
|
+
preferences?: Record<string, any>;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface UseSmartSuggestionsReturn {
|
|
40
|
+
suggestions: SmartSuggestion[];
|
|
41
|
+
loading: boolean;
|
|
42
|
+
error: Error | null;
|
|
43
|
+
/** Detected intent from the query */
|
|
44
|
+
detectedIntent: string | null;
|
|
45
|
+
/** Suggested corrections if query has typos */
|
|
46
|
+
corrections: string[];
|
|
47
|
+
/** Expanded query terms */
|
|
48
|
+
expansions: string[];
|
|
49
|
+
/** Process a query for smart suggestions */
|
|
50
|
+
getSuggestions: (query: string) => Promise<SmartSuggestion[]>;
|
|
51
|
+
/** Clear current suggestions */
|
|
52
|
+
clear: () => void;
|
|
53
|
+
}
|
|
54
|
+
export declare function useSmartSuggestions(query: string, options?: SmartSuggestionsOptions): UseSmartSuggestionsReturn;
|
|
55
|
+
//# sourceMappingURL=useSmartSuggestions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSmartSuggestions.d.ts","sourceRoot":"","sources":["../../src/hooks/useSmartSuggestions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;IACpE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,uBAAuB;IACtC,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6BAA6B;IAC7B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,mDAAmD;IACnD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,WAAW,CAAC,EAAE;QACZ,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,qCAAqC;IACrC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,+CAA+C;IAC/C,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2BAA2B;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,4CAA4C;IAC5C,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC9D,gCAAgC;IAChC,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAsHD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B,GACpC,yBAAyB,CA6J3B"}
|