@seekora-ai/ui-sdk-react 0.1.1

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.
Files changed (169) hide show
  1. package/dist/components/Breadcrumb.d.ts +43 -0
  2. package/dist/components/Breadcrumb.d.ts.map +1 -0
  3. package/dist/components/Breadcrumb.js +119 -0
  4. package/dist/components/ClearRefinements.d.ts +42 -0
  5. package/dist/components/ClearRefinements.d.ts.map +1 -0
  6. package/dist/components/ClearRefinements.js +80 -0
  7. package/dist/components/CurrentRefinements.d.ts +41 -0
  8. package/dist/components/CurrentRefinements.d.ts.map +1 -0
  9. package/dist/components/CurrentRefinements.js +83 -0
  10. package/dist/components/Facets.d.ts +53 -0
  11. package/dist/components/Facets.d.ts.map +1 -0
  12. package/dist/components/Facets.js +195 -0
  13. package/dist/components/FederatedDropdown.d.ts +92 -0
  14. package/dist/components/FederatedDropdown.d.ts.map +1 -0
  15. package/dist/components/FederatedDropdown.js +510 -0
  16. package/dist/components/HierarchicalMenu.d.ts +55 -0
  17. package/dist/components/HierarchicalMenu.d.ts.map +1 -0
  18. package/dist/components/HierarchicalMenu.js +168 -0
  19. package/dist/components/Highlight.d.ts +51 -0
  20. package/dist/components/Highlight.d.ts.map +1 -0
  21. package/dist/components/Highlight.js +155 -0
  22. package/dist/components/HitsPerPage.d.ts +41 -0
  23. package/dist/components/HitsPerPage.d.ts.map +1 -0
  24. package/dist/components/HitsPerPage.js +72 -0
  25. package/dist/components/InfiniteHits.d.ts +56 -0
  26. package/dist/components/InfiniteHits.d.ts.map +1 -0
  27. package/dist/components/InfiniteHits.js +181 -0
  28. package/dist/components/MobileFilters.d.ts +71 -0
  29. package/dist/components/MobileFilters.d.ts.map +1 -0
  30. package/dist/components/MobileFilters.js +242 -0
  31. package/dist/components/Pagination.d.ts +44 -0
  32. package/dist/components/Pagination.d.ts.map +1 -0
  33. package/dist/components/Pagination.js +142 -0
  34. package/dist/components/QuerySuggestions.d.ts +38 -0
  35. package/dist/components/QuerySuggestions.d.ts.map +1 -0
  36. package/dist/components/QuerySuggestions.js +86 -0
  37. package/dist/components/QuerySuggestionsDropdown.d.ts +86 -0
  38. package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -0
  39. package/dist/components/QuerySuggestionsDropdown.js +395 -0
  40. package/dist/components/RangeInput.d.ts +58 -0
  41. package/dist/components/RangeInput.d.ts.map +1 -0
  42. package/dist/components/RangeInput.js +203 -0
  43. package/dist/components/RangeSlider.d.ts +51 -0
  44. package/dist/components/RangeSlider.d.ts.map +1 -0
  45. package/dist/components/RangeSlider.js +193 -0
  46. package/dist/components/Recommendations.d.ts +90 -0
  47. package/dist/components/Recommendations.d.ts.map +1 -0
  48. package/dist/components/Recommendations.js +270 -0
  49. package/dist/components/RichQuerySuggestions.d.ts +77 -0
  50. package/dist/components/RichQuerySuggestions.d.ts.map +1 -0
  51. package/dist/components/RichQuerySuggestions.js +492 -0
  52. package/dist/components/SearchBar.d.ts +40 -0
  53. package/dist/components/SearchBar.d.ts.map +1 -0
  54. package/dist/components/SearchBar.js +217 -0
  55. package/dist/components/SearchBarWithSuggestions.d.ts +99 -0
  56. package/dist/components/SearchBarWithSuggestions.d.ts.map +1 -0
  57. package/dist/components/SearchBarWithSuggestions.js +275 -0
  58. package/dist/components/SearchLayout.d.ts +35 -0
  59. package/dist/components/SearchLayout.d.ts.map +1 -0
  60. package/dist/components/SearchLayout.js +56 -0
  61. package/dist/components/SearchProvider.d.ts +28 -0
  62. package/dist/components/SearchProvider.d.ts.map +1 -0
  63. package/dist/components/SearchProvider.js +43 -0
  64. package/dist/components/SearchResults.d.ts +51 -0
  65. package/dist/components/SearchResults.d.ts.map +1 -0
  66. package/dist/components/SearchResults.js +485 -0
  67. package/dist/components/SortBy.d.ts +44 -0
  68. package/dist/components/SortBy.d.ts.map +1 -0
  69. package/dist/components/SortBy.js +61 -0
  70. package/dist/components/Stats.d.ts +37 -0
  71. package/dist/components/Stats.d.ts.map +1 -0
  72. package/dist/components/Stats.js +52 -0
  73. package/dist/components/suggestions/AmazonDropdown.d.ts +30 -0
  74. package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -0
  75. package/dist/components/suggestions/AmazonDropdown.js +529 -0
  76. package/dist/components/suggestions/GoogleDropdown.d.ts +31 -0
  77. package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -0
  78. package/dist/components/suggestions/GoogleDropdown.js +370 -0
  79. package/dist/components/suggestions/MinimalDropdown.d.ts +24 -0
  80. package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -0
  81. package/dist/components/suggestions/MinimalDropdown.js +314 -0
  82. package/dist/components/suggestions/MobileSheetDropdown.d.ts +31 -0
  83. package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -0
  84. package/dist/components/suggestions/MobileSheetDropdown.js +485 -0
  85. package/dist/components/suggestions/PinterestDropdown.d.ts +29 -0
  86. package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -0
  87. package/dist/components/suggestions/PinterestDropdown.js +450 -0
  88. package/dist/components/suggestions/ShopifyDropdown.d.ts +27 -0
  89. package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -0
  90. package/dist/components/suggestions/ShopifyDropdown.js +451 -0
  91. package/dist/components/suggestions/SpotlightDropdown.d.ts +33 -0
  92. package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -0
  93. package/dist/components/suggestions/SpotlightDropdown.js +547 -0
  94. package/dist/components/suggestions/SuggestionSearchBar.d.ts +123 -0
  95. package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -0
  96. package/dist/components/suggestions/SuggestionSearchBar.js +652 -0
  97. package/dist/components/suggestions/index.d.ts +37 -0
  98. package/dist/components/suggestions/index.d.ts.map +1 -0
  99. package/dist/components/suggestions/index.js +59 -0
  100. package/dist/components/suggestions/styles/index.d.ts +11 -0
  101. package/dist/components/suggestions/styles/index.d.ts.map +1 -0
  102. package/dist/components/suggestions/styles/index.js +289 -0
  103. package/dist/components/suggestions/styles/responsive.d.ts +107 -0
  104. package/dist/components/suggestions/styles/responsive.d.ts.map +1 -0
  105. package/dist/components/suggestions/styles/responsive.js +237 -0
  106. package/dist/components/suggestions/types.d.ts +489 -0
  107. package/dist/components/suggestions/types.d.ts.map +1 -0
  108. package/dist/components/suggestions/types.js +6 -0
  109. package/dist/components/suggestions/utils.d.ts +213 -0
  110. package/dist/components/suggestions/utils.d.ts.map +1 -0
  111. package/dist/components/suggestions/utils.js +514 -0
  112. package/dist/hooks/useAnalytics.d.ts +20 -0
  113. package/dist/hooks/useAnalytics.d.ts.map +1 -0
  114. package/dist/hooks/useAnalytics.js +62 -0
  115. package/dist/hooks/useNaturalLanguageFilters.d.ts +48 -0
  116. package/dist/hooks/useNaturalLanguageFilters.d.ts.map +1 -0
  117. package/dist/hooks/useNaturalLanguageFilters.js +221 -0
  118. package/dist/hooks/useQuerySuggestions.d.ts +21 -0
  119. package/dist/hooks/useQuerySuggestions.d.ts.map +1 -0
  120. package/dist/hooks/useQuerySuggestions.js +68 -0
  121. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts +114 -0
  122. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -0
  123. package/dist/hooks/useQuerySuggestionsEnhanced.js +376 -0
  124. package/dist/hooks/useSearchState.d.ts +35 -0
  125. package/dist/hooks/useSearchState.d.ts.map +1 -0
  126. package/dist/hooks/useSearchState.js +68 -0
  127. package/dist/hooks/useSeekoraSearch.d.ts +20 -0
  128. package/dist/hooks/useSeekoraSearch.d.ts.map +1 -0
  129. package/dist/hooks/useSeekoraSearch.js +63 -0
  130. package/dist/hooks/useSmartSuggestions.d.ts +55 -0
  131. package/dist/hooks/useSmartSuggestions.d.ts.map +1 -0
  132. package/dist/hooks/useSmartSuggestions.js +236 -0
  133. package/dist/hooks/useSuggestionsAnalytics.d.ts +91 -0
  134. package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -0
  135. package/dist/hooks/useSuggestionsAnalytics.js +226 -0
  136. package/dist/index.d.ts +80 -0
  137. package/dist/index.d.ts.map +1 -0
  138. package/dist/index.js +86 -0
  139. package/dist/index.umd.js +1 -0
  140. package/dist/src/index.d.ts +2849 -0
  141. package/dist/src/index.esm.js +11679 -0
  142. package/dist/src/index.esm.js.map +1 -0
  143. package/dist/src/index.js +11761 -0
  144. package/dist/src/index.js.map +1 -0
  145. package/dist/themes/createTheme.d.ts +8 -0
  146. package/dist/themes/createTheme.d.ts.map +1 -0
  147. package/dist/themes/createTheme.js +10 -0
  148. package/dist/themes/dark.d.ts +6 -0
  149. package/dist/themes/dark.d.ts.map +1 -0
  150. package/dist/themes/dark.js +34 -0
  151. package/dist/themes/default.d.ts +6 -0
  152. package/dist/themes/default.d.ts.map +1 -0
  153. package/dist/themes/default.js +71 -0
  154. package/dist/themes/mergeThemes.d.ts +7 -0
  155. package/dist/themes/mergeThemes.d.ts.map +1 -0
  156. package/dist/themes/mergeThemes.js +6 -0
  157. package/dist/themes/minimal.d.ts +6 -0
  158. package/dist/themes/minimal.d.ts.map +1 -0
  159. package/dist/themes/minimal.js +34 -0
  160. package/dist/themes/suggestions.d.ts +216 -0
  161. package/dist/themes/suggestions.d.ts.map +1 -0
  162. package/dist/themes/suggestions.js +546 -0
  163. package/dist/themes/types.d.ts +7 -0
  164. package/dist/themes/types.d.ts.map +1 -0
  165. package/dist/themes/types.js +6 -0
  166. package/dist/types/index.d.ts +33 -0
  167. package/dist/types/index.d.ts.map +1 -0
  168. package/dist/types/index.js +4 -0
  169. package/package.json +65 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * useNaturalLanguageFilters Hook
3
+ *
4
+ * Convert natural language queries to structured filters
5
+ * Examples:
6
+ * - "red shirts under $50" → color: red, category: shirts, price: <= 50
7
+ * - "size large blue jeans" → size: L, color: blue, category: jeans
8
+ */
9
+ import { useMemo, useCallback } from 'react';
10
+ import { useSearchState } from './useSearchState';
11
+ // Default patterns for parsing natural language
12
+ const DEFAULT_PATTERNS = {
13
+ // Price patterns
14
+ price: [
15
+ { pattern: /under\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
16
+ { pattern: /less than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<', field: 'price' },
17
+ { pattern: /over\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>=', field: 'price' },
18
+ { pattern: /more than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>', field: 'price' },
19
+ { pattern: /\$(\d+(?:\.\d{2})?)\s*-\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
20
+ { pattern: /between\s*\$?(\d+(?:\.\d{2})?)\s*and\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
21
+ { pattern: /\$(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
22
+ ],
23
+ // Color patterns
24
+ colors: ['red', 'blue', 'green', 'black', 'white', 'pink', 'purple', 'yellow', 'orange', 'brown', 'gray', 'grey', 'navy', 'beige', 'gold', 'silver'],
25
+ // Size patterns
26
+ sizes: {
27
+ 'extra small': 'XS',
28
+ 'xs': 'XS',
29
+ 'small': 'S',
30
+ 's': 'S',
31
+ 'medium': 'M',
32
+ 'm': 'M',
33
+ 'large': 'L',
34
+ 'l': 'L',
35
+ 'extra large': 'XL',
36
+ 'xl': 'XL',
37
+ 'xxl': 'XXL',
38
+ '2xl': 'XXL',
39
+ 'xxxl': 'XXXL',
40
+ '3xl': 'XXXL',
41
+ },
42
+ // Brand patterns (common examples)
43
+ brandIndicators: ['by', 'from', 'brand'],
44
+ // Rating patterns
45
+ ratings: [
46
+ { pattern: /(\d+)\s*\+?\s*stars?/i, field: 'rating', operator: '>=' },
47
+ { pattern: /rated\s*(\d+)/i, field: 'rating', operator: '>=' },
48
+ { pattern: /top\s*rated/i, field: 'rating', value: '4', operator: '>=' },
49
+ ],
50
+ // Availability patterns
51
+ availability: [
52
+ { pattern: /in\s*stock/i, field: 'inStock', value: 'true' },
53
+ { pattern: /available/i, field: 'inStock', value: 'true' },
54
+ { pattern: /on\s*sale/i, field: 'onSale', value: 'true' },
55
+ ],
56
+ };
57
+ export function useNaturalLanguageFilters(options = {}) {
58
+ const { fieldMappings = {}, valueMappings = {}, autoApply = false, currencySymbol = '$', } = options;
59
+ const { addRefinement, removeRefinement, clearRefinements, setQuery } = useSearchState();
60
+ // Merge default patterns with custom mappings
61
+ const patterns = useMemo(() => ({
62
+ ...DEFAULT_PATTERNS,
63
+ colors: [...DEFAULT_PATTERNS.colors, ...(valueMappings.color ? Object.keys(valueMappings.color) : [])],
64
+ sizes: { ...DEFAULT_PATTERNS.sizes, ...(valueMappings.size || {}) },
65
+ }), [valueMappings]);
66
+ const parse = useCallback((query) => {
67
+ const filters = [];
68
+ let cleanedQuery = query;
69
+ // Parse price filters
70
+ for (const pricePattern of patterns.price) {
71
+ const match = query.match(pricePattern.pattern);
72
+ if (match) {
73
+ if (pricePattern.operator === 'range' && match[2]) {
74
+ // Handle price range
75
+ filters.push({
76
+ field: fieldMappings.price || 'price',
77
+ value: `>=${match[1]}`,
78
+ operator: '>=',
79
+ confidence: 0.95,
80
+ matchedText: match[0],
81
+ });
82
+ filters.push({
83
+ field: fieldMappings.price || 'price',
84
+ value: `<=${match[2]}`,
85
+ operator: '<=',
86
+ confidence: 0.95,
87
+ matchedText: match[0],
88
+ });
89
+ }
90
+ else if (match[1]) {
91
+ filters.push({
92
+ field: fieldMappings.price || 'price',
93
+ value: `${pricePattern.operator}${match[1]}`,
94
+ operator: pricePattern.operator,
95
+ confidence: 0.95,
96
+ matchedText: match[0],
97
+ });
98
+ }
99
+ cleanedQuery = cleanedQuery.replace(match[0], ' ');
100
+ break; // Only match first price pattern
101
+ }
102
+ }
103
+ // Parse colors
104
+ const colorRegex = new RegExp(`\\b(${patterns.colors.join('|')})\\b`, 'gi');
105
+ const colorMatches = query.match(colorRegex);
106
+ if (colorMatches) {
107
+ colorMatches.forEach(color => {
108
+ const normalizedColor = valueMappings.color?.[color.toLowerCase()] || color.toLowerCase();
109
+ filters.push({
110
+ field: fieldMappings.color || 'color',
111
+ value: normalizedColor,
112
+ operator: '=',
113
+ confidence: 0.9,
114
+ matchedText: color,
115
+ });
116
+ cleanedQuery = cleanedQuery.replace(new RegExp(`\\b${color}\\b`, 'gi'), ' ');
117
+ });
118
+ }
119
+ // Parse sizes
120
+ const sizeEntries = Object.entries(patterns.sizes);
121
+ for (const [sizeText, sizeValue] of sizeEntries) {
122
+ const sizeRegex = new RegExp(`\\b${sizeText}\\b`, 'gi');
123
+ if (sizeRegex.test(query)) {
124
+ filters.push({
125
+ field: fieldMappings.size || 'size',
126
+ value: sizeValue,
127
+ operator: '=',
128
+ confidence: 0.85,
129
+ matchedText: sizeText,
130
+ });
131
+ cleanedQuery = cleanedQuery.replace(sizeRegex, ' ');
132
+ break; // Only match first size
133
+ }
134
+ }
135
+ // Parse ratings
136
+ for (const ratingPattern of patterns.ratings) {
137
+ if ('value' in ratingPattern) {
138
+ if (ratingPattern.pattern.test(query)) {
139
+ filters.push({
140
+ field: fieldMappings.rating || ratingPattern.field,
141
+ value: `${ratingPattern.operator}${ratingPattern.value}`,
142
+ operator: ratingPattern.operator,
143
+ confidence: 0.8,
144
+ matchedText: query.match(ratingPattern.pattern)?.[0] || '',
145
+ });
146
+ cleanedQuery = cleanedQuery.replace(ratingPattern.pattern, ' ');
147
+ }
148
+ }
149
+ else {
150
+ const match = query.match(ratingPattern.pattern);
151
+ if (match && match[1]) {
152
+ filters.push({
153
+ field: fieldMappings.rating || ratingPattern.field,
154
+ value: `${ratingPattern.operator}${match[1]}`,
155
+ operator: ratingPattern.operator,
156
+ confidence: 0.85,
157
+ matchedText: match[0],
158
+ });
159
+ cleanedQuery = cleanedQuery.replace(match[0], ' ');
160
+ }
161
+ }
162
+ }
163
+ // Parse availability
164
+ for (const availPattern of patterns.availability) {
165
+ if (availPattern.pattern.test(query)) {
166
+ filters.push({
167
+ field: fieldMappings[availPattern.field] || availPattern.field,
168
+ value: availPattern.value,
169
+ operator: '=',
170
+ confidence: 0.9,
171
+ matchedText: query.match(availPattern.pattern)?.[0] || '',
172
+ });
173
+ cleanedQuery = cleanedQuery.replace(availPattern.pattern, ' ');
174
+ }
175
+ }
176
+ // Clean up the query
177
+ cleanedQuery = cleanedQuery
178
+ .replace(/\s+/g, ' ')
179
+ .trim();
180
+ return {
181
+ cleanedQuery,
182
+ filters,
183
+ originalQuery: query,
184
+ hasFilters: filters.length > 0,
185
+ };
186
+ }, [patterns, fieldMappings, valueMappings]);
187
+ const applyFilters = useCallback((filters) => {
188
+ filters.forEach(filter => {
189
+ addRefinement(filter.field, filter.value, false);
190
+ });
191
+ // Trigger search after all filters are added
192
+ if (filters.length > 0) {
193
+ // The last addRefinement with triggerSearch=true would be called
194
+ // But we add them all with false and rely on the query change to trigger
195
+ }
196
+ }, [addRefinement]);
197
+ const parseAndApply = useCallback((query) => {
198
+ const result = parse(query);
199
+ if (result.hasFilters) {
200
+ applyFilters(result.filters);
201
+ // Update the query to the cleaned version
202
+ if (result.cleanedQuery !== query) {
203
+ setQuery(result.cleanedQuery, true);
204
+ }
205
+ }
206
+ return result;
207
+ }, [parse, applyFilters, setQuery]);
208
+ return {
209
+ parse,
210
+ applyFilters,
211
+ parseAndApply,
212
+ };
213
+ }
214
+ /**
215
+ * Utility to format parsed filters for display
216
+ */
217
+ export function formatParsedFilters(filters) {
218
+ return filters
219
+ .map(f => `${f.field}: ${f.value}`)
220
+ .join(', ');
221
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * useQuerySuggestions Hook
3
+ *
4
+ * Hook for fetching query suggestions with debouncing
5
+ */
6
+ import type { SeekoraClient } from '@seekora-ai/search-sdk';
7
+ import type { SuggestionItem } from '../types';
8
+ export interface UseQuerySuggestionsOptions {
9
+ client: SeekoraClient;
10
+ query: string;
11
+ enabled?: boolean;
12
+ debounceMs?: number;
13
+ maxSuggestions?: number;
14
+ }
15
+ export interface UseQuerySuggestionsReturn {
16
+ suggestions: SuggestionItem[];
17
+ loading: boolean;
18
+ error: Error | null;
19
+ }
20
+ export declare const useQuerySuggestions: ({ client, query, enabled, debounceMs, maxSuggestions, }: UseQuerySuggestionsOptions) => UseQuerySuggestionsReturn;
21
+ //# sourceMappingURL=useQuerySuggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/hooks/useQuerySuggestions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,mBAAmB,GAAI,yDAMjC,0BAA0B,KAAG,yBAqE/B,CAAC"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * useQuerySuggestions Hook
3
+ *
4
+ * Hook for fetching query suggestions with debouncing
5
+ */
6
+ import { useState, useEffect, useRef } from 'react';
7
+ import { log } from '@seekora-ai/ui-sdk-core';
8
+ export const useQuerySuggestions = ({ client, query, enabled = true, debounceMs = 300, maxSuggestions = 10, }) => {
9
+ const [suggestions, setSuggestions] = useState([]);
10
+ const [loading, setLoading] = useState(false);
11
+ const [error, setError] = useState(null);
12
+ const debounceTimerRef = useRef(null);
13
+ useEffect(() => {
14
+ // Clear previous timer
15
+ if (debounceTimerRef.current) {
16
+ clearTimeout(debounceTimerRef.current);
17
+ }
18
+ if (!enabled || !query.trim()) {
19
+ setSuggestions([]);
20
+ setLoading(false);
21
+ setError(null);
22
+ return;
23
+ }
24
+ setLoading(true);
25
+ setError(null);
26
+ debounceTimerRef.current = setTimeout(async () => {
27
+ try {
28
+ const response = await client.getSuggestions?.(query, maxSuggestions);
29
+ // Transform suggestions to SuggestionItem format
30
+ // getSuggestions returns an array of suggestion objects with structure:
31
+ // { query: string, popularity: number, objectID: string, ... }
32
+ const rawSuggestions = Array.isArray(response) ? response : [];
33
+ const suggestionItems = rawSuggestions.map((suggestion) => {
34
+ // Extract query - it should be in suggestion.query
35
+ const suggestionQuery = suggestion.query || suggestion.text || suggestion;
36
+ // Extract count/popularity
37
+ const count = suggestion.popularity !== undefined ? suggestion.popularity : (suggestion.count !== undefined ? suggestion.count : undefined);
38
+ const item = {
39
+ query: typeof suggestionQuery === 'string' ? suggestionQuery : String(suggestionQuery),
40
+ count: typeof count === 'number' ? count : undefined,
41
+ metadata: suggestion,
42
+ };
43
+ return item;
44
+ });
45
+ setSuggestions(suggestionItems);
46
+ }
47
+ catch (err) {
48
+ const error = err instanceof Error ? err : new Error(String(err));
49
+ log.error('Error in useQuerySuggestions:', error);
50
+ setError(error);
51
+ setSuggestions([]);
52
+ }
53
+ finally {
54
+ setLoading(false);
55
+ }
56
+ }, debounceMs);
57
+ return () => {
58
+ if (debounceTimerRef.current) {
59
+ clearTimeout(debounceTimerRef.current);
60
+ }
61
+ };
62
+ }, [client, query, enabled, debounceMs, maxSuggestions]);
63
+ return {
64
+ suggestions,
65
+ loading,
66
+ error,
67
+ };
68
+ };
@@ -0,0 +1,114 @@
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 type { SeekoraClient } from '@seekora-ai/search-sdk';
12
+ import type { SuggestionItem, ProductItem, FilteredTab, DropdownRecommendations, RecentSearch, QuerySuggestionsResponse, TrendingSearch, TopSearch, RelatedSearch, PopularBrand, SuggestionCategory } from '@seekora-ai/ui-sdk-types';
13
+ export interface UseQuerySuggestionsEnhancedOptions {
14
+ /** Seekora client instance */
15
+ client: SeekoraClient;
16
+ /** Current search query */
17
+ query: string;
18
+ /** Enable/disable the hook */
19
+ enabled?: boolean;
20
+ /** Debounce delay in ms */
21
+ debounceMs?: number;
22
+ /** Max suggestions to fetch */
23
+ maxSuggestions?: number;
24
+ /** Minimum query length to trigger search */
25
+ minQueryLength?: number;
26
+ /** Include dropdown recommendations (trending, products, etc.) */
27
+ includeDropdownRecommendations?: boolean;
28
+ /** Include categories in suggestions */
29
+ includeCategories?: boolean;
30
+ /** Include facets in suggestions */
31
+ includeFacets?: boolean;
32
+ /** Max categories per suggestion */
33
+ maxCategories?: number;
34
+ /** Max facets per suggestion */
35
+ maxFacets?: number;
36
+ /** Filtered tabs configuration */
37
+ filteredTabs?: Array<{
38
+ id?: string;
39
+ label: string;
40
+ filter: string;
41
+ }>;
42
+ /** Minimum popularity threshold */
43
+ minPopularity?: number;
44
+ /** Time range for analytics data */
45
+ timeRange?: '7d' | '30d' | '90d';
46
+ /** Disable typo tolerance */
47
+ disableTypoTolerance?: boolean;
48
+ /** Analytics tags */
49
+ analyticsTags?: string[];
50
+ /** Enable recent searches from localStorage */
51
+ enableRecentSearches?: boolean;
52
+ /** Max recent searches to store */
53
+ maxRecentSearches?: number;
54
+ /** Local storage key for recent searches */
55
+ recentSearchesKey?: string;
56
+ /** Callback when suggestions are loaded */
57
+ onSuggestionsLoaded?: (response: QuerySuggestionsResponse) => void;
58
+ /** Callback on error */
59
+ onError?: (error: Error) => void;
60
+ }
61
+ export interface UseQuerySuggestionsEnhancedReturn {
62
+ /** Basic suggestion items */
63
+ suggestions: SuggestionItem[];
64
+ /** Loading state */
65
+ loading: boolean;
66
+ /** Error state */
67
+ error: Error | null;
68
+ /** Dropdown recommendations */
69
+ dropdownRecommendations: DropdownRecommendations | null;
70
+ /** Trending searches */
71
+ trendingSearches: TrendingSearch[];
72
+ /** Top searches */
73
+ topSearches: TopSearch[];
74
+ /** Related searches */
75
+ relatedSearches: RelatedSearch[];
76
+ /** Popular brands */
77
+ popularBrands: PopularBrand[];
78
+ /** Filtered tabs with products */
79
+ filteredTabs: FilteredTab[];
80
+ /** Trending products */
81
+ trendingProducts: ProductItem[];
82
+ /** Recent searches (from localStorage) */
83
+ recentSearches: RecentSearch[];
84
+ /** Processing time in ms */
85
+ processingTimeMs: number | null;
86
+ /** Total hits count */
87
+ totalHits: number;
88
+ /** Current page */
89
+ currentPage: number;
90
+ /** Total pages */
91
+ totalPages: number;
92
+ /** Original query */
93
+ originalQuery: string;
94
+ /** Add a search to recent searches */
95
+ addRecentSearch: (query: string, resultsCount?: number) => void;
96
+ /** Remove a search from recent searches */
97
+ removeRecentSearch: (query: string) => void;
98
+ /** Clear all recent searches */
99
+ clearRecentSearches: () => void;
100
+ /** Manually refetch suggestions */
101
+ refetch: () => Promise<void>;
102
+ /** Check if dropdown has any content to show */
103
+ hasContent: boolean;
104
+ /** Get all items for keyboard navigation (flattened) */
105
+ getAllNavigableItems: () => NavigableItem[];
106
+ }
107
+ export interface NavigableItem {
108
+ type: 'suggestion' | 'recent' | 'trending' | 'product' | 'category' | 'brand' | 'tab';
109
+ index: number;
110
+ data: SuggestionItem | RecentSearch | TrendingSearch | ProductItem | SuggestionCategory | PopularBrand | FilteredTab;
111
+ }
112
+ export declare function useQuerySuggestionsEnhanced(options: UseQuerySuggestionsEnhancedOptions): UseQuerySuggestionsEnhancedReturn;
113
+ export default useQuerySuggestionsEnhanced;
114
+ //# sourceMappingURL=useQuerySuggestionsEnhanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useQuerySuggestionsEnhanced.d.ts","sourceRoot":"","sources":["../../src/hooks/useQuerySuggestionsEnhanced.ts"],"names":[],"mappings":"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"}