@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.
- 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 +81 -0
- package/dist/components/CurrentRefinements.d.ts +63 -0
- package/dist/components/CurrentRefinements.d.ts.map +1 -0
- package/dist/components/CurrentRefinements.js +302 -0
- package/dist/components/FacetDropdown.d.ts +94 -0
- package/dist/components/FacetDropdown.d.ts.map +1 -0
- package/dist/components/FacetDropdown.js +396 -0
- package/dist/components/Facets.d.ts +118 -0
- package/dist/components/Facets.d.ts.map +1 -0
- package/dist/components/Facets.js +785 -0
- package/dist/components/FederatedDropdown.d.ts +98 -0
- package/dist/components/FederatedDropdown.d.ts.map +1 -0
- package/dist/components/FederatedDropdown.js +526 -0
- package/dist/components/HierarchicalMenu.d.ts +55 -0
- package/dist/components/HierarchicalMenu.d.ts.map +1 -0
- package/dist/components/HierarchicalMenu.js +276 -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 +82 -0
- package/dist/components/InfiniteHits.d.ts +51 -0
- package/dist/components/InfiniteHits.d.ts.map +1 -0
- package/dist/components/InfiniteHits.js +173 -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 +90 -0
- package/dist/components/Pagination.d.ts.map +1 -0
- package/dist/components/Pagination.js +298 -0
- package/dist/components/QuerySuggestions.d.ts +36 -0
- package/dist/components/QuerySuggestions.d.ts.map +1 -0
- package/dist/components/QuerySuggestions.js +71 -0
- package/dist/components/QuerySuggestionsDropdown.d.ts +82 -0
- package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -0
- package/dist/components/QuerySuggestionsDropdown.js +394 -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 +262 -0
- package/dist/components/Recommendations.d.ts +89 -0
- package/dist/components/Recommendations.d.ts.map +1 -0
- package/dist/components/Recommendations.js +256 -0
- package/dist/components/RichQuerySuggestions.d.ts +88 -0
- package/dist/components/RichQuerySuggestions.d.ts.map +1 -0
- package/dist/components/RichQuerySuggestions.js +498 -0
- package/dist/components/SearchBar.d.ts +57 -0
- package/dist/components/SearchBar.d.ts.map +1 -0
- package/dist/components/SearchBar.js +361 -0
- package/dist/components/SearchBarWithSuggestions.d.ts +105 -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 +61 -0
- package/dist/components/SearchProvider.d.ts +35 -0
- package/dist/components/SearchProvider.d.ts.map +1 -0
- package/dist/components/SearchProvider.js +53 -0
- package/dist/components/SearchResults.d.ts +57 -0
- package/dist/components/SearchResults.d.ts.map +1 -0
- package/dist/components/SearchResults.js +456 -0
- package/dist/components/SortBy.d.ts +84 -0
- package/dist/components/SortBy.d.ts.map +1 -0
- package/dist/components/SortBy.js +183 -0
- package/dist/components/Stats.d.ts +51 -0
- package/dist/components/Stats.d.ts.map +1 -0
- package/dist/components/Stats.js +201 -0
- package/dist/components/primitives/ActionButtons.d.ts +27 -0
- package/dist/components/primitives/ActionButtons.d.ts.map +1 -0
- package/dist/components/primitives/ActionButtons.js +102 -0
- package/dist/components/primitives/AnalyticsProvider.d.ts +22 -0
- package/dist/components/primitives/AnalyticsProvider.d.ts.map +1 -0
- package/dist/components/primitives/AnalyticsProvider.js +87 -0
- package/dist/components/primitives/BadgeList.d.ts +14 -0
- package/dist/components/primitives/BadgeList.d.ts.map +1 -0
- package/dist/components/primitives/BadgeList.js +65 -0
- package/dist/components/primitives/CustomSelect.d.ts +40 -0
- package/dist/components/primitives/CustomSelect.d.ts.map +1 -0
- package/dist/components/primitives/CustomSelect.js +196 -0
- package/dist/components/primitives/ImageDisplay.d.ts +28 -0
- package/dist/components/primitives/ImageDisplay.d.ts.map +1 -0
- package/dist/components/primitives/ImageDisplay.js +127 -0
- package/dist/components/primitives/ImageZoom.d.ts +33 -0
- package/dist/components/primitives/ImageZoom.d.ts.map +1 -0
- package/dist/components/primitives/ImageZoom.js +433 -0
- package/dist/components/primitives/PriceDisplay.d.ts +21 -0
- package/dist/components/primitives/PriceDisplay.d.ts.map +1 -0
- package/dist/components/primitives/PriceDisplay.js +44 -0
- package/dist/components/primitives/RatingDisplay.d.ts +43 -0
- package/dist/components/primitives/RatingDisplay.d.ts.map +1 -0
- package/dist/components/primitives/RatingDisplay.js +114 -0
- package/dist/components/primitives/VariantSelector.d.ts +30 -0
- package/dist/components/primitives/VariantSelector.d.ts.map +1 -0
- package/dist/components/primitives/VariantSelector.js +155 -0
- package/dist/components/primitives/VariantSwatches.d.ts +28 -0
- package/dist/components/primitives/VariantSwatches.d.ts.map +1 -0
- package/dist/components/primitives/VariantSwatches.js +188 -0
- package/dist/components/primitives/index.d.ts +12 -0
- package/dist/components/primitives/index.d.ts.map +1 -0
- package/dist/components/primitives/index.js +11 -0
- package/dist/components/primitives/withAnalytics.d.ts +24 -0
- package/dist/components/primitives/withAnalytics.d.ts.map +1 -0
- package/dist/components/primitives/withAnalytics.js +73 -0
- package/dist/components/product-page/ProductGallery.d.ts +26 -0
- package/dist/components/product-page/ProductGallery.d.ts.map +1 -0
- package/dist/components/product-page/ProductGallery.js +13 -0
- package/dist/components/product-page/ProductInfo.d.ts +44 -0
- package/dist/components/product-page/ProductInfo.d.ts.map +1 -0
- package/dist/components/product-page/ProductInfo.js +34 -0
- package/dist/components/product-page/ProductRecommendations.d.ts +21 -0
- package/dist/components/product-page/ProductRecommendations.d.ts.map +1 -0
- package/dist/components/product-page/ProductRecommendations.js +17 -0
- package/dist/components/product-page/index.d.ts +4 -0
- package/dist/components/product-page/index.d.ts.map +1 -0
- package/dist/components/product-page/index.js +3 -0
- package/dist/components/section-primitives/SectionError.d.ts +11 -0
- package/dist/components/section-primitives/SectionError.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionError.js +13 -0
- package/dist/components/section-primitives/SectionItemGrid.d.ts +18 -0
- package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionItemGrid.js +14 -0
- package/dist/components/section-primitives/SectionLoading.d.ts +11 -0
- package/dist/components/section-primitives/SectionLoading.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionLoading.js +11 -0
- package/dist/components/section-primitives/SectionSearchContext.d.ts +17 -0
- package/dist/components/section-primitives/SectionSearchContext.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionSearchContext.js +17 -0
- package/dist/components/section-primitives/SectionSearchProvider.d.ts +25 -0
- package/dist/components/section-primitives/SectionSearchProvider.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionSearchProvider.js +106 -0
- package/dist/components/section-primitives/index.d.ts +5 -0
- package/dist/components/section-primitives/index.d.ts.map +1 -0
- package/dist/components/section-primitives/index.js +4 -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 +509 -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 +349 -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 +312 -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 +483 -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 +446 -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 +448 -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 +544 -0
- package/dist/components/suggestions/SuggestionSearchBar.d.ts +127 -0
- package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -0
- package/dist/components/suggestions/SuggestionSearchBar.js +644 -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 +511 -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 +259 -0
- package/dist/components/suggestions/utils.d.ts.map +1 -0
- package/dist/components/suggestions/utils.js +668 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.d.ts +13 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.js +35 -0
- package/dist/components/suggestions-primitives/DropdownPanel.d.ts +24 -0
- package/dist/components/suggestions-primitives/DropdownPanel.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/DropdownPanel.js +67 -0
- package/dist/components/suggestions-primitives/ItemCard.d.ts +48 -0
- package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ItemCard.js +103 -0
- package/dist/components/suggestions-primitives/ItemGrid.d.ts +28 -0
- package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ItemGrid.js +55 -0
- package/dist/components/suggestions-primitives/ProductCard.d.ts +45 -0
- package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ProductCard.js +177 -0
- package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts +44 -0
- package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ProductCardLayouts.js +137 -0
- package/dist/components/suggestions-primitives/ProductGrid.d.ts +22 -0
- package/dist/components/suggestions-primitives/ProductGrid.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ProductGrid.js +41 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.d.ts +17 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.js +46 -0
- package/dist/components/suggestions-primitives/SearchInput.d.ts +23 -0
- package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SearchInput.js +114 -0
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts +31 -0
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionItem.js +47 -0
- package/dist/components/suggestions-primitives/SuggestionList.d.ts +26 -0
- package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionList.js +35 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts +44 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.js +18 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts +24 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.js +30 -0
- package/dist/components/suggestions-primitives/SuggestionsError.d.ts +11 -0
- package/dist/components/suggestions-primitives/SuggestionsError.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsError.js +19 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts +11 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.js +17 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts +38 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.js +259 -0
- package/dist/components/suggestions-primitives/TrendingList.d.ts +17 -0
- package/dist/components/suggestions-primitives/TrendingList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/TrendingList.js +48 -0
- package/dist/components/suggestions-primitives/highlightMarkup.d.ts +31 -0
- package/dist/components/suggestions-primitives/highlightMarkup.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/highlightMarkup.js +70 -0
- package/dist/components/suggestions-primitives/index.d.ts +39 -0
- package/dist/components/suggestions-primitives/index.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/index.js +24 -0
- package/dist/docsearch/components/DocSearch.d.ts +4 -0
- package/dist/docsearch/components/DocSearch.d.ts.map +1 -0
- package/dist/docsearch/components/DocSearch.js +93 -0
- package/dist/docsearch/components/DocSearchButton.d.ts +4 -0
- package/dist/docsearch/components/DocSearchButton.d.ts.map +1 -0
- package/dist/docsearch/components/DocSearchButton.js +12 -0
- package/dist/docsearch/components/Footer.d.ts +8 -0
- package/dist/docsearch/components/Footer.d.ts.map +1 -0
- package/dist/docsearch/components/Footer.js +40 -0
- package/dist/docsearch/components/Highlight.d.ts +9 -0
- package/dist/docsearch/components/Highlight.d.ts.map +1 -0
- package/dist/docsearch/components/Highlight.js +48 -0
- package/dist/docsearch/components/Hit.d.ts +15 -0
- package/dist/docsearch/components/Hit.d.ts.map +1 -0
- package/dist/docsearch/components/Hit.js +96 -0
- package/dist/docsearch/components/Modal.d.ts +10 -0
- package/dist/docsearch/components/Modal.d.ts.map +1 -0
- package/dist/docsearch/components/Modal.js +57 -0
- package/dist/docsearch/components/Results.d.ts +23 -0
- package/dist/docsearch/components/Results.d.ts.map +1 -0
- package/dist/docsearch/components/Results.js +141 -0
- package/dist/docsearch/components/SearchBox.d.ts +11 -0
- package/dist/docsearch/components/SearchBox.d.ts.map +1 -0
- package/dist/docsearch/components/SearchBox.js +16 -0
- package/dist/docsearch/hooks/useDocSearch.d.ts +33 -0
- package/dist/docsearch/hooks/useDocSearch.d.ts.map +1 -0
- package/dist/docsearch/hooks/useDocSearch.js +224 -0
- package/dist/docsearch/hooks/useKeyboard.d.ts +17 -0
- package/dist/docsearch/hooks/useKeyboard.d.ts.map +1 -0
- package/dist/docsearch/hooks/useKeyboard.js +71 -0
- package/dist/docsearch/hooks/useSeekoraSearch.d.ts +27 -0
- package/dist/docsearch/hooks/useSeekoraSearch.d.ts.map +1 -0
- package/dist/docsearch/hooks/useSeekoraSearch.js +213 -0
- package/dist/docsearch/index.d.ts +13 -0
- package/dist/docsearch/index.d.ts.map +1 -0
- package/dist/docsearch/index.js +11 -0
- package/dist/docsearch/types.d.ts +175 -0
- package/dist/docsearch/types.d.ts.map +1 -0
- package/dist/docsearch/types.js +4 -0
- package/dist/docsearch.css +234 -0
- package/dist/hooks/useAnalytics.d.ts +24 -0
- package/dist/hooks/useAnalytics.d.ts.map +1 -0
- package/dist/hooks/useAnalytics.js +67 -0
- package/dist/hooks/useClickTracking.d.ts +36 -0
- package/dist/hooks/useClickTracking.d.ts.map +1 -0
- package/dist/hooks/useClickTracking.js +89 -0
- package/dist/hooks/useExperiment.d.ts +25 -0
- package/dist/hooks/useExperiment.d.ts.map +1 -0
- package/dist/hooks/useExperiment.js +123 -0
- package/dist/hooks/useFilters.d.ts +27 -0
- package/dist/hooks/useFilters.d.ts.map +1 -0
- package/dist/hooks/useFilters.js +86 -0
- package/dist/hooks/useKeyboardNavigation.d.ts +51 -0
- package/dist/hooks/useKeyboardNavigation.d.ts.map +1 -0
- package/dist/hooks/useKeyboardNavigation.js +113 -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/useProductAnalytics.d.ts +49 -0
- package/dist/hooks/useProductAnalytics.d.ts.map +1 -0
- package/dist/hooks/useProductAnalytics.js +116 -0
- package/dist/hooks/useQuerySuggestions.d.ts +21 -0
- package/dist/hooks/useQuerySuggestions.d.ts.map +1 -0
- package/dist/hooks/useQuerySuggestions.js +84 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts +120 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.js +444 -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 +93 -0
- package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -0
- package/dist/hooks/useSuggestionsAnalytics.js +239 -0
- package/dist/hooks/useVariantSelection.d.ts +28 -0
- package/dist/hooks/useVariantSelection.d.ts.map +1 -0
- package/dist/hooks/useVariantSelection.js +44 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +110 -0
- package/dist/index.umd.js +1 -0
- package/dist/src/index.d.ts +4469 -0
- package/dist/src/index.esm.js +18952 -0
- package/dist/src/index.esm.js.map +1 -0
- package/dist/src/index.js +19086 -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/dist/utils/responsive.d.ts +130 -0
- package/dist/utils/responsive.d.ts.map +1 -0
- package/dist/utils/responsive.js +225 -0
- package/package.json +68 -0
- package/src/docsearch/docsearch.css +234 -0
|
@@ -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"}
|
|
@@ -0,0 +1,236 @@
|
|
|
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
|
+
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
|
8
|
+
import { useSearchContext } from '../components/SearchProvider';
|
|
9
|
+
/**
|
|
10
|
+
* Pattern-based intent detection (client-side fallback)
|
|
11
|
+
*/
|
|
12
|
+
function detectIntent(query) {
|
|
13
|
+
const patterns = [
|
|
14
|
+
{ pattern: /^(buy|purchase|order|get)\s+/i, intent: 'purchase' },
|
|
15
|
+
{ pattern: /^(find|search|looking for|where)\s+/i, intent: 'search' },
|
|
16
|
+
{ pattern: /^(compare|vs|versus)\s+/i, intent: 'compare' },
|
|
17
|
+
{ pattern: /^(how (to|do)|what is|why)\s+/i, intent: 'informational' },
|
|
18
|
+
{ pattern: /under\s*\$?\d+|less than\s*\$?\d+|cheap|affordable/i, intent: 'price_sensitive' },
|
|
19
|
+
{ pattern: /best|top|recommended|popular/i, intent: 'recommendation' },
|
|
20
|
+
{ pattern: /\d+\s*(gb|tb|inch|cm|mm|kg|lb)/i, intent: 'specification' },
|
|
21
|
+
{ pattern: /(red|blue|green|black|white|pink|purple|yellow)\s+/i, intent: 'color_preference' },
|
|
22
|
+
{ pattern: /(size|small|medium|large|xl|xxl)\s+/i, intent: 'size_preference' },
|
|
23
|
+
];
|
|
24
|
+
for (const { pattern, intent } of patterns) {
|
|
25
|
+
if (pattern.test(query)) {
|
|
26
|
+
return { intent, confidence: 0.8 };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Simple Levenshtein distance for spell checking
|
|
33
|
+
*/
|
|
34
|
+
function levenshteinDistance(a, b) {
|
|
35
|
+
const matrix = [];
|
|
36
|
+
for (let i = 0; i <= b.length; i++) {
|
|
37
|
+
matrix[i] = [i];
|
|
38
|
+
}
|
|
39
|
+
for (let j = 0; j <= a.length; j++) {
|
|
40
|
+
matrix[0][j] = j;
|
|
41
|
+
}
|
|
42
|
+
for (let i = 1; i <= b.length; i++) {
|
|
43
|
+
for (let j = 1; j <= a.length; j++) {
|
|
44
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
45
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return matrix[b.length][a.length];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Find potential corrections from a dictionary
|
|
56
|
+
*/
|
|
57
|
+
function findCorrections(query, dictionary, maxDistance = 2) {
|
|
58
|
+
const words = query.toLowerCase().split(/\s+/);
|
|
59
|
+
const corrections = [];
|
|
60
|
+
words.forEach(word => {
|
|
61
|
+
if (word.length < 3)
|
|
62
|
+
return;
|
|
63
|
+
dictionary.forEach(dictWord => {
|
|
64
|
+
const distance = levenshteinDistance(word, dictWord.toLowerCase());
|
|
65
|
+
if (distance > 0 && distance <= maxDistance && distance < word.length / 2) {
|
|
66
|
+
const corrected = query.replace(new RegExp(word, 'gi'), dictWord);
|
|
67
|
+
if (!corrections.includes(corrected)) {
|
|
68
|
+
corrections.push(corrected);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
return corrections.slice(0, 3);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Expand query with synonyms and related terms
|
|
77
|
+
*/
|
|
78
|
+
function expandQuery(query) {
|
|
79
|
+
const expansions = {
|
|
80
|
+
phone: ['smartphone', 'mobile', 'cellphone'],
|
|
81
|
+
laptop: ['notebook', 'computer', 'pc'],
|
|
82
|
+
tv: ['television', 'smart tv', 'monitor'],
|
|
83
|
+
headphones: ['earbuds', 'earphones', 'headset'],
|
|
84
|
+
shoes: ['footwear', 'sneakers', 'boots'],
|
|
85
|
+
shirt: ['top', 'blouse', 'tee'],
|
|
86
|
+
pants: ['trousers', 'jeans', 'bottoms'],
|
|
87
|
+
cheap: ['affordable', 'budget', 'inexpensive'],
|
|
88
|
+
best: ['top-rated', 'popular', 'recommended'],
|
|
89
|
+
};
|
|
90
|
+
const queryLower = query.toLowerCase();
|
|
91
|
+
const expanded = [];
|
|
92
|
+
Object.entries(expansions).forEach(([term, synonyms]) => {
|
|
93
|
+
if (queryLower.includes(term)) {
|
|
94
|
+
synonyms.forEach(syn => {
|
|
95
|
+
const exp = query.replace(new RegExp(term, 'gi'), syn);
|
|
96
|
+
if (!expanded.includes(exp)) {
|
|
97
|
+
expanded.push(exp);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return expanded.slice(0, 3);
|
|
103
|
+
}
|
|
104
|
+
export function useSmartSuggestions(query, options = {}) {
|
|
105
|
+
const { minQueryLength = 1, maxSuggestions = 10, debounceMs = 200, enableSpellCorrection = true, enableQueryExpansion = true, enableIntentDetection = true, includeTrending = true, userContext, } = options;
|
|
106
|
+
const { stateManager } = useSearchContext();
|
|
107
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
108
|
+
const [loading, setLoading] = useState(false);
|
|
109
|
+
const [error, setError] = useState(null);
|
|
110
|
+
const [detectedIntent, setDetectedIntent] = useState(null);
|
|
111
|
+
const [corrections, setCorrections] = useState([]);
|
|
112
|
+
const [expansions, setExpansions] = useState([]);
|
|
113
|
+
const debounceTimer = useRef(null);
|
|
114
|
+
// Sample dictionary for spell checking (in production, this would come from the API)
|
|
115
|
+
const dictionary = useMemo(() => [
|
|
116
|
+
'phone', 'laptop', 'computer', 'tablet', 'headphones', 'camera',
|
|
117
|
+
'television', 'speaker', 'watch', 'keyboard', 'mouse', 'monitor',
|
|
118
|
+
'shirt', 'pants', 'shoes', 'jacket', 'dress', 'skirt', 'sweater',
|
|
119
|
+
'electronics', 'clothing', 'accessories', 'furniture', 'appliances',
|
|
120
|
+
], []);
|
|
121
|
+
const processQuery = useCallback(async (q) => {
|
|
122
|
+
const results = [];
|
|
123
|
+
// Detect intent
|
|
124
|
+
if (enableIntentDetection) {
|
|
125
|
+
const intent = detectIntent(q);
|
|
126
|
+
if (intent) {
|
|
127
|
+
setDetectedIntent(intent.intent);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
setDetectedIntent(null);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Find spell corrections
|
|
134
|
+
if (enableSpellCorrection && q.length >= 3) {
|
|
135
|
+
const correctionResults = findCorrections(q, dictionary);
|
|
136
|
+
setCorrections(correctionResults);
|
|
137
|
+
correctionResults.forEach(correction => {
|
|
138
|
+
results.push({
|
|
139
|
+
text: correction,
|
|
140
|
+
type: 'correction',
|
|
141
|
+
confidence: 0.9,
|
|
142
|
+
metadata: { correctedFrom: q },
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// Expand query
|
|
147
|
+
if (enableQueryExpansion) {
|
|
148
|
+
const expansionResults = expandQuery(q);
|
|
149
|
+
setExpansions(expansionResults);
|
|
150
|
+
expansionResults.forEach(exp => {
|
|
151
|
+
results.push({
|
|
152
|
+
text: exp,
|
|
153
|
+
type: 'expansion',
|
|
154
|
+
confidence: 0.7,
|
|
155
|
+
metadata: { expandedTo: [exp] },
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// Add the original query as a suggestion
|
|
160
|
+
results.unshift({
|
|
161
|
+
text: q,
|
|
162
|
+
type: 'query',
|
|
163
|
+
confidence: 1.0,
|
|
164
|
+
});
|
|
165
|
+
// Add related suggestions based on context
|
|
166
|
+
if (userContext?.recentSearches) {
|
|
167
|
+
userContext.recentSearches
|
|
168
|
+
.filter(s => s.toLowerCase().includes(q.toLowerCase()) && s !== q)
|
|
169
|
+
.slice(0, 2)
|
|
170
|
+
.forEach(s => {
|
|
171
|
+
results.push({
|
|
172
|
+
text: s,
|
|
173
|
+
type: 'related',
|
|
174
|
+
confidence: 0.6,
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return results.slice(0, maxSuggestions);
|
|
179
|
+
}, [dictionary, enableIntentDetection, enableSpellCorrection, enableQueryExpansion, maxSuggestions, userContext]);
|
|
180
|
+
const getSuggestions = useCallback(async (q) => {
|
|
181
|
+
if (q.length < minQueryLength) {
|
|
182
|
+
return [];
|
|
183
|
+
}
|
|
184
|
+
return processQuery(q);
|
|
185
|
+
}, [minQueryLength, processQuery]);
|
|
186
|
+
// Debounced effect
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (debounceTimer.current) {
|
|
189
|
+
clearTimeout(debounceTimer.current);
|
|
190
|
+
}
|
|
191
|
+
if (query.length < minQueryLength) {
|
|
192
|
+
setSuggestions([]);
|
|
193
|
+
setCorrections([]);
|
|
194
|
+
setExpansions([]);
|
|
195
|
+
setDetectedIntent(null);
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
setLoading(true);
|
|
199
|
+
debounceTimer.current = setTimeout(async () => {
|
|
200
|
+
try {
|
|
201
|
+
const results = await processQuery(query);
|
|
202
|
+
setSuggestions(results);
|
|
203
|
+
setError(null);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
207
|
+
setSuggestions([]);
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
setLoading(false);
|
|
211
|
+
}
|
|
212
|
+
}, debounceMs);
|
|
213
|
+
return () => {
|
|
214
|
+
if (debounceTimer.current) {
|
|
215
|
+
clearTimeout(debounceTimer.current);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}, [query, minQueryLength, debounceMs, processQuery]);
|
|
219
|
+
const clear = useCallback(() => {
|
|
220
|
+
setSuggestions([]);
|
|
221
|
+
setCorrections([]);
|
|
222
|
+
setExpansions([]);
|
|
223
|
+
setDetectedIntent(null);
|
|
224
|
+
setError(null);
|
|
225
|
+
}, []);
|
|
226
|
+
return {
|
|
227
|
+
suggestions,
|
|
228
|
+
loading,
|
|
229
|
+
error,
|
|
230
|
+
detectedIntent,
|
|
231
|
+
corrections,
|
|
232
|
+
expansions,
|
|
233
|
+
getSuggestions,
|
|
234
|
+
clear,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggestions Analytics Hook
|
|
3
|
+
*
|
|
4
|
+
* Provides analytics tracking for query suggestions components using
|
|
5
|
+
* Analytics V3 event structure and schema/fields (event_name, event_ts,
|
|
6
|
+
* correlation_id/search_id via context, and V3 top-level fields such as
|
|
7
|
+
* original_query, position, section, clicked_item_id, click_type, tab_id,
|
|
8
|
+
* suggestions_count, etc.). All events are sent via client.trackEvent(payload, context)
|
|
9
|
+
* so the SDK can attach correlation_id, search_id, event_ts, orgcode, xstoreid.
|
|
10
|
+
*/
|
|
11
|
+
import type { SeekoraClient, SearchContext } from '@seekora-ai/search-sdk';
|
|
12
|
+
import type { SuggestionItem, ProductItem, SuggestionCategory, PopularBrand, FilteredTab, RecentSearch, TrendingSearch } from '@seekora-ai/ui-sdk-types';
|
|
13
|
+
export interface UseSuggestionsAnalyticsOptions {
|
|
14
|
+
/** Seekora client instance */
|
|
15
|
+
client: SeekoraClient;
|
|
16
|
+
/** Enable analytics tracking */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Analytics tags to include with all events */
|
|
19
|
+
analyticsTags?: string[];
|
|
20
|
+
/** Debounce impression events (ms) */
|
|
21
|
+
impressionDebounce?: number;
|
|
22
|
+
/** Track suggestion impressions automatically */
|
|
23
|
+
trackImpressions?: boolean;
|
|
24
|
+
/** Track clicks automatically */
|
|
25
|
+
trackClicks?: boolean;
|
|
26
|
+
/** Optional search context (correlationId, searchId) to attach to events when available */
|
|
27
|
+
context?: SearchContext | Partial<SearchContext>;
|
|
28
|
+
}
|
|
29
|
+
export interface SuggestionClickEventData {
|
|
30
|
+
/** The clicked suggestion */
|
|
31
|
+
suggestion: SuggestionItem;
|
|
32
|
+
/** Position in the list (0-indexed) */
|
|
33
|
+
position: number;
|
|
34
|
+
/** Section where the suggestion appeared */
|
|
35
|
+
section?: 'suggestions' | 'trending' | 'recent' | 'related';
|
|
36
|
+
/** Original query that triggered suggestions */
|
|
37
|
+
query?: string;
|
|
38
|
+
/** Total suggestions shown */
|
|
39
|
+
totalSuggestions?: number;
|
|
40
|
+
}
|
|
41
|
+
export interface ProductClickEventData {
|
|
42
|
+
/** The clicked product */
|
|
43
|
+
product: ProductItem;
|
|
44
|
+
/** Position in the list (0-indexed) */
|
|
45
|
+
position: number;
|
|
46
|
+
/** Section where the product appeared */
|
|
47
|
+
section?: 'products' | 'trending' | 'recommendations' | 'filtered_tab';
|
|
48
|
+
/** Tab ID if from filtered tab */
|
|
49
|
+
tabId?: string;
|
|
50
|
+
/** Original query */
|
|
51
|
+
query?: string;
|
|
52
|
+
}
|
|
53
|
+
export interface SuggestionImpressionEventData {
|
|
54
|
+
/** Suggestions that were shown */
|
|
55
|
+
suggestions: SuggestionItem[];
|
|
56
|
+
/** Products that were shown */
|
|
57
|
+
products?: ProductItem[];
|
|
58
|
+
/** Categories that were shown */
|
|
59
|
+
categories?: SuggestionCategory[];
|
|
60
|
+
/** Brands that were shown */
|
|
61
|
+
brands?: PopularBrand[];
|
|
62
|
+
/** Original query */
|
|
63
|
+
query: string;
|
|
64
|
+
/** Timestamp when impressions occurred */
|
|
65
|
+
timestamp: number;
|
|
66
|
+
}
|
|
67
|
+
export interface UseSuggestionsAnalyticsReturn {
|
|
68
|
+
/** Track a suggestion click */
|
|
69
|
+
trackSuggestionClick: (data: SuggestionClickEventData) => void;
|
|
70
|
+
/** Track a product click from suggestions dropdown */
|
|
71
|
+
trackProductClick: (data: ProductClickEventData) => void;
|
|
72
|
+
/** Track a category click */
|
|
73
|
+
trackCategoryClick: (category: SuggestionCategory, query?: string) => void;
|
|
74
|
+
/** Track a brand click */
|
|
75
|
+
trackBrandClick: (brand: PopularBrand, query?: string) => void;
|
|
76
|
+
/** Track a tab selection */
|
|
77
|
+
trackTabSelect: (tab: FilteredTab, query?: string) => void;
|
|
78
|
+
/** Track recent search click */
|
|
79
|
+
trackRecentSearchClick: (search: RecentSearch) => void;
|
|
80
|
+
/** Track trending search click */
|
|
81
|
+
trackTrendingClick: (trending: TrendingSearch, position: number) => void;
|
|
82
|
+
/** Track suggestions impression */
|
|
83
|
+
trackImpression: (data: SuggestionImpressionEventData) => void;
|
|
84
|
+
/** Track search submission from suggestion */
|
|
85
|
+
trackSearchSubmit: (query: string, fromSuggestion: boolean, suggestion?: SuggestionItem) => void;
|
|
86
|
+
/** Track dropdown open */
|
|
87
|
+
trackDropdownOpen: (query: string) => void;
|
|
88
|
+
/** Track dropdown close */
|
|
89
|
+
trackDropdownClose: (query: string, selectedSuggestion?: string) => void;
|
|
90
|
+
}
|
|
91
|
+
export declare function useSuggestionsAnalytics(options: UseSuggestionsAnalyticsOptions): UseSuggestionsAnalyticsReturn;
|
|
92
|
+
export default useSuggestionsAnalytics;
|
|
93
|
+
//# sourceMappingURL=useSuggestionsAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSuggestionsAnalytics.d.ts","sourceRoot":"","sources":["../../src/hooks/useSuggestionsAnalytics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggestions Analytics Hook
|
|
3
|
+
*
|
|
4
|
+
* Provides analytics tracking for query suggestions components using
|
|
5
|
+
* Analytics V3 event structure and schema/fields (event_name, event_ts,
|
|
6
|
+
* correlation_id/search_id via context, and V3 top-level fields such as
|
|
7
|
+
* original_query, position, section, clicked_item_id, click_type, tab_id,
|
|
8
|
+
* suggestions_count, etc.). All events are sent via client.trackEvent(payload, context)
|
|
9
|
+
* so the SDK can attach correlation_id, search_id, event_ts, orgcode, xstoreid.
|
|
10
|
+
*/
|
|
11
|
+
import { useCallback, useRef, useEffect } from 'react';
|
|
12
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Event Names
|
|
15
|
+
// ============================================================================
|
|
16
|
+
const EVENTS = {
|
|
17
|
+
SUGGESTION_CLICK: 'suggestions.click',
|
|
18
|
+
SUGGESTION_IMPRESSION: 'suggestions.impression',
|
|
19
|
+
PRODUCT_CLICK: 'suggestions.product_click',
|
|
20
|
+
CATEGORY_CLICK: 'suggestions.category_click',
|
|
21
|
+
BRAND_CLICK: 'suggestions.brand_click',
|
|
22
|
+
TAB_SELECT: 'suggestions.tab_select',
|
|
23
|
+
RECENT_CLICK: 'suggestions.recent_click',
|
|
24
|
+
TRENDING_CLICK: 'suggestions.trending_click',
|
|
25
|
+
SEARCH_SUBMIT: 'suggestions.search_submit',
|
|
26
|
+
DROPDOWN_OPEN: 'suggestions.dropdown_open',
|
|
27
|
+
DROPDOWN_CLOSE: 'suggestions.dropdown_close',
|
|
28
|
+
// Variant & product interaction events
|
|
29
|
+
VARIANT_SELECT: 'product.variant_select',
|
|
30
|
+
VARIANT_HOVER: 'product.variant_hover',
|
|
31
|
+
ADD_TO_CART: 'product.add_to_cart',
|
|
32
|
+
PRODUCT_IMPRESSION: 'product.impression',
|
|
33
|
+
SWATCH_CLICK: 'product.swatch_click',
|
|
34
|
+
};
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Hook Implementation
|
|
37
|
+
// ============================================================================
|
|
38
|
+
export function useSuggestionsAnalytics(options) {
|
|
39
|
+
const { client, enabled = true, analyticsTags = [], impressionDebounce = 500, trackImpressions = true, trackClicks = true, context: contextOption, } = options;
|
|
40
|
+
// Refs for debouncing and tracking
|
|
41
|
+
const impressionTimerRef = useRef(null);
|
|
42
|
+
const lastImpressionRef = useRef(null);
|
|
43
|
+
const dropdownOpenTimeRef = useRef(null);
|
|
44
|
+
// Cleanup on unmount
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
return () => {
|
|
47
|
+
if (impressionTimerRef.current) {
|
|
48
|
+
clearTimeout(impressionTimerRef.current);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}, []);
|
|
52
|
+
// Helper to send event (optional context links event to search for v3 analytics)
|
|
53
|
+
const sendEvent = useCallback(async (eventName, metadata, context) => {
|
|
54
|
+
if (!enabled || !client)
|
|
55
|
+
return;
|
|
56
|
+
const searchContext = context ?? contextOption;
|
|
57
|
+
try {
|
|
58
|
+
// Extract query for search-related events (backend requires query at top level for search events)
|
|
59
|
+
const { query, ...restMetadata } = metadata;
|
|
60
|
+
const isSearchEvent = eventName.includes('search') || eventName === EVENTS.SEARCH_SUBMIT;
|
|
61
|
+
await client.trackEvent?.({
|
|
62
|
+
event_name: eventName,
|
|
63
|
+
analytics_tags: analyticsTags,
|
|
64
|
+
// Include query at top level for search events
|
|
65
|
+
...(isSearchEvent && query ? { query } : {}),
|
|
66
|
+
metadata: {
|
|
67
|
+
...restMetadata,
|
|
68
|
+
timestamp: Date.now(),
|
|
69
|
+
source: 'suggestions_dropdown',
|
|
70
|
+
},
|
|
71
|
+
}, searchContext);
|
|
72
|
+
log.verbose(`Analytics: ${eventName}`, metadata);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
log.warn(`Failed to track ${eventName}`, { error });
|
|
76
|
+
}
|
|
77
|
+
}, [client, enabled, analyticsTags, contextOption]);
|
|
78
|
+
// Track suggestion click
|
|
79
|
+
const trackSuggestionClick = useCallback((data) => {
|
|
80
|
+
if (!trackClicks)
|
|
81
|
+
return;
|
|
82
|
+
sendEvent(EVENTS.SUGGESTION_CLICK, {
|
|
83
|
+
suggestion_query: data.suggestion.query,
|
|
84
|
+
suggestion_id: data.suggestion.objectID,
|
|
85
|
+
suggestion_popularity: data.suggestion.popularity,
|
|
86
|
+
position: data.position,
|
|
87
|
+
section: data.section || 'suggestions',
|
|
88
|
+
original_query: data.query,
|
|
89
|
+
total_suggestions: data.totalSuggestions,
|
|
90
|
+
});
|
|
91
|
+
}, [sendEvent, trackClicks]);
|
|
92
|
+
// Track product click
|
|
93
|
+
const trackProductClick = useCallback((data) => {
|
|
94
|
+
if (!trackClicks)
|
|
95
|
+
return;
|
|
96
|
+
sendEvent(EVENTS.PRODUCT_CLICK, {
|
|
97
|
+
product_id: data.product.id || data.product.objectID,
|
|
98
|
+
product_title: data.product.title || data.product.name,
|
|
99
|
+
product_price: data.product.price,
|
|
100
|
+
position: data.position,
|
|
101
|
+
section: data.section || 'products',
|
|
102
|
+
tab_id: data.tabId,
|
|
103
|
+
original_query: data.query,
|
|
104
|
+
});
|
|
105
|
+
// Also track as a general product click for analytics (with context when available)
|
|
106
|
+
const searchContext = contextOption;
|
|
107
|
+
if (client?.trackClick) {
|
|
108
|
+
Promise.resolve(client.trackClick(data.product.id || data.product.objectID || '', data.position + 1, searchContext)).catch(() => { });
|
|
109
|
+
}
|
|
110
|
+
}, [client, contextOption, sendEvent, trackClicks]);
|
|
111
|
+
// Track category click
|
|
112
|
+
const trackCategoryClick = useCallback((category, query) => {
|
|
113
|
+
if (!trackClicks)
|
|
114
|
+
return;
|
|
115
|
+
sendEvent(EVENTS.CATEGORY_CLICK, {
|
|
116
|
+
category_value: category.value,
|
|
117
|
+
category_count: category.count,
|
|
118
|
+
category_path: category.path,
|
|
119
|
+
original_query: query,
|
|
120
|
+
});
|
|
121
|
+
}, [sendEvent, trackClicks]);
|
|
122
|
+
// Track brand click
|
|
123
|
+
const trackBrandClick = useCallback((brand, query) => {
|
|
124
|
+
if (!trackClicks)
|
|
125
|
+
return;
|
|
126
|
+
sendEvent(EVENTS.BRAND_CLICK, {
|
|
127
|
+
brand_name: brand.name,
|
|
128
|
+
brand_count: brand.count,
|
|
129
|
+
original_query: query,
|
|
130
|
+
});
|
|
131
|
+
}, [sendEvent, trackClicks]);
|
|
132
|
+
// Track tab selection
|
|
133
|
+
const trackTabSelect = useCallback((tab, query) => {
|
|
134
|
+
sendEvent(EVENTS.TAB_SELECT, {
|
|
135
|
+
tab_id: tab.id,
|
|
136
|
+
tab_label: tab.label,
|
|
137
|
+
tab_filter: tab.filter,
|
|
138
|
+
products_count: tab.products?.length || 0,
|
|
139
|
+
nb_hits: tab.nb_hits,
|
|
140
|
+
original_query: query,
|
|
141
|
+
});
|
|
142
|
+
}, [sendEvent]);
|
|
143
|
+
// Track recent search click
|
|
144
|
+
const trackRecentSearchClick = useCallback((search) => {
|
|
145
|
+
if (!trackClicks)
|
|
146
|
+
return;
|
|
147
|
+
sendEvent(EVENTS.RECENT_CLICK, {
|
|
148
|
+
query: search.query,
|
|
149
|
+
original_timestamp: search.timestamp,
|
|
150
|
+
results_count: search.resultsCount,
|
|
151
|
+
});
|
|
152
|
+
}, [sendEvent, trackClicks]);
|
|
153
|
+
// Track trending click
|
|
154
|
+
const trackTrendingClick = useCallback((trending, position) => {
|
|
155
|
+
if (!trackClicks)
|
|
156
|
+
return;
|
|
157
|
+
sendEvent(EVENTS.TRENDING_CLICK, {
|
|
158
|
+
query: trending.query,
|
|
159
|
+
count: trending.count,
|
|
160
|
+
trend_score: trending.trend_score,
|
|
161
|
+
position,
|
|
162
|
+
});
|
|
163
|
+
}, [sendEvent, trackClicks]);
|
|
164
|
+
// Track impression (debounced)
|
|
165
|
+
const trackImpression = useCallback((data) => {
|
|
166
|
+
if (!trackImpressions)
|
|
167
|
+
return;
|
|
168
|
+
// Create a hash of the impression to avoid duplicates
|
|
169
|
+
const impressionHash = `${data.query}:${data.suggestions.length}:${data.products?.length || 0}`;
|
|
170
|
+
if (impressionHash === lastImpressionRef.current)
|
|
171
|
+
return;
|
|
172
|
+
// Clear existing timer
|
|
173
|
+
if (impressionTimerRef.current) {
|
|
174
|
+
clearTimeout(impressionTimerRef.current);
|
|
175
|
+
}
|
|
176
|
+
// Debounce the impression
|
|
177
|
+
impressionTimerRef.current = setTimeout(() => {
|
|
178
|
+
lastImpressionRef.current = impressionHash;
|
|
179
|
+
sendEvent(EVENTS.SUGGESTION_IMPRESSION, {
|
|
180
|
+
query: data.query,
|
|
181
|
+
suggestions_count: data.suggestions.length,
|
|
182
|
+
suggestions: data.suggestions.slice(0, 10).map((s, i) => ({
|
|
183
|
+
query: s.query,
|
|
184
|
+
position: i,
|
|
185
|
+
popularity: s.popularity,
|
|
186
|
+
})),
|
|
187
|
+
products_count: data.products?.length || 0,
|
|
188
|
+
categories_count: data.categories?.length || 0,
|
|
189
|
+
brands_count: data.brands?.length || 0,
|
|
190
|
+
impression_timestamp: data.timestamp,
|
|
191
|
+
});
|
|
192
|
+
}, impressionDebounce);
|
|
193
|
+
}, [sendEvent, trackImpressions, impressionDebounce]);
|
|
194
|
+
// Track search submit
|
|
195
|
+
const trackSearchSubmit = useCallback((query, fromSuggestion, suggestion) => {
|
|
196
|
+
sendEvent(EVENTS.SEARCH_SUBMIT, {
|
|
197
|
+
query,
|
|
198
|
+
from_suggestion: fromSuggestion,
|
|
199
|
+
suggestion_query: suggestion?.query,
|
|
200
|
+
suggestion_id: suggestion?.objectID,
|
|
201
|
+
suggestion_popularity: suggestion?.popularity,
|
|
202
|
+
});
|
|
203
|
+
}, [sendEvent]);
|
|
204
|
+
// Track dropdown open
|
|
205
|
+
const trackDropdownOpen = useCallback((query) => {
|
|
206
|
+
dropdownOpenTimeRef.current = Date.now();
|
|
207
|
+
sendEvent(EVENTS.DROPDOWN_OPEN, {
|
|
208
|
+
query,
|
|
209
|
+
has_query: query.length > 0,
|
|
210
|
+
});
|
|
211
|
+
}, [sendEvent]);
|
|
212
|
+
// Track dropdown close
|
|
213
|
+
const trackDropdownClose = useCallback((query, selectedSuggestion) => {
|
|
214
|
+
const duration = dropdownOpenTimeRef.current
|
|
215
|
+
? Date.now() - dropdownOpenTimeRef.current
|
|
216
|
+
: null;
|
|
217
|
+
sendEvent(EVENTS.DROPDOWN_CLOSE, {
|
|
218
|
+
query,
|
|
219
|
+
selected_suggestion: selectedSuggestion,
|
|
220
|
+
had_selection: !!selectedSuggestion,
|
|
221
|
+
duration_ms: duration,
|
|
222
|
+
});
|
|
223
|
+
dropdownOpenTimeRef.current = null;
|
|
224
|
+
}, [sendEvent]);
|
|
225
|
+
return {
|
|
226
|
+
trackSuggestionClick,
|
|
227
|
+
trackProductClick,
|
|
228
|
+
trackCategoryClick,
|
|
229
|
+
trackBrandClick,
|
|
230
|
+
trackTabSelect,
|
|
231
|
+
trackRecentSearchClick,
|
|
232
|
+
trackTrendingClick,
|
|
233
|
+
trackImpression,
|
|
234
|
+
trackSearchSubmit,
|
|
235
|
+
trackDropdownOpen,
|
|
236
|
+
trackDropdownClose,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
export default useSuggestionsAnalytics;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useVariantSelection – manages variant selection state
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for variant interactions on product pages.
|
|
5
|
+
* Cards display variants passively; product pages use this hook.
|
|
6
|
+
*/
|
|
7
|
+
import type { ProductOption, ProductVariant } from '@seekora-ai/ui-sdk-types';
|
|
8
|
+
export interface UseVariantSelectionOptions {
|
|
9
|
+
options?: ProductOption[];
|
|
10
|
+
variants?: ProductVariant[];
|
|
11
|
+
initialSelections?: Record<string, string>;
|
|
12
|
+
onVariantChange?: (variant: ProductVariant | null, selections: Record<string, string>) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface UseVariantSelectionReturn {
|
|
15
|
+
selections: Record<string, string>;
|
|
16
|
+
setSelection: (optionName: string, value: string) => void;
|
|
17
|
+
resetSelections: () => void;
|
|
18
|
+
selectedVariant: ProductVariant | null;
|
|
19
|
+
availableValues: Record<string, {
|
|
20
|
+
value: string;
|
|
21
|
+
available: boolean;
|
|
22
|
+
}[]>;
|
|
23
|
+
isComplete: boolean;
|
|
24
|
+
effectivePrice: number | null;
|
|
25
|
+
effectiveComparePrice: number | null;
|
|
26
|
+
}
|
|
27
|
+
export declare function useVariantSelection({ options, variants, initialSelections, onVariantChange, }?: UseVariantSelectionOptions): UseVariantSelectionReturn;
|
|
28
|
+
//# sourceMappingURL=useVariantSelection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useVariantSelection.d.ts","sourceRoot":"","sources":["../../src/hooks/useVariantSelection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG9E,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CAChG;AAED,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,EAAE,cAAc,GAAG,IAAI,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC,CAAC;IACzE,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,OAAY,EACZ,QAAa,EACb,iBAAsB,EACtB,eAAe,GAChB,GAAE,0BAA+B,GAAG,yBAAyB,CAwD7D"}
|