@seekora-ai/ui-sdk-react 0.0.0-stage-20260517092419

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 (357) 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 +81 -0
  7. package/dist/components/CurrentRefinements.d.ts +63 -0
  8. package/dist/components/CurrentRefinements.d.ts.map +1 -0
  9. package/dist/components/CurrentRefinements.js +302 -0
  10. package/dist/components/FacetDropdown.d.ts +94 -0
  11. package/dist/components/FacetDropdown.d.ts.map +1 -0
  12. package/dist/components/FacetDropdown.js +396 -0
  13. package/dist/components/Facets.d.ts +118 -0
  14. package/dist/components/Facets.d.ts.map +1 -0
  15. package/dist/components/Facets.js +785 -0
  16. package/dist/components/FederatedDropdown.d.ts +98 -0
  17. package/dist/components/FederatedDropdown.d.ts.map +1 -0
  18. package/dist/components/FederatedDropdown.js +526 -0
  19. package/dist/components/HierarchicalMenu.d.ts +55 -0
  20. package/dist/components/HierarchicalMenu.d.ts.map +1 -0
  21. package/dist/components/HierarchicalMenu.js +276 -0
  22. package/dist/components/Highlight.d.ts +51 -0
  23. package/dist/components/Highlight.d.ts.map +1 -0
  24. package/dist/components/Highlight.js +155 -0
  25. package/dist/components/HitsPerPage.d.ts +41 -0
  26. package/dist/components/HitsPerPage.d.ts.map +1 -0
  27. package/dist/components/HitsPerPage.js +82 -0
  28. package/dist/components/InfiniteHits.d.ts +51 -0
  29. package/dist/components/InfiniteHits.d.ts.map +1 -0
  30. package/dist/components/InfiniteHits.js +173 -0
  31. package/dist/components/MobileFilters.d.ts +71 -0
  32. package/dist/components/MobileFilters.d.ts.map +1 -0
  33. package/dist/components/MobileFilters.js +242 -0
  34. package/dist/components/Pagination.d.ts +90 -0
  35. package/dist/components/Pagination.d.ts.map +1 -0
  36. package/dist/components/Pagination.js +298 -0
  37. package/dist/components/QuerySuggestions.d.ts +36 -0
  38. package/dist/components/QuerySuggestions.d.ts.map +1 -0
  39. package/dist/components/QuerySuggestions.js +71 -0
  40. package/dist/components/QuerySuggestionsDropdown.d.ts +82 -0
  41. package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -0
  42. package/dist/components/QuerySuggestionsDropdown.js +394 -0
  43. package/dist/components/RangeInput.d.ts +58 -0
  44. package/dist/components/RangeInput.d.ts.map +1 -0
  45. package/dist/components/RangeInput.js +203 -0
  46. package/dist/components/RangeSlider.d.ts +51 -0
  47. package/dist/components/RangeSlider.d.ts.map +1 -0
  48. package/dist/components/RangeSlider.js +262 -0
  49. package/dist/components/Recommendations.d.ts +89 -0
  50. package/dist/components/Recommendations.d.ts.map +1 -0
  51. package/dist/components/Recommendations.js +256 -0
  52. package/dist/components/RichQuerySuggestions.d.ts +88 -0
  53. package/dist/components/RichQuerySuggestions.d.ts.map +1 -0
  54. package/dist/components/RichQuerySuggestions.js +498 -0
  55. package/dist/components/SearchBar.d.ts +57 -0
  56. package/dist/components/SearchBar.d.ts.map +1 -0
  57. package/dist/components/SearchBar.js +361 -0
  58. package/dist/components/SearchBarWithSuggestions.d.ts +105 -0
  59. package/dist/components/SearchBarWithSuggestions.d.ts.map +1 -0
  60. package/dist/components/SearchBarWithSuggestions.js +275 -0
  61. package/dist/components/SearchLayout.d.ts +35 -0
  62. package/dist/components/SearchLayout.d.ts.map +1 -0
  63. package/dist/components/SearchLayout.js +61 -0
  64. package/dist/components/SearchProvider.d.ts +35 -0
  65. package/dist/components/SearchProvider.d.ts.map +1 -0
  66. package/dist/components/SearchProvider.js +53 -0
  67. package/dist/components/SearchResults.d.ts +57 -0
  68. package/dist/components/SearchResults.d.ts.map +1 -0
  69. package/dist/components/SearchResults.js +456 -0
  70. package/dist/components/SortBy.d.ts +84 -0
  71. package/dist/components/SortBy.d.ts.map +1 -0
  72. package/dist/components/SortBy.js +183 -0
  73. package/dist/components/Stats.d.ts +51 -0
  74. package/dist/components/Stats.d.ts.map +1 -0
  75. package/dist/components/Stats.js +201 -0
  76. package/dist/components/primitives/ActionButtons.d.ts +27 -0
  77. package/dist/components/primitives/ActionButtons.d.ts.map +1 -0
  78. package/dist/components/primitives/ActionButtons.js +102 -0
  79. package/dist/components/primitives/AnalyticsProvider.d.ts +22 -0
  80. package/dist/components/primitives/AnalyticsProvider.d.ts.map +1 -0
  81. package/dist/components/primitives/AnalyticsProvider.js +87 -0
  82. package/dist/components/primitives/BadgeList.d.ts +14 -0
  83. package/dist/components/primitives/BadgeList.d.ts.map +1 -0
  84. package/dist/components/primitives/BadgeList.js +65 -0
  85. package/dist/components/primitives/CustomSelect.d.ts +40 -0
  86. package/dist/components/primitives/CustomSelect.d.ts.map +1 -0
  87. package/dist/components/primitives/CustomSelect.js +196 -0
  88. package/dist/components/primitives/ImageDisplay.d.ts +28 -0
  89. package/dist/components/primitives/ImageDisplay.d.ts.map +1 -0
  90. package/dist/components/primitives/ImageDisplay.js +127 -0
  91. package/dist/components/primitives/ImageZoom.d.ts +33 -0
  92. package/dist/components/primitives/ImageZoom.d.ts.map +1 -0
  93. package/dist/components/primitives/ImageZoom.js +433 -0
  94. package/dist/components/primitives/PriceDisplay.d.ts +21 -0
  95. package/dist/components/primitives/PriceDisplay.d.ts.map +1 -0
  96. package/dist/components/primitives/PriceDisplay.js +44 -0
  97. package/dist/components/primitives/RatingDisplay.d.ts +43 -0
  98. package/dist/components/primitives/RatingDisplay.d.ts.map +1 -0
  99. package/dist/components/primitives/RatingDisplay.js +114 -0
  100. package/dist/components/primitives/VariantSelector.d.ts +30 -0
  101. package/dist/components/primitives/VariantSelector.d.ts.map +1 -0
  102. package/dist/components/primitives/VariantSelector.js +155 -0
  103. package/dist/components/primitives/VariantSwatches.d.ts +28 -0
  104. package/dist/components/primitives/VariantSwatches.d.ts.map +1 -0
  105. package/dist/components/primitives/VariantSwatches.js +188 -0
  106. package/dist/components/primitives/index.d.ts +12 -0
  107. package/dist/components/primitives/index.d.ts.map +1 -0
  108. package/dist/components/primitives/index.js +11 -0
  109. package/dist/components/primitives/withAnalytics.d.ts +24 -0
  110. package/dist/components/primitives/withAnalytics.d.ts.map +1 -0
  111. package/dist/components/primitives/withAnalytics.js +73 -0
  112. package/dist/components/product-page/ProductGallery.d.ts +26 -0
  113. package/dist/components/product-page/ProductGallery.d.ts.map +1 -0
  114. package/dist/components/product-page/ProductGallery.js +13 -0
  115. package/dist/components/product-page/ProductInfo.d.ts +44 -0
  116. package/dist/components/product-page/ProductInfo.d.ts.map +1 -0
  117. package/dist/components/product-page/ProductInfo.js +34 -0
  118. package/dist/components/product-page/ProductRecommendations.d.ts +21 -0
  119. package/dist/components/product-page/ProductRecommendations.d.ts.map +1 -0
  120. package/dist/components/product-page/ProductRecommendations.js +17 -0
  121. package/dist/components/product-page/index.d.ts +4 -0
  122. package/dist/components/product-page/index.d.ts.map +1 -0
  123. package/dist/components/product-page/index.js +3 -0
  124. package/dist/components/section-primitives/SectionError.d.ts +11 -0
  125. package/dist/components/section-primitives/SectionError.d.ts.map +1 -0
  126. package/dist/components/section-primitives/SectionError.js +13 -0
  127. package/dist/components/section-primitives/SectionItemGrid.d.ts +18 -0
  128. package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -0
  129. package/dist/components/section-primitives/SectionItemGrid.js +14 -0
  130. package/dist/components/section-primitives/SectionLoading.d.ts +11 -0
  131. package/dist/components/section-primitives/SectionLoading.d.ts.map +1 -0
  132. package/dist/components/section-primitives/SectionLoading.js +11 -0
  133. package/dist/components/section-primitives/SectionSearchContext.d.ts +17 -0
  134. package/dist/components/section-primitives/SectionSearchContext.d.ts.map +1 -0
  135. package/dist/components/section-primitives/SectionSearchContext.js +17 -0
  136. package/dist/components/section-primitives/SectionSearchProvider.d.ts +25 -0
  137. package/dist/components/section-primitives/SectionSearchProvider.d.ts.map +1 -0
  138. package/dist/components/section-primitives/SectionSearchProvider.js +106 -0
  139. package/dist/components/section-primitives/index.d.ts +5 -0
  140. package/dist/components/section-primitives/index.d.ts.map +1 -0
  141. package/dist/components/section-primitives/index.js +4 -0
  142. package/dist/components/suggestions/AmazonDropdown.d.ts +30 -0
  143. package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -0
  144. package/dist/components/suggestions/AmazonDropdown.js +509 -0
  145. package/dist/components/suggestions/GoogleDropdown.d.ts +31 -0
  146. package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -0
  147. package/dist/components/suggestions/GoogleDropdown.js +349 -0
  148. package/dist/components/suggestions/MinimalDropdown.d.ts +24 -0
  149. package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -0
  150. package/dist/components/suggestions/MinimalDropdown.js +312 -0
  151. package/dist/components/suggestions/MobileSheetDropdown.d.ts +31 -0
  152. package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -0
  153. package/dist/components/suggestions/MobileSheetDropdown.js +483 -0
  154. package/dist/components/suggestions/PinterestDropdown.d.ts +29 -0
  155. package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -0
  156. package/dist/components/suggestions/PinterestDropdown.js +446 -0
  157. package/dist/components/suggestions/ShopifyDropdown.d.ts +27 -0
  158. package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -0
  159. package/dist/components/suggestions/ShopifyDropdown.js +448 -0
  160. package/dist/components/suggestions/SpotlightDropdown.d.ts +33 -0
  161. package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -0
  162. package/dist/components/suggestions/SpotlightDropdown.js +544 -0
  163. package/dist/components/suggestions/SuggestionSearchBar.d.ts +127 -0
  164. package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -0
  165. package/dist/components/suggestions/SuggestionSearchBar.js +644 -0
  166. package/dist/components/suggestions/index.d.ts +37 -0
  167. package/dist/components/suggestions/index.d.ts.map +1 -0
  168. package/dist/components/suggestions/index.js +59 -0
  169. package/dist/components/suggestions/styles/index.d.ts +11 -0
  170. package/dist/components/suggestions/styles/index.d.ts.map +1 -0
  171. package/dist/components/suggestions/styles/index.js +289 -0
  172. package/dist/components/suggestions/styles/responsive.d.ts +107 -0
  173. package/dist/components/suggestions/styles/responsive.d.ts.map +1 -0
  174. package/dist/components/suggestions/styles/responsive.js +237 -0
  175. package/dist/components/suggestions/types.d.ts +511 -0
  176. package/dist/components/suggestions/types.d.ts.map +1 -0
  177. package/dist/components/suggestions/types.js +6 -0
  178. package/dist/components/suggestions/utils.d.ts +259 -0
  179. package/dist/components/suggestions/utils.d.ts.map +1 -0
  180. package/dist/components/suggestions/utils.js +668 -0
  181. package/dist/components/suggestions-primitives/CategoriesTabs.d.ts +13 -0
  182. package/dist/components/suggestions-primitives/CategoriesTabs.d.ts.map +1 -0
  183. package/dist/components/suggestions-primitives/CategoriesTabs.js +35 -0
  184. package/dist/components/suggestions-primitives/DropdownPanel.d.ts +24 -0
  185. package/dist/components/suggestions-primitives/DropdownPanel.d.ts.map +1 -0
  186. package/dist/components/suggestions-primitives/DropdownPanel.js +67 -0
  187. package/dist/components/suggestions-primitives/ItemCard.d.ts +48 -0
  188. package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -0
  189. package/dist/components/suggestions-primitives/ItemCard.js +103 -0
  190. package/dist/components/suggestions-primitives/ItemGrid.d.ts +28 -0
  191. package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -0
  192. package/dist/components/suggestions-primitives/ItemGrid.js +55 -0
  193. package/dist/components/suggestions-primitives/ProductCard.d.ts +45 -0
  194. package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -0
  195. package/dist/components/suggestions-primitives/ProductCard.js +177 -0
  196. package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts +44 -0
  197. package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts.map +1 -0
  198. package/dist/components/suggestions-primitives/ProductCardLayouts.js +137 -0
  199. package/dist/components/suggestions-primitives/ProductGrid.d.ts +22 -0
  200. package/dist/components/suggestions-primitives/ProductGrid.d.ts.map +1 -0
  201. package/dist/components/suggestions-primitives/ProductGrid.js +41 -0
  202. package/dist/components/suggestions-primitives/RecentSearchesList.d.ts +17 -0
  203. package/dist/components/suggestions-primitives/RecentSearchesList.d.ts.map +1 -0
  204. package/dist/components/suggestions-primitives/RecentSearchesList.js +46 -0
  205. package/dist/components/suggestions-primitives/SearchInput.d.ts +23 -0
  206. package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -0
  207. package/dist/components/suggestions-primitives/SearchInput.js +114 -0
  208. package/dist/components/suggestions-primitives/SuggestionItem.d.ts +31 -0
  209. package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -0
  210. package/dist/components/suggestions-primitives/SuggestionItem.js +47 -0
  211. package/dist/components/suggestions-primitives/SuggestionList.d.ts +26 -0
  212. package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -0
  213. package/dist/components/suggestions-primitives/SuggestionList.js +35 -0
  214. package/dist/components/suggestions-primitives/SuggestionsContext.d.ts +44 -0
  215. package/dist/components/suggestions-primitives/SuggestionsContext.d.ts.map +1 -0
  216. package/dist/components/suggestions-primitives/SuggestionsContext.js +18 -0
  217. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts +24 -0
  218. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts.map +1 -0
  219. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.js +30 -0
  220. package/dist/components/suggestions-primitives/SuggestionsError.d.ts +11 -0
  221. package/dist/components/suggestions-primitives/SuggestionsError.d.ts.map +1 -0
  222. package/dist/components/suggestions-primitives/SuggestionsError.js +19 -0
  223. package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts +11 -0
  224. package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts.map +1 -0
  225. package/dist/components/suggestions-primitives/SuggestionsLoading.js +17 -0
  226. package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts +38 -0
  227. package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts.map +1 -0
  228. package/dist/components/suggestions-primitives/SuggestionsProvider.js +259 -0
  229. package/dist/components/suggestions-primitives/TrendingList.d.ts +17 -0
  230. package/dist/components/suggestions-primitives/TrendingList.d.ts.map +1 -0
  231. package/dist/components/suggestions-primitives/TrendingList.js +48 -0
  232. package/dist/components/suggestions-primitives/highlightMarkup.d.ts +31 -0
  233. package/dist/components/suggestions-primitives/highlightMarkup.d.ts.map +1 -0
  234. package/dist/components/suggestions-primitives/highlightMarkup.js +70 -0
  235. package/dist/components/suggestions-primitives/index.d.ts +39 -0
  236. package/dist/components/suggestions-primitives/index.d.ts.map +1 -0
  237. package/dist/components/suggestions-primitives/index.js +24 -0
  238. package/dist/docsearch/components/DocSearch.d.ts +4 -0
  239. package/dist/docsearch/components/DocSearch.d.ts.map +1 -0
  240. package/dist/docsearch/components/DocSearch.js +93 -0
  241. package/dist/docsearch/components/DocSearchButton.d.ts +4 -0
  242. package/dist/docsearch/components/DocSearchButton.d.ts.map +1 -0
  243. package/dist/docsearch/components/DocSearchButton.js +12 -0
  244. package/dist/docsearch/components/Footer.d.ts +8 -0
  245. package/dist/docsearch/components/Footer.d.ts.map +1 -0
  246. package/dist/docsearch/components/Footer.js +40 -0
  247. package/dist/docsearch/components/Highlight.d.ts +9 -0
  248. package/dist/docsearch/components/Highlight.d.ts.map +1 -0
  249. package/dist/docsearch/components/Highlight.js +48 -0
  250. package/dist/docsearch/components/Hit.d.ts +15 -0
  251. package/dist/docsearch/components/Hit.d.ts.map +1 -0
  252. package/dist/docsearch/components/Hit.js +96 -0
  253. package/dist/docsearch/components/Modal.d.ts +10 -0
  254. package/dist/docsearch/components/Modal.d.ts.map +1 -0
  255. package/dist/docsearch/components/Modal.js +57 -0
  256. package/dist/docsearch/components/Results.d.ts +23 -0
  257. package/dist/docsearch/components/Results.d.ts.map +1 -0
  258. package/dist/docsearch/components/Results.js +141 -0
  259. package/dist/docsearch/components/SearchBox.d.ts +11 -0
  260. package/dist/docsearch/components/SearchBox.d.ts.map +1 -0
  261. package/dist/docsearch/components/SearchBox.js +16 -0
  262. package/dist/docsearch/hooks/useDocSearch.d.ts +33 -0
  263. package/dist/docsearch/hooks/useDocSearch.d.ts.map +1 -0
  264. package/dist/docsearch/hooks/useDocSearch.js +224 -0
  265. package/dist/docsearch/hooks/useKeyboard.d.ts +17 -0
  266. package/dist/docsearch/hooks/useKeyboard.d.ts.map +1 -0
  267. package/dist/docsearch/hooks/useKeyboard.js +71 -0
  268. package/dist/docsearch/hooks/useSeekoraSearch.d.ts +27 -0
  269. package/dist/docsearch/hooks/useSeekoraSearch.d.ts.map +1 -0
  270. package/dist/docsearch/hooks/useSeekoraSearch.js +213 -0
  271. package/dist/docsearch/index.d.ts +13 -0
  272. package/dist/docsearch/index.d.ts.map +1 -0
  273. package/dist/docsearch/index.js +11 -0
  274. package/dist/docsearch/types.d.ts +175 -0
  275. package/dist/docsearch/types.d.ts.map +1 -0
  276. package/dist/docsearch/types.js +4 -0
  277. package/dist/docsearch.css +234 -0
  278. package/dist/hooks/useAnalytics.d.ts +24 -0
  279. package/dist/hooks/useAnalytics.d.ts.map +1 -0
  280. package/dist/hooks/useAnalytics.js +67 -0
  281. package/dist/hooks/useClickTracking.d.ts +36 -0
  282. package/dist/hooks/useClickTracking.d.ts.map +1 -0
  283. package/dist/hooks/useClickTracking.js +89 -0
  284. package/dist/hooks/useExperiment.d.ts +25 -0
  285. package/dist/hooks/useExperiment.d.ts.map +1 -0
  286. package/dist/hooks/useExperiment.js +123 -0
  287. package/dist/hooks/useFilters.d.ts +27 -0
  288. package/dist/hooks/useFilters.d.ts.map +1 -0
  289. package/dist/hooks/useFilters.js +86 -0
  290. package/dist/hooks/useKeyboardNavigation.d.ts +51 -0
  291. package/dist/hooks/useKeyboardNavigation.d.ts.map +1 -0
  292. package/dist/hooks/useKeyboardNavigation.js +113 -0
  293. package/dist/hooks/useNaturalLanguageFilters.d.ts +48 -0
  294. package/dist/hooks/useNaturalLanguageFilters.d.ts.map +1 -0
  295. package/dist/hooks/useNaturalLanguageFilters.js +221 -0
  296. package/dist/hooks/useProductAnalytics.d.ts +49 -0
  297. package/dist/hooks/useProductAnalytics.d.ts.map +1 -0
  298. package/dist/hooks/useProductAnalytics.js +116 -0
  299. package/dist/hooks/useQuerySuggestions.d.ts +21 -0
  300. package/dist/hooks/useQuerySuggestions.d.ts.map +1 -0
  301. package/dist/hooks/useQuerySuggestions.js +84 -0
  302. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts +120 -0
  303. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -0
  304. package/dist/hooks/useQuerySuggestionsEnhanced.js +444 -0
  305. package/dist/hooks/useSearchState.d.ts +35 -0
  306. package/dist/hooks/useSearchState.d.ts.map +1 -0
  307. package/dist/hooks/useSearchState.js +68 -0
  308. package/dist/hooks/useSeekoraSearch.d.ts +20 -0
  309. package/dist/hooks/useSeekoraSearch.d.ts.map +1 -0
  310. package/dist/hooks/useSeekoraSearch.js +63 -0
  311. package/dist/hooks/useSmartSuggestions.d.ts +55 -0
  312. package/dist/hooks/useSmartSuggestions.d.ts.map +1 -0
  313. package/dist/hooks/useSmartSuggestions.js +236 -0
  314. package/dist/hooks/useSuggestionsAnalytics.d.ts +93 -0
  315. package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -0
  316. package/dist/hooks/useSuggestionsAnalytics.js +239 -0
  317. package/dist/hooks/useVariantSelection.d.ts +28 -0
  318. package/dist/hooks/useVariantSelection.d.ts.map +1 -0
  319. package/dist/hooks/useVariantSelection.js +44 -0
  320. package/dist/index.d.ts +105 -0
  321. package/dist/index.d.ts.map +1 -0
  322. package/dist/index.js +110 -0
  323. package/dist/index.umd.js +1 -0
  324. package/dist/src/index.d.ts +4469 -0
  325. package/dist/src/index.esm.js +18952 -0
  326. package/dist/src/index.esm.js.map +1 -0
  327. package/dist/src/index.js +19086 -0
  328. package/dist/src/index.js.map +1 -0
  329. package/dist/themes/createTheme.d.ts +8 -0
  330. package/dist/themes/createTheme.d.ts.map +1 -0
  331. package/dist/themes/createTheme.js +10 -0
  332. package/dist/themes/dark.d.ts +6 -0
  333. package/dist/themes/dark.d.ts.map +1 -0
  334. package/dist/themes/dark.js +34 -0
  335. package/dist/themes/default.d.ts +6 -0
  336. package/dist/themes/default.d.ts.map +1 -0
  337. package/dist/themes/default.js +71 -0
  338. package/dist/themes/mergeThemes.d.ts +7 -0
  339. package/dist/themes/mergeThemes.d.ts.map +1 -0
  340. package/dist/themes/mergeThemes.js +6 -0
  341. package/dist/themes/minimal.d.ts +6 -0
  342. package/dist/themes/minimal.d.ts.map +1 -0
  343. package/dist/themes/minimal.js +34 -0
  344. package/dist/themes/suggestions.d.ts +216 -0
  345. package/dist/themes/suggestions.d.ts.map +1 -0
  346. package/dist/themes/suggestions.js +546 -0
  347. package/dist/themes/types.d.ts +7 -0
  348. package/dist/themes/types.d.ts.map +1 -0
  349. package/dist/themes/types.js +6 -0
  350. package/dist/types/index.d.ts +33 -0
  351. package/dist/types/index.d.ts.map +1 -0
  352. package/dist/types/index.js +4 -0
  353. package/dist/utils/responsive.d.ts +130 -0
  354. package/dist/utils/responsive.d.ts.map +1 -0
  355. package/dist/utils/responsive.js +225 -0
  356. package/package.json +68 -0
  357. package/src/docsearch/docsearch.css +234 -0
@@ -0,0 +1,785 @@
1
+ /**
2
+ * Facets Component
3
+ *
4
+ * Displays facet filters for search results with multiple display variants,
5
+ * client-side search, count badges, and color swatch support.
6
+ */
7
+ import React, { useState, useMemo, useRef, useEffect } from 'react';
8
+ import { useSearchContext } from './SearchProvider';
9
+ import { useSearchState } from '../hooks/useSearchState';
10
+ import { useFilters } from '../hooks/useFilters';
11
+ import { log } from '@seekora-ai/ui-sdk-core';
12
+ import { clsx } from 'clsx';
13
+ import { RangeSlider } from './RangeSlider';
14
+ // ---------------------------------------------------------------------------
15
+ // Helpers
16
+ // ---------------------------------------------------------------------------
17
+ /** Generate a deterministic colour from a string (used as fallback for color-swatch). */
18
+ function stringToColor(str) {
19
+ let hash = 0;
20
+ for (let i = 0; i < str.length; i++) {
21
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
22
+ hash |= 0; // Convert to 32-bit int
23
+ }
24
+ const h = Math.abs(hash) % 360;
25
+ return `hsl(${h}, 65%, 55%)`;
26
+ }
27
+ /** Return swatch pixel size from the size prop. */
28
+ function swatchSize(size) {
29
+ switch (size) {
30
+ case 'small':
31
+ return 24;
32
+ case 'large':
33
+ return 40;
34
+ case 'medium':
35
+ default:
36
+ return 32;
37
+ }
38
+ }
39
+ // ---------------------------------------------------------------------------
40
+ // Chevron SVG icon for collapsible variant
41
+ // ---------------------------------------------------------------------------
42
+ const ChevronIcon = ({ expanded, color = 'currentColor', size = 16, }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", style: {
43
+ transform: expanded ? 'rotate(180deg)' : 'rotate(0deg)',
44
+ transition: 'transform 200ms ease',
45
+ flexShrink: 0,
46
+ }, "aria-hidden": "true" },
47
+ React.createElement("path", { d: "M4 6L8 10L12 6", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })));
48
+ // ---------------------------------------------------------------------------
49
+ // Checkmark SVG for selected color swatches
50
+ // ---------------------------------------------------------------------------
51
+ const CheckmarkIcon = ({ size = 16 }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true" },
52
+ React.createElement("path", { d: "M3.5 8.5L6.5 11.5L12.5 4.5", stroke: "#fff", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
53
+ // ---------------------------------------------------------------------------
54
+ // CSS variable defaults
55
+ // ---------------------------------------------------------------------------
56
+ const CSS_VAR_DEFAULTS = {
57
+ '--seekora-facet-bg': 'transparent',
58
+ '--seekora-facet-border': '#dee2e6',
59
+ '--seekora-facet-active-bg': 'rgba(0, 0, 0, 0.05)',
60
+ '--seekora-facet-swatch-size': '32px',
61
+ '--seekora-facet-count-bg': '#e9ecef',
62
+ '--seekora-facet-count-color': '#495057',
63
+ '--seekora-primary': '#3b82f6',
64
+ '--seekora-primary-text': '#ffffff',
65
+ };
66
+ // ---------------------------------------------------------------------------
67
+ // Component
68
+ // ---------------------------------------------------------------------------
69
+ export const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, renderFacet, renderFacetItem, maxItems = 10, showMore = true, className, style, theme: customTheme, variant = 'checkbox', searchable = false, showCounts = true, colorMap, defaultCollapsed = false, size = 'medium', facetRanges, useFiltersApi = false, disjunctiveFacets, hideEmptyFacets = true, defaultCollapsedFields, onFacetsAvailable, }) => {
70
+ const { theme } = useSearchContext();
71
+ const { results: stateResults, refinements, addRefinement, removeRefinement } = useSearchState();
72
+ const facetsTheme = customTheme || {};
73
+ // Use dedicated Filters API when useFiltersApi is enabled
74
+ const { filters: filtersApiData, searchFacetValues } = useFilters(useFiltersApi ? { disjunctiveFacets } : { autoFetch: false });
75
+ // expandedFacets is used for "Show more/less" in checkbox/color-swatch variants
76
+ // AND for collapse/expand in collapsible variant.
77
+ const [expandedFacets, setExpandedFacets] = useState({});
78
+ const [searchTerms, setSearchTerms] = useState({});
79
+ // Use results from prop if provided, otherwise from state manager
80
+ const results = resultsProp || stateResults;
81
+ // -------------------------------------------------------------------
82
+ // Extract facets from results (or Filters API)
83
+ // -------------------------------------------------------------------
84
+ const extractFacets = () => {
85
+ if (facetsProp)
86
+ return facetsProp;
87
+ // When using Filters API, convert FilterField[] to Facet[]
88
+ if (useFiltersApi && filtersApiData.length > 0) {
89
+ log.verbose('Facets: Using Filters API data', { filterCount: filtersApiData.length });
90
+ return filtersApiData.map((filter) => ({
91
+ field: filter.field || '',
92
+ label: filter.field || '',
93
+ items: (filter.values || []).map((v) => ({
94
+ value: v.value || '',
95
+ count: v.count || 0,
96
+ selected: refinements.some(r => r.field === filter.field && r.value === v.value),
97
+ })),
98
+ stats: filter.stats?.min != null && filter.stats?.max != null
99
+ ? { min: filter.stats.min, max: filter.stats.max, avg: filter.stats.avg, sum: filter.stats.sum }
100
+ : undefined,
101
+ }));
102
+ }
103
+ // Try to get facets from various locations in the response
104
+ // Primary location: data.facets (widget_mode response structure)
105
+ const rawFacets = results?.data?.facets
106
+ || results?.facets
107
+ || results?.data?.data?.facets
108
+ || null;
109
+ log.verbose('Facets: Extracting facets', {
110
+ hasResults: !!results,
111
+ hasData: !!results?.data,
112
+ rawFacets: rawFacets ? (Array.isArray(rawFacets) ? rawFacets.length : 'not array') : null,
113
+ resultsKeys: results ? Object.keys(results) : [],
114
+ dataKeys: results?.data ? Object.keys(results.data) : [],
115
+ sampleFacet: rawFacets && Array.isArray(rawFacets) && rawFacets.length > 0 ? rawFacets[0] : null,
116
+ });
117
+ // Ensure rawFacets is an array before mapping
118
+ if (!rawFacets || !Array.isArray(rawFacets)) {
119
+ log.verbose('Facets: No facets found in response', {
120
+ rawFacetsType: rawFacets ? typeof rawFacets : 'null',
121
+ isArray: Array.isArray(rawFacets),
122
+ resultsStructure: results ? JSON.stringify(Object.keys(results)) : 'null',
123
+ dataStructure: results?.data ? JSON.stringify(Object.keys(results.data)) : 'null',
124
+ });
125
+ return [];
126
+ }
127
+ const extracted = rawFacets.map((facet) => {
128
+ const fieldName = facet.field_name || facet.field;
129
+ return {
130
+ field: fieldName,
131
+ label: facet.label || fieldName,
132
+ items: Array.isArray(facet.counts) ? facet.counts.map((count) => ({
133
+ value: count.value,
134
+ count: count.count,
135
+ selected: refinements.some(r => r.field === fieldName && r.value === count.value),
136
+ })) : [],
137
+ stats: facet.stats || undefined,
138
+ };
139
+ });
140
+ log.verbose('Facets: Extracted facets', {
141
+ count: extracted.length,
142
+ facets: extracted.map(f => ({ field: f.field, itemsCount: f.items.length })),
143
+ });
144
+ return extracted;
145
+ };
146
+ const rawFacetList = extractFacets();
147
+ const hasStats = (stats) => stats != null && (stats.min != null || stats.max != null);
148
+ const facets = hideEmptyFacets
149
+ ? rawFacetList.filter(f => f.items.length > 0 || hasStats(f.stats))
150
+ : rawFacetList;
151
+ // Notify parent about facet availability
152
+ const facetCount = facets.length;
153
+ const prevFacetAvailableRef = useRef(null);
154
+ useEffect(() => {
155
+ if (!onFacetsAvailable)
156
+ return;
157
+ const available = facetCount > 0;
158
+ if (prevFacetAvailableRef.current !== available) {
159
+ prevFacetAvailableRef.current = available;
160
+ onFacetsAvailable(available);
161
+ }
162
+ }, [facetCount, onFacetsAvailable]);
163
+ // -------------------------------------------------------------------
164
+ // Handlers
165
+ // -------------------------------------------------------------------
166
+ const handleFacetToggle = (field, value, selected) => {
167
+ const newSelected = !selected;
168
+ log.verbose('Facets: Facet toggled', { field, value, selected: newSelected });
169
+ // Update state manager (automatically triggers search)
170
+ if (newSelected) {
171
+ addRefinement(field, value);
172
+ }
173
+ else {
174
+ removeRefinement(field, value);
175
+ }
176
+ // Call callback for backwards compatibility
177
+ if (onFacetChange) {
178
+ try {
179
+ onFacetChange(field, value, newSelected);
180
+ }
181
+ catch (err) {
182
+ const error = err instanceof Error ? err : new Error(String(err));
183
+ log.error('Facets: Error in onFacetChange callback', {
184
+ field,
185
+ value,
186
+ selected: newSelected,
187
+ error: error.message,
188
+ });
189
+ }
190
+ }
191
+ };
192
+ const toggleFacetExpansion = (field) => {
193
+ setExpandedFacets((prev) => ({
194
+ ...prev,
195
+ [field]: !prev[field],
196
+ }));
197
+ };
198
+ /** For collapsible variant — determine if a facet group is open. */
199
+ const isFieldDefaultCollapsed = (field) => {
200
+ if (defaultCollapsedFields?.includes(field))
201
+ return true;
202
+ return defaultCollapsed;
203
+ };
204
+ const isFacetGroupOpen = (field) => {
205
+ if (field in expandedFacets) {
206
+ return expandedFacets[field];
207
+ }
208
+ return !isFieldDefaultCollapsed(field);
209
+ };
210
+ const toggleCollapsible = (field) => {
211
+ setExpandedFacets((prev) => ({
212
+ ...prev,
213
+ [field]: !(prev[field] ?? !isFieldDefaultCollapsed(field)),
214
+ }));
215
+ };
216
+ const getSearchTerm = (field) => searchTerms[field] || '';
217
+ const setSearchTerm = (field, term) => {
218
+ setSearchTerms((prev) => ({ ...prev, [field]: term }));
219
+ };
220
+ /** Filter facet items by search term. */
221
+ const filterItems = (items, field) => {
222
+ if (!searchable)
223
+ return items;
224
+ const term = getSearchTerm(field).toLowerCase();
225
+ if (!term)
226
+ return items;
227
+ return items.filter((item) => item.value.toLowerCase().includes(term));
228
+ };
229
+ // -------------------------------------------------------------------
230
+ // Size helpers
231
+ // -------------------------------------------------------------------
232
+ const sizeScale = useMemo(() => {
233
+ switch (size) {
234
+ case 'small':
235
+ return { font: theme.typography.fontSize.small, padding: '0.5rem', gap: '0.5rem' };
236
+ case 'large':
237
+ return { font: theme.typography.fontSize.large, padding: '0.75rem', gap: '0.75rem' };
238
+ case 'medium':
239
+ default:
240
+ return { font: theme.typography.fontSize.medium, padding: theme.spacing.small, gap: theme.spacing.small };
241
+ }
242
+ }, [size, theme]);
243
+ // -------------------------------------------------------------------
244
+ // Count badge renderer
245
+ // -------------------------------------------------------------------
246
+ const renderCountBadge = (count) => {
247
+ if (!showCounts)
248
+ return null;
249
+ return (React.createElement("span", { className: clsx(facetsTheme.countBadge), style: {
250
+ display: 'inline-flex',
251
+ alignItems: 'center',
252
+ justifyContent: 'center',
253
+ minWidth: '1.5em',
254
+ padding: '0.1em 0.5em',
255
+ marginLeft: sizeScale.gap,
256
+ fontSize: theme.typography.fontSize.small,
257
+ fontWeight: theme.typography.fontWeight?.medium ?? 500,
258
+ lineHeight: 1,
259
+ color: 'var(--seekora-facet-count-color, #495057)',
260
+ backgroundColor: 'var(--seekora-facet-count-bg, #e9ecef)',
261
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.full,
262
+ flexShrink: 0,
263
+ } }, count));
264
+ };
265
+ // -------------------------------------------------------------------
266
+ // Search input renderer
267
+ // -------------------------------------------------------------------
268
+ const renderSearchInput = (facet) => {
269
+ if (!searchable)
270
+ return null;
271
+ return (React.createElement("input", { type: "text", value: getSearchTerm(facet.field), onChange: (e) => setSearchTerm(facet.field, e.target.value), placeholder: `Search ${facet.label || facet.field}...`, className: clsx(facetsTheme.searchInput), "aria-label": `Search within ${facet.label || facet.field}`, style: {
272
+ width: '100%',
273
+ boxSizing: 'border-box',
274
+ padding: sizeScale.padding,
275
+ marginBottom: sizeScale.gap,
276
+ fontSize: theme.typography.fontSize.small,
277
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
278
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.small,
279
+ outline: 'none',
280
+ color: theme.colors.text,
281
+ backgroundColor: 'var(--seekora-facet-bg, transparent)',
282
+ } }));
283
+ };
284
+ // -------------------------------------------------------------------
285
+ // Checkbox variant item renderer (original behaviour, preserved)
286
+ // -------------------------------------------------------------------
287
+ const defaultRenderFacetItem = (item, facet, index) => {
288
+ const isExpanded = expandedFacets[facet.field] || index < maxItems;
289
+ if (!isExpanded && index >= maxItems) {
290
+ return null;
291
+ }
292
+ const isChecked = refinements.some(r => r.field === facet.field && r.value === item.value) || item.selected || false;
293
+ return (React.createElement("div", { key: `${facet.field}-${item.value}`, className: clsx(facetsTheme.facetItem, isChecked && facetsTheme.facetItemActive), role: "option", "aria-selected": isChecked, "aria-checked": isChecked, tabIndex: -1, onClick: () => handleFacetToggle(facet.field, item.value, item.selected || false), style: {
294
+ display: 'flex',
295
+ alignItems: 'center',
296
+ padding: sizeScale.padding,
297
+ cursor: 'pointer',
298
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
299
+ marginBottom: sizeScale.gap,
300
+ backgroundColor: isChecked
301
+ ? 'var(--seekora-facet-active-bg, ' + theme.colors.hover + ')'
302
+ : 'transparent',
303
+ transition: 'background-color 0.2s ease',
304
+ boxSizing: 'border-box',
305
+ } },
306
+ React.createElement("input", { type: "checkbox", checked: refinements.some(r => r.field === facet.field && r.value === item.value) || item.selected || false, onChange: () => handleFacetToggle(facet.field, item.value, item.selected || false), className: facetsTheme.checkbox, style: {
307
+ marginRight: sizeScale.gap,
308
+ cursor: 'pointer',
309
+ }, "aria-label": `Filter by ${item.value}` }),
310
+ React.createElement("span", { className: facetsTheme.facetItemLabel, style: {
311
+ flex: 1,
312
+ fontSize: sizeScale.font,
313
+ lineHeight: 1.5,
314
+ color: theme.colors.text,
315
+ } }, item.value),
316
+ renderCountBadge(item.count)));
317
+ };
318
+ // -------------------------------------------------------------------
319
+ // Color swatch variant item renderer
320
+ // -------------------------------------------------------------------
321
+ const renderColorSwatchItem = (item, facet, index) => {
322
+ const isExpanded = expandedFacets[facet.field] || index < maxItems;
323
+ if (!isExpanded && index >= maxItems) {
324
+ return null;
325
+ }
326
+ const isChecked = refinements.some(r => r.field === facet.field && r.value === item.value) || item.selected || false;
327
+ const color = colorMap?.[item.value] ?? stringToColor(item.value);
328
+ const pxSize = swatchSize(size);
329
+ return (React.createElement("div", { key: `${facet.field}-${item.value}`, className: clsx(facetsTheme.facetItem, isChecked && facetsTheme.facetItemActive), role: "option", "aria-selected": isChecked, "aria-checked": isChecked, tabIndex: -1, onClick: () => handleFacetToggle(facet.field, item.value, item.selected || false), title: `${item.value}${showCounts ? ` (${item.count})` : ''}`, style: {
330
+ display: 'inline-flex',
331
+ flexDirection: 'column',
332
+ alignItems: 'center',
333
+ cursor: 'pointer',
334
+ margin: sizeScale.gap,
335
+ } },
336
+ React.createElement("div", { className: clsx(facetsTheme.colorSwatch, isChecked && facetsTheme.colorSwatchSelected), style: {
337
+ width: `var(--seekora-facet-swatch-size, ${pxSize}px)`,
338
+ height: `var(--seekora-facet-swatch-size, ${pxSize}px)`,
339
+ borderRadius: '50%',
340
+ backgroundColor: color,
341
+ border: isChecked
342
+ ? `3px solid var(--seekora-primary, ${theme.colors.primary})`
343
+ : `2px solid var(--seekora-facet-border, ${theme.colors.border})`,
344
+ display: 'flex',
345
+ alignItems: 'center',
346
+ justifyContent: 'center',
347
+ transition: 'border 0.2s ease, box-shadow 0.2s ease',
348
+ boxShadow: isChecked ? `0 0 0 2px var(--seekora-primary-alpha, ${theme.colors.primary}33)` : 'none',
349
+ position: 'relative',
350
+ } }, isChecked && (React.createElement("span", { className: clsx(facetsTheme.colorSwatchInner), style: {
351
+ display: 'flex',
352
+ alignItems: 'center',
353
+ justifyContent: 'center',
354
+ } },
355
+ React.createElement(CheckmarkIcon, { size: Math.round(pxSize * 0.5) })))),
356
+ React.createElement("span", { className: facetsTheme.facetItemLabel, style: {
357
+ fontSize: theme.typography.fontSize.small,
358
+ color: theme.colors.text,
359
+ marginTop: '0.25rem',
360
+ textAlign: 'center',
361
+ maxWidth: `${pxSize + 16}px`,
362
+ overflow: 'hidden',
363
+ textOverflow: 'ellipsis',
364
+ whiteSpace: 'nowrap',
365
+ } }, item.value),
366
+ showCounts && (React.createElement("span", { className: clsx(facetsTheme.countBadge), style: {
367
+ fontSize: theme.typography.fontSize.small,
368
+ color: 'var(--seekora-facet-count-color, ' + (theme.colors.textSecondary || theme.colors.text) + ')',
369
+ lineHeight: 1,
370
+ marginTop: '0.125rem',
371
+ } }, item.count))));
372
+ };
373
+ // -------------------------------------------------------------------
374
+ // Item renderer dispatcher
375
+ // -------------------------------------------------------------------
376
+ const renderItem = (item, facet, index) => {
377
+ if (renderFacetItem) {
378
+ return renderFacetItem(item, facet, index);
379
+ }
380
+ switch (variant) {
381
+ case 'color-swatch':
382
+ return renderColorSwatchItem(item, facet, index);
383
+ case 'collapsible':
384
+ case 'checkbox':
385
+ default:
386
+ return defaultRenderFacetItem(item, facet, index);
387
+ }
388
+ };
389
+ // -------------------------------------------------------------------
390
+ // Keyboard handler (shared across variants)
391
+ // -------------------------------------------------------------------
392
+ const handleListKeyDown = (e, visibleItems, facet) => {
393
+ const currentEl = e.currentTarget.querySelector('[aria-selected="true"]');
394
+ const allItems = Array.from(e.currentTarget.querySelectorAll('[role="option"]'));
395
+ const currentIdx = currentEl ? allItems.indexOf(currentEl) : -1;
396
+ if (e.key === 'ArrowDown') {
397
+ e.preventDefault();
398
+ const next = Math.min(currentIdx + 1, allItems.length - 1);
399
+ allItems[next]?.focus();
400
+ }
401
+ else if (e.key === 'ArrowUp') {
402
+ e.preventDefault();
403
+ const prev = Math.max(currentIdx - 1, 0);
404
+ allItems[prev]?.focus();
405
+ }
406
+ else if (e.key === 'Enter' || e.key === ' ') {
407
+ e.preventDefault();
408
+ if (currentIdx >= 0 && currentIdx < visibleItems.length) {
409
+ handleFacetToggle(facet.field, visibleItems[currentIdx].value, visibleItems[currentIdx].selected || false);
410
+ }
411
+ }
412
+ };
413
+ // -------------------------------------------------------------------
414
+ // Show more / less buttons (shared)
415
+ // -------------------------------------------------------------------
416
+ const renderShowMoreLess = (facet, filteredItems) => {
417
+ const isExpanded = expandedFacets[facet.field] || false;
418
+ const hasMore = filteredItems.length > maxItems;
419
+ return (React.createElement(React.Fragment, null,
420
+ showMore && hasMore && !isExpanded && (React.createElement("button", { type: "button", onClick: () => toggleFacetExpansion(facet.field), style: {
421
+ marginTop: sizeScale.gap,
422
+ padding: sizeScale.padding,
423
+ border: 'none',
424
+ backgroundColor: 'transparent',
425
+ color: theme.colors.primary,
426
+ cursor: 'pointer',
427
+ fontSize: theme.typography.fontSize.small,
428
+ textDecoration: 'underline',
429
+ } },
430
+ "Show more (",
431
+ filteredItems.length - maxItems,
432
+ " more)")),
433
+ isExpanded && hasMore && (React.createElement("button", { type: "button", onClick: () => toggleFacetExpansion(facet.field), style: {
434
+ marginTop: sizeScale.gap,
435
+ padding: sizeScale.padding,
436
+ border: 'none',
437
+ backgroundColor: 'transparent',
438
+ color: theme.colors.primary,
439
+ cursor: 'pointer',
440
+ fontSize: theme.typography.fontSize.small,
441
+ textDecoration: 'underline',
442
+ } }, "Show less"))));
443
+ };
444
+ // -------------------------------------------------------------------
445
+ // Default facet group renderer — Checkbox variant
446
+ // -------------------------------------------------------------------
447
+ const renderCheckboxFacet = (facet, _index) => {
448
+ const filteredItems = filterItems(facet.items, facet.field);
449
+ const isExpanded = expandedFacets[facet.field] || false;
450
+ const visibleItems = isExpanded ? filteredItems : filteredItems.slice(0, maxItems);
451
+ return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
452
+ marginBottom: theme.spacing.large,
453
+ padding: theme.spacing.medium,
454
+ backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
455
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
456
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
457
+ } },
458
+ React.createElement("h3", { className: facetsTheme.facetTitle, style: {
459
+ margin: 0,
460
+ marginBottom: theme.spacing.medium,
461
+ color: theme.colors.text,
462
+ } }, facet.label || facet.field),
463
+ renderSearchInput(facet),
464
+ React.createElement("div", { className: facetsTheme.facetList, role: "listbox", "aria-label": `${facet.label || facet.field} filters`, tabIndex: 0, onKeyDown: (e) => handleListKeyDown(e, visibleItems, facet) }, visibleItems.map((item, itemIndex) => renderItem(item, facet, itemIndex))),
465
+ renderShowMoreLess(facet, filteredItems)));
466
+ };
467
+ // -------------------------------------------------------------------
468
+ // Color-swatch facet group renderer
469
+ // -------------------------------------------------------------------
470
+ const renderColorSwatchFacet = (facet, _index) => {
471
+ const filteredItems = filterItems(facet.items, facet.field);
472
+ const isExpanded = expandedFacets[facet.field] || false;
473
+ const visibleItems = isExpanded ? filteredItems : filteredItems.slice(0, maxItems);
474
+ return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
475
+ marginBottom: theme.spacing.large,
476
+ padding: theme.spacing.medium,
477
+ backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
478
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
479
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
480
+ } },
481
+ React.createElement("h3", { className: facetsTheme.facetTitle, style: {
482
+ margin: 0,
483
+ marginBottom: theme.spacing.medium,
484
+ color: theme.colors.text,
485
+ } }, facet.label || facet.field),
486
+ renderSearchInput(facet),
487
+ React.createElement("div", { className: facetsTheme.facetList, role: "listbox", "aria-label": `${facet.label || facet.field} filters`, tabIndex: 0, onKeyDown: (e) => handleListKeyDown(e, visibleItems, facet), style: {
488
+ display: 'flex',
489
+ flexWrap: 'wrap',
490
+ gap: sizeScale.gap,
491
+ } }, visibleItems.map((item, itemIndex) => renderItem(item, facet, itemIndex))),
492
+ renderShowMoreLess(facet, filteredItems)));
493
+ };
494
+ // -------------------------------------------------------------------
495
+ // Collapsible facet group renderer
496
+ // -------------------------------------------------------------------
497
+ const renderCollapsibleFacet = (facet, _index) => {
498
+ const isOpen = isFacetGroupOpen(facet.field);
499
+ const filteredItems = filterItems(facet.items, facet.field);
500
+ const isItemsExpanded = expandedFacets[facet.field] || false;
501
+ // Note: For collapsible, the expandedFacets state controls the collapse/expand
502
+ // of the group itself. We use a separate concept for Show more/less within items.
503
+ // To avoid collision, Show more/less for collapsible uses the same expandedFacets
504
+ // key prefixed with `_items_`.
505
+ const isShowMoreExpanded = expandedFacets[`_items_${facet.field}`] || false;
506
+ const visibleItems = isShowMoreExpanded ? filteredItems : filteredItems.slice(0, maxItems);
507
+ const hasMore = filteredItems.length > maxItems;
508
+ return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
509
+ marginBottom: theme.spacing.large,
510
+ backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
511
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
512
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
513
+ overflow: 'hidden',
514
+ } },
515
+ React.createElement("button", { type: "button", className: clsx(facetsTheme.collapsibleHeader), onClick: () => toggleCollapsible(facet.field), "aria-expanded": isOpen, "aria-controls": `facet-group-${facet.field}`, style: {
516
+ display: 'flex',
517
+ alignItems: 'center',
518
+ justifyContent: 'space-between',
519
+ width: '100%',
520
+ padding: theme.spacing.medium,
521
+ border: 'none',
522
+ backgroundColor: 'transparent',
523
+ cursor: 'pointer',
524
+ textAlign: 'left',
525
+ } },
526
+ React.createElement("span", { className: facetsTheme.facetTitle, style: {
527
+ color: theme.colors.text,
528
+ flex: 1,
529
+ } }, facet.label || facet.field),
530
+ React.createElement("span", { className: clsx(facetsTheme.collapsibleIcon) },
531
+ React.createElement(ChevronIcon, { expanded: isOpen, color: theme.colors.textSecondary || theme.colors.text }))),
532
+ isOpen && (React.createElement("div", { id: `facet-group-${facet.field}`, style: {
533
+ padding: `0 ${theme.spacing.medium} ${theme.spacing.medium}`,
534
+ } },
535
+ renderSearchInput(facet),
536
+ React.createElement("div", { className: facetsTheme.facetList, role: "listbox", "aria-label": `${facet.label || facet.field} filters`, tabIndex: 0, onKeyDown: (e) => handleListKeyDown(e, visibleItems, facet) }, visibleItems.map((item, itemIndex) => renderItem(item, facet, itemIndex))),
537
+ showMore && hasMore && !isShowMoreExpanded && (React.createElement("button", { type: "button", onClick: () => setExpandedFacets((prev) => ({
538
+ ...prev,
539
+ [`_items_${facet.field}`]: true,
540
+ })), style: {
541
+ marginTop: sizeScale.gap,
542
+ padding: sizeScale.padding,
543
+ border: 'none',
544
+ backgroundColor: 'transparent',
545
+ color: theme.colors.primary,
546
+ cursor: 'pointer',
547
+ fontSize: theme.typography.fontSize.small,
548
+ textDecoration: 'underline',
549
+ } },
550
+ "Show more (",
551
+ filteredItems.length - maxItems,
552
+ " more)")),
553
+ isShowMoreExpanded && hasMore && (React.createElement("button", { type: "button", onClick: () => setExpandedFacets((prev) => ({
554
+ ...prev,
555
+ [`_items_${facet.field}`]: false,
556
+ })), style: {
557
+ marginTop: sizeScale.gap,
558
+ padding: sizeScale.padding,
559
+ border: 'none',
560
+ backgroundColor: 'transparent',
561
+ color: theme.colors.primary,
562
+ cursor: 'pointer',
563
+ fontSize: theme.typography.fontSize.small,
564
+ textDecoration: 'underline',
565
+ } }, "Show less"))))));
566
+ };
567
+ // -------------------------------------------------------------------
568
+ // Render-type detection for numeric / range facets
569
+ // -------------------------------------------------------------------
570
+ const determineFacetRenderType = (fieldName, stats) => {
571
+ // If explicit range config exists for this field → range buttons
572
+ if (facetRanges?.some((rc) => rc.field === fieldName)) {
573
+ return 'range-buttons';
574
+ }
575
+ // If stats with valid min/max → range slider
576
+ if (stats && typeof stats.min === 'number' && typeof stats.max === 'number' && stats.min !== stats.max) {
577
+ return 'range-slider';
578
+ }
579
+ return 'list';
580
+ };
581
+ // -------------------------------------------------------------------
582
+ // Range button facet renderer
583
+ // -------------------------------------------------------------------
584
+ const renderRangeButtonFacet = (facet, _index) => {
585
+ const rangeConfig = facetRanges?.find((rc) => rc.field === facet.field);
586
+ if (!rangeConfig)
587
+ return null;
588
+ // Build a lookup from item value → count
589
+ const countMap = new Map();
590
+ facet.items.forEach((item) => countMap.set(item.value, item.count));
591
+ // Detect currently active range from refinements
592
+ const activeMin = refinements.find((r) => r.field === facet.field && r.value.startsWith('>='));
593
+ const activeMax = refinements.find((r) => r.field === facet.field && r.value.startsWith('<='));
594
+ const activeFromVal = activeMin ? parseFloat(activeMin.value.slice(2)) : undefined;
595
+ const activeToVal = activeMax ? parseFloat(activeMax.value.slice(2)) : undefined;
596
+ const isRangeActive = (range) => {
597
+ const fromMatch = range.from === undefined
598
+ ? activeFromVal === undefined
599
+ : activeFromVal === range.from;
600
+ const toMatch = range.to === undefined
601
+ ? activeToVal === undefined
602
+ : activeToVal === range.to;
603
+ return fromMatch && toMatch;
604
+ };
605
+ const handleRangeClick = (range) => {
606
+ // Clear existing range refinements for this field
607
+ refinements
608
+ .filter((r) => r.field === facet.field)
609
+ .forEach((r) => removeRefinement(facet.field, r.value, false));
610
+ if (isRangeActive(range)) {
611
+ // Was active → just clear (already removed above), trigger search
612
+ addRefinement(facet.field, '__noop__', false);
613
+ removeRefinement(facet.field, '__noop__', true);
614
+ return;
615
+ }
616
+ // Set new range
617
+ if (range.from !== undefined) {
618
+ addRefinement(facet.field, `>=${range.from}`, false);
619
+ }
620
+ if (range.to !== undefined) {
621
+ addRefinement(facet.field, `<=${range.to}`, true);
622
+ }
623
+ else if (range.from !== undefined) {
624
+ // Only "from" set — trigger search
625
+ addRefinement(facet.field, `>=${range.from}`, true);
626
+ }
627
+ };
628
+ const hasActiveRange = activeMin !== undefined || activeMax !== undefined;
629
+ const handleClear = () => {
630
+ refinements
631
+ .filter((r) => r.field === facet.field)
632
+ .forEach((r) => removeRefinement(facet.field, r.value, false));
633
+ // Trigger search after clearing
634
+ addRefinement(facet.field, '__noop__', false);
635
+ removeRefinement(facet.field, '__noop__', true);
636
+ };
637
+ return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
638
+ marginBottom: theme.spacing.large,
639
+ padding: theme.spacing.medium,
640
+ backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
641
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
642
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
643
+ } },
644
+ React.createElement("h3", { className: facetsTheme.facetTitle, style: {
645
+ margin: 0,
646
+ marginBottom: theme.spacing.medium,
647
+ color: theme.colors.text,
648
+ } }, facet.label || facet.field),
649
+ React.createElement("div", { style: {
650
+ display: 'flex',
651
+ flexWrap: 'wrap',
652
+ gap: sizeScale.gap,
653
+ } }, rangeConfig.ranges.map((range) => {
654
+ const count = countMap.get(range.label) ?? 0;
655
+ const active = isRangeActive(range);
656
+ return (React.createElement("button", { key: range.label, type: "button", className: clsx(facetsTheme.rangeButton, active && facetsTheme.rangeButtonActive), disabled: count === 0 && !active, onClick: () => handleRangeClick(range), style: {
657
+ display: 'inline-flex',
658
+ alignItems: 'center',
659
+ gap: '0.35em',
660
+ padding: `${sizeScale.padding} 0.75em`,
661
+ fontSize: sizeScale.font,
662
+ border: `1px solid ${active ? 'var(--seekora-primary, ' + theme.colors.primary + ')' : 'var(--seekora-facet-border, ' + theme.colors.border + ')'}`,
663
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.full,
664
+ backgroundColor: active ? 'var(--seekora-primary, ' + theme.colors.primary + ')' : 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
665
+ color: active ? 'var(--seekora-primary-text, #fff)' : theme.colors.text,
666
+ cursor: count === 0 && !active ? 'not-allowed' : 'pointer',
667
+ opacity: count === 0 && !active ? 0.5 : 1,
668
+ transition: 'all 0.2s ease',
669
+ } },
670
+ range.label,
671
+ showCounts && (React.createElement("span", { className: clsx(facetsTheme.rangeButtonCount), style: {
672
+ fontSize: theme.typography.fontSize.small,
673
+ opacity: 0.8,
674
+ } },
675
+ "(",
676
+ count,
677
+ ")"))));
678
+ })),
679
+ hasActiveRange && (React.createElement("button", { type: "button", className: clsx(facetsTheme.rangeClear), onClick: handleClear, style: {
680
+ marginTop: sizeScale.gap,
681
+ padding: sizeScale.padding,
682
+ border: 'none',
683
+ backgroundColor: 'transparent',
684
+ color: theme.colors.primary,
685
+ cursor: 'pointer',
686
+ fontSize: theme.typography.fontSize.small,
687
+ textDecoration: 'underline',
688
+ } }, "Clear"))));
689
+ };
690
+ // -------------------------------------------------------------------
691
+ // Range slider facet renderer
692
+ // -------------------------------------------------------------------
693
+ const renderRangeSliderFacet = (facet, _index) => {
694
+ if (!facet.stats)
695
+ return null;
696
+ const { min: statsMin, max: statsMax } = facet.stats;
697
+ // Auto-detect formatting for common field names
698
+ const fieldLower = facet.field.toLowerCase();
699
+ const isPriceField = fieldLower.includes('price') || fieldLower.includes('cost') || fieldLower.includes('amount');
700
+ const formatValue = isPriceField
701
+ ? (v) => `$${v.toFixed(2)}`
702
+ : (v) => v.toString();
703
+ // Determine step: use 0.01 for price, 1 for integer ranges, 0.1 otherwise
704
+ const range = statsMax - statsMin;
705
+ const step = isPriceField ? 0.01 : range > 10 ? 1 : 0.1;
706
+ // Check if there's an active range refinement
707
+ const hasActiveRange = refinements.some((r) => r.field === facet.field && (r.value.startsWith('>=') || r.value.startsWith('<=')));
708
+ const handleClear = () => {
709
+ refinements
710
+ .filter((r) => r.field === facet.field && (r.value.startsWith('>=') || r.value.startsWith('<=')))
711
+ .forEach((r) => removeRefinement(facet.field, r.value, false));
712
+ // Trigger search after clearing
713
+ addRefinement(facet.field, '__noop__', false);
714
+ removeRefinement(facet.field, '__noop__', true);
715
+ };
716
+ return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
717
+ marginBottom: theme.spacing.large,
718
+ padding: theme.spacing.medium,
719
+ backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
720
+ border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
721
+ borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
722
+ } },
723
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: theme.spacing.small } },
724
+ React.createElement("h3", { className: facetsTheme.facetTitle, style: {
725
+ margin: 0,
726
+ color: theme.colors.text,
727
+ } }, facet.label || facet.field),
728
+ hasActiveRange && (React.createElement("button", { type: "button", className: clsx(facetsTheme.rangeClear), onClick: handleClear, style: {
729
+ padding: '0.15em 0.5em',
730
+ border: 'none',
731
+ backgroundColor: 'transparent',
732
+ color: theme.colors.primary,
733
+ cursor: 'pointer',
734
+ fontSize: theme.typography.fontSize.small,
735
+ textDecoration: 'underline',
736
+ } }, "Clear"))),
737
+ React.createElement(RangeSlider, { field: facet.field, min: statsMin, max: statsMax, step: step, formatValue: formatValue, syncWithState: true })));
738
+ };
739
+ // -------------------------------------------------------------------
740
+ // Default facet renderer dispatcher
741
+ // -------------------------------------------------------------------
742
+ const defaultRenderFacet = (facet, index) => {
743
+ const renderType = determineFacetRenderType(facet.field, facet.stats);
744
+ if (renderType === 'range-buttons') {
745
+ return renderRangeButtonFacet(facet, index);
746
+ }
747
+ if (renderType === 'range-slider') {
748
+ return renderRangeSliderFacet(facet, index);
749
+ }
750
+ switch (variant) {
751
+ case 'color-swatch':
752
+ return renderColorSwatchFacet(facet, index);
753
+ case 'collapsible':
754
+ return renderCollapsibleFacet(facet, index);
755
+ case 'checkbox':
756
+ default:
757
+ return renderCheckboxFacet(facet, index);
758
+ }
759
+ };
760
+ // -------------------------------------------------------------------
761
+ // Empty state
762
+ // -------------------------------------------------------------------
763
+ if (facets.length === 0) {
764
+ log.verbose('Facets: No facets to display', {
765
+ hasResults: !!results,
766
+ resultsType: results ? typeof results : 'null',
767
+ });
768
+ // Return a placeholder instead of null for debugging
769
+ if (process.env.NODE_ENV === 'development') {
770
+ return (React.createElement("div", { style: { padding: theme.spacing.small, color: theme.colors.textSecondary, fontSize: theme.typography.fontSize.small } }, "No facets available"));
771
+ }
772
+ return null;
773
+ }
774
+ // -------------------------------------------------------------------
775
+ // Render
776
+ // -------------------------------------------------------------------
777
+ return (React.createElement("div", { className: clsx(facetsTheme.container, className), style: {
778
+ ...CSS_VAR_DEFAULTS,
779
+ ...style,
780
+ } }, facets.map((facet, index) => {
781
+ return renderFacet
782
+ ? renderFacet(facet, index)
783
+ : defaultRenderFacet(facet, index);
784
+ })));
785
+ };