@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,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useNaturalLanguageFilters Hook
|
|
3
|
+
*
|
|
4
|
+
* Convert natural language queries to structured filters
|
|
5
|
+
* Examples:
|
|
6
|
+
* - "red shirts under $50" → color: red, category: shirts, price: <= 50
|
|
7
|
+
* - "size large blue jeans" → size: L, color: blue, category: jeans
|
|
8
|
+
*/
|
|
9
|
+
export interface ParsedFilter {
|
|
10
|
+
field: string;
|
|
11
|
+
value: string;
|
|
12
|
+
operator: '=' | '>' | '<' | '>=' | '<=' | 'contains';
|
|
13
|
+
confidence: number;
|
|
14
|
+
matchedText: string;
|
|
15
|
+
}
|
|
16
|
+
export interface NaturalLanguageResult {
|
|
17
|
+
/** Cleaned query with filter terms removed */
|
|
18
|
+
cleanedQuery: string;
|
|
19
|
+
/** Extracted filters */
|
|
20
|
+
filters: ParsedFilter[];
|
|
21
|
+
/** Original query */
|
|
22
|
+
originalQuery: string;
|
|
23
|
+
/** Whether any filters were detected */
|
|
24
|
+
hasFilters: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface NaturalLanguageFiltersOptions {
|
|
27
|
+
/** Custom field mappings */
|
|
28
|
+
fieldMappings?: Record<string, string>;
|
|
29
|
+
/** Custom value mappings */
|
|
30
|
+
valueMappings?: Record<string, Record<string, string>>;
|
|
31
|
+
/** Whether to auto-apply filters to search state */
|
|
32
|
+
autoApply?: boolean;
|
|
33
|
+
/** Currency symbol for price parsing */
|
|
34
|
+
currencySymbol?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function useNaturalLanguageFilters(options?: NaturalLanguageFiltersOptions): {
|
|
37
|
+
/** Parse a natural language query */
|
|
38
|
+
parse: (query: string) => NaturalLanguageResult;
|
|
39
|
+
/** Apply parsed filters to search state */
|
|
40
|
+
applyFilters: (filters: ParsedFilter[]) => void;
|
|
41
|
+
/** Parse and apply in one step */
|
|
42
|
+
parseAndApply: (query: string) => NaturalLanguageResult;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Utility to format parsed filters for display
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatParsedFilters(filters: ParsedFilter[]): string;
|
|
48
|
+
//# sourceMappingURL=useNaturalLanguageFilters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNaturalLanguageFilters.d.ts","sourceRoot":"","sources":["../../src/hooks/useNaturalLanguageFilters.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,UAAU,CAAC;IACrD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,qBAAqB;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,wCAAwC;IACxC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,4BAA4B;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAsDD,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,6BAAkC,GAC1C;IACD,qCAAqC;IACrC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,qBAAqB,CAAC;IAChD,2CAA2C;IAC3C,YAAY,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;IAChD,kCAAkC;IAClC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,qBAAqB,CAAC;CACzD,CA8KA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAInE"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useNaturalLanguageFilters Hook
|
|
3
|
+
*
|
|
4
|
+
* Convert natural language queries to structured filters
|
|
5
|
+
* Examples:
|
|
6
|
+
* - "red shirts under $50" → color: red, category: shirts, price: <= 50
|
|
7
|
+
* - "size large blue jeans" → size: L, color: blue, category: jeans
|
|
8
|
+
*/
|
|
9
|
+
import { useMemo, useCallback } from 'react';
|
|
10
|
+
import { useSearchState } from './useSearchState';
|
|
11
|
+
// Default patterns for parsing natural language
|
|
12
|
+
const DEFAULT_PATTERNS = {
|
|
13
|
+
// Price patterns
|
|
14
|
+
price: [
|
|
15
|
+
{ pattern: /under\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
|
|
16
|
+
{ pattern: /less than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<', field: 'price' },
|
|
17
|
+
{ pattern: /over\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>=', field: 'price' },
|
|
18
|
+
{ pattern: /more than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>', field: 'price' },
|
|
19
|
+
{ pattern: /\$(\d+(?:\.\d{2})?)\s*-\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
|
|
20
|
+
{ pattern: /between\s*\$?(\d+(?:\.\d{2})?)\s*and\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
|
|
21
|
+
{ pattern: /\$(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
|
|
22
|
+
],
|
|
23
|
+
// Color patterns
|
|
24
|
+
colors: ['red', 'blue', 'green', 'black', 'white', 'pink', 'purple', 'yellow', 'orange', 'brown', 'gray', 'grey', 'navy', 'beige', 'gold', 'silver'],
|
|
25
|
+
// Size patterns
|
|
26
|
+
sizes: {
|
|
27
|
+
'extra small': 'XS',
|
|
28
|
+
'xs': 'XS',
|
|
29
|
+
'small': 'S',
|
|
30
|
+
's': 'S',
|
|
31
|
+
'medium': 'M',
|
|
32
|
+
'm': 'M',
|
|
33
|
+
'large': 'L',
|
|
34
|
+
'l': 'L',
|
|
35
|
+
'extra large': 'XL',
|
|
36
|
+
'xl': 'XL',
|
|
37
|
+
'xxl': 'XXL',
|
|
38
|
+
'2xl': 'XXL',
|
|
39
|
+
'xxxl': 'XXXL',
|
|
40
|
+
'3xl': 'XXXL',
|
|
41
|
+
},
|
|
42
|
+
// Brand patterns (common examples)
|
|
43
|
+
brandIndicators: ['by', 'from', 'brand'],
|
|
44
|
+
// Rating patterns
|
|
45
|
+
ratings: [
|
|
46
|
+
{ pattern: /(\d+)\s*\+?\s*stars?/i, field: 'rating', operator: '>=' },
|
|
47
|
+
{ pattern: /rated\s*(\d+)/i, field: 'rating', operator: '>=' },
|
|
48
|
+
{ pattern: /top\s*rated/i, field: 'rating', value: '4', operator: '>=' },
|
|
49
|
+
],
|
|
50
|
+
// Availability patterns
|
|
51
|
+
availability: [
|
|
52
|
+
{ pattern: /in\s*stock/i, field: 'inStock', value: 'true' },
|
|
53
|
+
{ pattern: /available/i, field: 'inStock', value: 'true' },
|
|
54
|
+
{ pattern: /on\s*sale/i, field: 'onSale', value: 'true' },
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
export function useNaturalLanguageFilters(options = {}) {
|
|
58
|
+
const { fieldMappings = {}, valueMappings = {}, autoApply = false, currencySymbol = '$', } = options;
|
|
59
|
+
const { addRefinement, removeRefinement, clearRefinements, setQuery } = useSearchState();
|
|
60
|
+
// Merge default patterns with custom mappings
|
|
61
|
+
const patterns = useMemo(() => ({
|
|
62
|
+
...DEFAULT_PATTERNS,
|
|
63
|
+
colors: [...DEFAULT_PATTERNS.colors, ...(valueMappings.color ? Object.keys(valueMappings.color) : [])],
|
|
64
|
+
sizes: { ...DEFAULT_PATTERNS.sizes, ...(valueMappings.size || {}) },
|
|
65
|
+
}), [valueMappings]);
|
|
66
|
+
const parse = useCallback((query) => {
|
|
67
|
+
const filters = [];
|
|
68
|
+
let cleanedQuery = query;
|
|
69
|
+
// Parse price filters
|
|
70
|
+
for (const pricePattern of patterns.price) {
|
|
71
|
+
const match = query.match(pricePattern.pattern);
|
|
72
|
+
if (match) {
|
|
73
|
+
if (pricePattern.operator === 'range' && match[2]) {
|
|
74
|
+
// Handle price range
|
|
75
|
+
filters.push({
|
|
76
|
+
field: fieldMappings.price || 'price',
|
|
77
|
+
value: `>=${match[1]}`,
|
|
78
|
+
operator: '>=',
|
|
79
|
+
confidence: 0.95,
|
|
80
|
+
matchedText: match[0],
|
|
81
|
+
});
|
|
82
|
+
filters.push({
|
|
83
|
+
field: fieldMappings.price || 'price',
|
|
84
|
+
value: `<=${match[2]}`,
|
|
85
|
+
operator: '<=',
|
|
86
|
+
confidence: 0.95,
|
|
87
|
+
matchedText: match[0],
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (match[1]) {
|
|
91
|
+
filters.push({
|
|
92
|
+
field: fieldMappings.price || 'price',
|
|
93
|
+
value: `${pricePattern.operator}${match[1]}`,
|
|
94
|
+
operator: pricePattern.operator,
|
|
95
|
+
confidence: 0.95,
|
|
96
|
+
matchedText: match[0],
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
cleanedQuery = cleanedQuery.replace(match[0], ' ');
|
|
100
|
+
break; // Only match first price pattern
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Parse colors
|
|
104
|
+
const colorRegex = new RegExp(`\\b(${patterns.colors.join('|')})\\b`, 'gi');
|
|
105
|
+
const colorMatches = query.match(colorRegex);
|
|
106
|
+
if (colorMatches) {
|
|
107
|
+
colorMatches.forEach(color => {
|
|
108
|
+
const normalizedColor = valueMappings.color?.[color.toLowerCase()] || color.toLowerCase();
|
|
109
|
+
filters.push({
|
|
110
|
+
field: fieldMappings.color || 'color',
|
|
111
|
+
value: normalizedColor,
|
|
112
|
+
operator: '=',
|
|
113
|
+
confidence: 0.9,
|
|
114
|
+
matchedText: color,
|
|
115
|
+
});
|
|
116
|
+
cleanedQuery = cleanedQuery.replace(new RegExp(`\\b${color}\\b`, 'gi'), ' ');
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// Parse sizes
|
|
120
|
+
const sizeEntries = Object.entries(patterns.sizes);
|
|
121
|
+
for (const [sizeText, sizeValue] of sizeEntries) {
|
|
122
|
+
const sizeRegex = new RegExp(`\\b${sizeText}\\b`, 'gi');
|
|
123
|
+
if (sizeRegex.test(query)) {
|
|
124
|
+
filters.push({
|
|
125
|
+
field: fieldMappings.size || 'size',
|
|
126
|
+
value: sizeValue,
|
|
127
|
+
operator: '=',
|
|
128
|
+
confidence: 0.85,
|
|
129
|
+
matchedText: sizeText,
|
|
130
|
+
});
|
|
131
|
+
cleanedQuery = cleanedQuery.replace(sizeRegex, ' ');
|
|
132
|
+
break; // Only match first size
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Parse ratings
|
|
136
|
+
for (const ratingPattern of patterns.ratings) {
|
|
137
|
+
if ('value' in ratingPattern) {
|
|
138
|
+
if (ratingPattern.pattern.test(query)) {
|
|
139
|
+
filters.push({
|
|
140
|
+
field: fieldMappings.rating || ratingPattern.field,
|
|
141
|
+
value: `${ratingPattern.operator}${ratingPattern.value}`,
|
|
142
|
+
operator: ratingPattern.operator,
|
|
143
|
+
confidence: 0.8,
|
|
144
|
+
matchedText: query.match(ratingPattern.pattern)?.[0] || '',
|
|
145
|
+
});
|
|
146
|
+
cleanedQuery = cleanedQuery.replace(ratingPattern.pattern, ' ');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
const match = query.match(ratingPattern.pattern);
|
|
151
|
+
if (match && match[1]) {
|
|
152
|
+
filters.push({
|
|
153
|
+
field: fieldMappings.rating || ratingPattern.field,
|
|
154
|
+
value: `${ratingPattern.operator}${match[1]}`,
|
|
155
|
+
operator: ratingPattern.operator,
|
|
156
|
+
confidence: 0.85,
|
|
157
|
+
matchedText: match[0],
|
|
158
|
+
});
|
|
159
|
+
cleanedQuery = cleanedQuery.replace(match[0], ' ');
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Parse availability
|
|
164
|
+
for (const availPattern of patterns.availability) {
|
|
165
|
+
if (availPattern.pattern.test(query)) {
|
|
166
|
+
filters.push({
|
|
167
|
+
field: fieldMappings[availPattern.field] || availPattern.field,
|
|
168
|
+
value: availPattern.value,
|
|
169
|
+
operator: '=',
|
|
170
|
+
confidence: 0.9,
|
|
171
|
+
matchedText: query.match(availPattern.pattern)?.[0] || '',
|
|
172
|
+
});
|
|
173
|
+
cleanedQuery = cleanedQuery.replace(availPattern.pattern, ' ');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Clean up the query
|
|
177
|
+
cleanedQuery = cleanedQuery
|
|
178
|
+
.replace(/\s+/g, ' ')
|
|
179
|
+
.trim();
|
|
180
|
+
return {
|
|
181
|
+
cleanedQuery,
|
|
182
|
+
filters,
|
|
183
|
+
originalQuery: query,
|
|
184
|
+
hasFilters: filters.length > 0,
|
|
185
|
+
};
|
|
186
|
+
}, [patterns, fieldMappings, valueMappings]);
|
|
187
|
+
const applyFilters = useCallback((filters) => {
|
|
188
|
+
filters.forEach(filter => {
|
|
189
|
+
addRefinement(filter.field, filter.value, false);
|
|
190
|
+
});
|
|
191
|
+
// Trigger search after all filters are added
|
|
192
|
+
if (filters.length > 0) {
|
|
193
|
+
// The last addRefinement with triggerSearch=true would be called
|
|
194
|
+
// But we add them all with false and rely on the query change to trigger
|
|
195
|
+
}
|
|
196
|
+
}, [addRefinement]);
|
|
197
|
+
const parseAndApply = useCallback((query) => {
|
|
198
|
+
const result = parse(query);
|
|
199
|
+
if (result.hasFilters) {
|
|
200
|
+
applyFilters(result.filters);
|
|
201
|
+
// Update the query to the cleaned version
|
|
202
|
+
if (result.cleanedQuery !== query) {
|
|
203
|
+
setQuery(result.cleanedQuery, true);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}, [parse, applyFilters, setQuery]);
|
|
208
|
+
return {
|
|
209
|
+
parse,
|
|
210
|
+
applyFilters,
|
|
211
|
+
parseAndApply,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Utility to format parsed filters for display
|
|
216
|
+
*/
|
|
217
|
+
export function formatParsedFilters(filters) {
|
|
218
|
+
return filters
|
|
219
|
+
.map(f => `${f.field}: ${f.value}`)
|
|
220
|
+
.join(', ');
|
|
221
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useProductAnalytics – analytics event binding hook for custom components
|
|
3
|
+
*
|
|
4
|
+
* Returns event handler props ready to spread onto any element, plus imperative
|
|
5
|
+
* tracking methods. Builds on existing useAnalytics infrastructure.
|
|
6
|
+
*/
|
|
7
|
+
import type { SeekoraClient, SearchContext } from '@seekora-ai/search-sdk';
|
|
8
|
+
import type { ProductItem, ProductVariant } from '@seekora-ai/ui-sdk-types';
|
|
9
|
+
export interface UseProductAnalyticsOptions {
|
|
10
|
+
client: SeekoraClient;
|
|
11
|
+
product: ProductItem;
|
|
12
|
+
position?: number;
|
|
13
|
+
section?: string;
|
|
14
|
+
tabId?: string;
|
|
15
|
+
query?: string;
|
|
16
|
+
context?: SearchContext | Partial<SearchContext>;
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface UseProductAnalyticsReturn {
|
|
20
|
+
/** Spread onto any clickable element to track product click */
|
|
21
|
+
clickProps: {
|
|
22
|
+
onClick: (e?: React.MouseEvent) => void;
|
|
23
|
+
'data-seekora-product-id': string;
|
|
24
|
+
'data-seekora-position': number;
|
|
25
|
+
};
|
|
26
|
+
/** Spread onto any element to track variant selection */
|
|
27
|
+
variantSelectProps: (optionName: string, value: string) => {
|
|
28
|
+
onClick: (e?: React.MouseEvent) => void;
|
|
29
|
+
'data-seekora-variant-option': string;
|
|
30
|
+
'data-seekora-variant-value': string;
|
|
31
|
+
};
|
|
32
|
+
/** Spread onto any element to track add-to-cart */
|
|
33
|
+
addToCartProps: (variant?: ProductVariant) => {
|
|
34
|
+
onClick: (e?: React.MouseEvent) => void;
|
|
35
|
+
'data-seekora-action': 'add-to-cart';
|
|
36
|
+
};
|
|
37
|
+
/** Spread onto any element to track impression (uses IntersectionObserver) */
|
|
38
|
+
impressionRef: React.RefCallback<HTMLElement>;
|
|
39
|
+
/** Imperative: track product click */
|
|
40
|
+
trackClick: () => void;
|
|
41
|
+
/** Imperative: track variant select */
|
|
42
|
+
trackVariantSelect: (optionName: string, value: string) => void;
|
|
43
|
+
/** Imperative: track add to cart */
|
|
44
|
+
trackAddToCart: (variant?: ProductVariant) => void;
|
|
45
|
+
/** Imperative: track custom event with product context */
|
|
46
|
+
trackCustomEvent: (eventName: string, metadata?: Record<string, any>) => void;
|
|
47
|
+
}
|
|
48
|
+
export declare function useProductAnalytics({ client, product, position, section, tabId, query, context, enabled, }: UseProductAnalyticsOptions): UseProductAnalyticsReturn;
|
|
49
|
+
//# sourceMappingURL=useProductAnalytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProductAnalytics.d.ts","sourceRoot":"","sources":["../../src/hooks/useProductAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG5E,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,+DAA+D;IAC/D,UAAU,EAAE;QACV,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;QACxC,yBAAyB,EAAE,MAAM,CAAC;QAClC,uBAAuB,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,yDAAyD;IACzD,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK;QACzD,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;QACxC,6BAA6B,EAAE,MAAM,CAAC;QACtC,4BAA4B,EAAE,MAAM,CAAC;KACtC,CAAC;IACF,mDAAmD;IACnD,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK;QAC5C,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;QACxC,qBAAqB,EAAE,aAAa,CAAC;KACtC,CAAC;IACF,8EAA8E;IAC9E,aAAa,EAAE,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAC9C,sCAAsC;IACtC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,uCAAuC;IACvC,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,oCAAoC;IACpC,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,0DAA0D;IAC1D,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;CAC/E;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,OAAO,EACP,QAAY,EACZ,OAAO,EACP,KAAK,EACL,KAAK,EACL,OAAO,EACP,OAAc,GACf,EAAE,0BAA0B,GAAG,yBAAyB,CAyIxD"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useProductAnalytics – analytics event binding hook for custom components
|
|
3
|
+
*
|
|
4
|
+
* Returns event handler props ready to spread onto any element, plus imperative
|
|
5
|
+
* tracking methods. Builds on existing useAnalytics infrastructure.
|
|
6
|
+
*/
|
|
7
|
+
import { useCallback, useRef, useEffect } from 'react';
|
|
8
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
9
|
+
export function useProductAnalytics({ client, product, position = 0, section, tabId, query, context, enabled = true, }) {
|
|
10
|
+
const impressionTrackedRef = useRef(false);
|
|
11
|
+
const observerRef = useRef(null);
|
|
12
|
+
const elementRef = useRef(null);
|
|
13
|
+
const productId = product.id || product.objectID || '';
|
|
14
|
+
const sendEvent = useCallback(async (eventName, metadata) => {
|
|
15
|
+
if (!enabled || !client)
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
await client.trackEvent?.({
|
|
19
|
+
event_name: eventName,
|
|
20
|
+
metadata: {
|
|
21
|
+
product_id: productId,
|
|
22
|
+
product_title: product.title || product.name,
|
|
23
|
+
product_price: product.price,
|
|
24
|
+
position,
|
|
25
|
+
section,
|
|
26
|
+
tab_id: tabId,
|
|
27
|
+
original_query: query,
|
|
28
|
+
timestamp: Date.now(),
|
|
29
|
+
source: 'product_analytics',
|
|
30
|
+
...metadata,
|
|
31
|
+
},
|
|
32
|
+
}, context);
|
|
33
|
+
log.verbose(`ProductAnalytics: ${eventName}`, metadata);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
log.warn(`Failed to track ${eventName}`, { error });
|
|
37
|
+
}
|
|
38
|
+
}, [client, enabled, productId, product, position, section, tabId, query, context]);
|
|
39
|
+
const trackClick = useCallback(() => {
|
|
40
|
+
sendEvent('product.click', {});
|
|
41
|
+
// Also fire via client.trackClick for V3 compat
|
|
42
|
+
if (client?.trackClick) {
|
|
43
|
+
Promise.resolve(client.trackClick(productId, position + 1, context)).catch(() => { });
|
|
44
|
+
}
|
|
45
|
+
}, [sendEvent, client, productId, position, context]);
|
|
46
|
+
const trackVariantSelect = useCallback((optionName, value) => {
|
|
47
|
+
sendEvent('product.variant_select', {
|
|
48
|
+
option_name: optionName,
|
|
49
|
+
option_value: value,
|
|
50
|
+
});
|
|
51
|
+
}, [sendEvent]);
|
|
52
|
+
const trackAddToCart = useCallback((variant) => {
|
|
53
|
+
sendEvent('product.add_to_cart', {
|
|
54
|
+
variant_id: variant?.id,
|
|
55
|
+
variant_sku: variant?.sku,
|
|
56
|
+
variant_title: variant?.title,
|
|
57
|
+
variant_price: variant?.price,
|
|
58
|
+
});
|
|
59
|
+
}, [sendEvent]);
|
|
60
|
+
const trackCustomEvent = useCallback((eventName, metadata) => {
|
|
61
|
+
sendEvent(eventName, metadata ?? {});
|
|
62
|
+
}, [sendEvent]);
|
|
63
|
+
// Impression tracking via IntersectionObserver
|
|
64
|
+
const impressionRef = useCallback((node) => {
|
|
65
|
+
// Cleanup previous observer
|
|
66
|
+
if (observerRef.current) {
|
|
67
|
+
observerRef.current.disconnect();
|
|
68
|
+
observerRef.current = null;
|
|
69
|
+
}
|
|
70
|
+
elementRef.current = node;
|
|
71
|
+
if (!node || !enabled || impressionTrackedRef.current)
|
|
72
|
+
return;
|
|
73
|
+
if (typeof IntersectionObserver === 'undefined')
|
|
74
|
+
return;
|
|
75
|
+
observerRef.current = new IntersectionObserver((entries) => {
|
|
76
|
+
for (const entry of entries) {
|
|
77
|
+
if (entry.isIntersecting && !impressionTrackedRef.current) {
|
|
78
|
+
impressionTrackedRef.current = true;
|
|
79
|
+
sendEvent('product.impression', {});
|
|
80
|
+
observerRef.current?.disconnect();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}, { threshold: 0.5 });
|
|
84
|
+
observerRef.current.observe(node);
|
|
85
|
+
}, [enabled, sendEvent]);
|
|
86
|
+
// Cleanup on unmount
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
return () => {
|
|
89
|
+
observerRef.current?.disconnect();
|
|
90
|
+
};
|
|
91
|
+
}, []);
|
|
92
|
+
const clickProps = {
|
|
93
|
+
onClick: () => trackClick(),
|
|
94
|
+
'data-seekora-product-id': productId,
|
|
95
|
+
'data-seekora-position': position,
|
|
96
|
+
};
|
|
97
|
+
const variantSelectProps = (optionName, value) => ({
|
|
98
|
+
onClick: () => trackVariantSelect(optionName, value),
|
|
99
|
+
'data-seekora-variant-option': optionName,
|
|
100
|
+
'data-seekora-variant-value': value,
|
|
101
|
+
});
|
|
102
|
+
const addToCartProps = (variant) => ({
|
|
103
|
+
onClick: () => trackAddToCart(variant),
|
|
104
|
+
'data-seekora-action': 'add-to-cart',
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
clickProps,
|
|
108
|
+
variantSelectProps,
|
|
109
|
+
addToCartProps,
|
|
110
|
+
impressionRef,
|
|
111
|
+
trackClick,
|
|
112
|
+
trackVariantSelect,
|
|
113
|
+
trackAddToCart,
|
|
114
|
+
trackCustomEvent,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useQuerySuggestions Hook
|
|
3
|
+
*
|
|
4
|
+
* Hook for fetching query suggestions with debouncing
|
|
5
|
+
*/
|
|
6
|
+
import type { SeekoraClient } from '@seekora-ai/search-sdk';
|
|
7
|
+
import type { SuggestionItem } from '../types';
|
|
8
|
+
export interface UseQuerySuggestionsOptions {
|
|
9
|
+
client: SeekoraClient;
|
|
10
|
+
query: string;
|
|
11
|
+
enabled?: boolean;
|
|
12
|
+
debounceMs?: number;
|
|
13
|
+
maxSuggestions?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface UseQuerySuggestionsReturn {
|
|
16
|
+
suggestions: SuggestionItem[];
|
|
17
|
+
loading: boolean;
|
|
18
|
+
error: Error | null;
|
|
19
|
+
}
|
|
20
|
+
export declare const useQuerySuggestions: ({ client, query, enabled, debounceMs, maxSuggestions, }: UseQuerySuggestionsOptions) => UseQuerySuggestionsReturn;
|
|
21
|
+
//# sourceMappingURL=useQuerySuggestions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/hooks/useQuerySuggestions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,mBAAmB,GAAI,yDAMjC,0BAA0B,KAAG,yBAuF/B,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useQuerySuggestions Hook
|
|
3
|
+
*
|
|
4
|
+
* Hook for fetching query suggestions with debouncing
|
|
5
|
+
*/
|
|
6
|
+
import { useState, useEffect, useRef } from 'react';
|
|
7
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
8
|
+
export const useQuerySuggestions = ({ client, query, enabled = true, debounceMs = 300, maxSuggestions = 10, }) => {
|
|
9
|
+
const [suggestions, setSuggestions] = useState([]);
|
|
10
|
+
const [loading, setLoading] = useState(false);
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
const debounceTimerRef = useRef(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
// Clear previous timer
|
|
15
|
+
if (debounceTimerRef.current) {
|
|
16
|
+
clearTimeout(debounceTimerRef.current);
|
|
17
|
+
}
|
|
18
|
+
if (!enabled || !query.trim()) {
|
|
19
|
+
setSuggestions([]);
|
|
20
|
+
setLoading(false);
|
|
21
|
+
setError(null);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
setLoading(true);
|
|
25
|
+
setError(null);
|
|
26
|
+
debounceTimerRef.current = setTimeout(async () => {
|
|
27
|
+
try {
|
|
28
|
+
const response = await client.getSuggestions?.(query, maxSuggestions);
|
|
29
|
+
// Transform suggestions to SuggestionItem format
|
|
30
|
+
// getSuggestions returns an array of suggestion objects with structure:
|
|
31
|
+
// { query: string, popularity: number, objectID: string, ... }
|
|
32
|
+
const rawSuggestions = Array.isArray(response) ? response : [];
|
|
33
|
+
const suggestionItems = rawSuggestions.map((suggestion) => {
|
|
34
|
+
// Extract query - it should be in suggestion.query
|
|
35
|
+
const suggestionQuery = suggestion.query || suggestion.text || suggestion;
|
|
36
|
+
// Extract count/popularity
|
|
37
|
+
const count = suggestion.popularity !== undefined ? suggestion.popularity : (suggestion.count !== undefined ? suggestion.count : undefined);
|
|
38
|
+
const item = {
|
|
39
|
+
query: typeof suggestionQuery === 'string' ? suggestionQuery : String(suggestionQuery),
|
|
40
|
+
count: typeof count === 'number' ? count : undefined,
|
|
41
|
+
metadata: suggestion,
|
|
42
|
+
};
|
|
43
|
+
return item;
|
|
44
|
+
});
|
|
45
|
+
setSuggestions(suggestionItems);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
49
|
+
// Check if it's a 404 error (suggestions not enabled for this store).
|
|
50
|
+
// The search SDK wraps axios errors into plain Error objects with the status
|
|
51
|
+
// embedded in the message, e.g. "[getSuggestions] ... (404)".
|
|
52
|
+
const errMsg = error.message || '';
|
|
53
|
+
const is404 = err?.response?.status === 404 ||
|
|
54
|
+
err?.status === 404 ||
|
|
55
|
+
/\(404\)/.test(errMsg);
|
|
56
|
+
if (is404) {
|
|
57
|
+
// Silently handle 404 - suggestions feature not enabled
|
|
58
|
+
log.verbose('Query suggestions not enabled for this store (404)');
|
|
59
|
+
setSuggestions([]);
|
|
60
|
+
setError(null);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// For other errors, log and set error state
|
|
64
|
+
log.error('Error in useQuerySuggestions:', error);
|
|
65
|
+
setError(error);
|
|
66
|
+
setSuggestions([]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
setLoading(false);
|
|
71
|
+
}
|
|
72
|
+
}, debounceMs);
|
|
73
|
+
return () => {
|
|
74
|
+
if (debounceTimerRef.current) {
|
|
75
|
+
clearTimeout(debounceTimerRef.current);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}, [client, query, enabled, debounceMs, maxSuggestions]);
|
|
79
|
+
return {
|
|
80
|
+
suggestions,
|
|
81
|
+
loading,
|
|
82
|
+
error,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Query Suggestions Hook
|
|
3
|
+
*
|
|
4
|
+
* Provides full support for query suggestions API including:
|
|
5
|
+
* - Basic suggestions
|
|
6
|
+
* - Dropdown recommendations (trending, top searches, related)
|
|
7
|
+
* - Filtered tabs with products
|
|
8
|
+
* - Recent searches (local storage)
|
|
9
|
+
* - Analytics tracking
|
|
10
|
+
*/
|
|
11
|
+
import type { SeekoraClient } from '@seekora-ai/search-sdk';
|
|
12
|
+
import type { SuggestionItem, ProductItem, FilteredTab, DropdownRecommendations, RecentSearch, QuerySuggestionsResponse, TrendingSearch, TopSearch, RelatedSearch, PopularBrand, SuggestionCategory } from '@seekora-ai/ui-sdk-types';
|
|
13
|
+
export interface UseQuerySuggestionsEnhancedOptions {
|
|
14
|
+
/** Seekora client instance */
|
|
15
|
+
client: SeekoraClient;
|
|
16
|
+
/** Current search query */
|
|
17
|
+
query: string;
|
|
18
|
+
/** Enable/disable the hook */
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
/** Prefetch initial (empty-query) data on mount even if not enabled yet */
|
|
21
|
+
prefetch?: boolean;
|
|
22
|
+
/** Debounce delay in ms */
|
|
23
|
+
debounceMs?: number;
|
|
24
|
+
/** Max suggestions to fetch */
|
|
25
|
+
maxSuggestions?: number;
|
|
26
|
+
/** Minimum query length to trigger search */
|
|
27
|
+
minQueryLength?: number;
|
|
28
|
+
/** Include dropdown recommendations (trending, products, etc.) */
|
|
29
|
+
includeDropdownRecommendations?: boolean;
|
|
30
|
+
/** When false, omit product hits list from dropdown (default true) */
|
|
31
|
+
includeDropdownProductList?: boolean;
|
|
32
|
+
/** When false, omit filtered_tabs from dropdown extensions (default true) */
|
|
33
|
+
includeFilteredTabs?: boolean;
|
|
34
|
+
/** Include categories in suggestions */
|
|
35
|
+
includeCategories?: boolean;
|
|
36
|
+
/** Include facets in suggestions */
|
|
37
|
+
includeFacets?: boolean;
|
|
38
|
+
/** Max categories per suggestion */
|
|
39
|
+
maxCategories?: number;
|
|
40
|
+
/** Max facets per suggestion */
|
|
41
|
+
maxFacets?: number;
|
|
42
|
+
/** Filtered tabs configuration */
|
|
43
|
+
filteredTabs?: Array<{
|
|
44
|
+
id?: string;
|
|
45
|
+
label: string;
|
|
46
|
+
filter: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** Minimum popularity threshold */
|
|
49
|
+
minPopularity?: number;
|
|
50
|
+
/** Time range for analytics data */
|
|
51
|
+
timeRange?: '7d' | '30d' | '90d';
|
|
52
|
+
/** Disable typo tolerance */
|
|
53
|
+
disableTypoTolerance?: boolean;
|
|
54
|
+
/** Analytics tags */
|
|
55
|
+
analyticsTags?: string[];
|
|
56
|
+
/** Enable recent searches from localStorage */
|
|
57
|
+
enableRecentSearches?: boolean;
|
|
58
|
+
/** Max recent searches to store */
|
|
59
|
+
maxRecentSearches?: number;
|
|
60
|
+
/** Local storage key for recent searches */
|
|
61
|
+
recentSearchesKey?: string;
|
|
62
|
+
/** Callback when suggestions are loaded */
|
|
63
|
+
onSuggestionsLoaded?: (response: QuerySuggestionsResponse) => void;
|
|
64
|
+
/** Callback on error */
|
|
65
|
+
onError?: (error: Error) => void;
|
|
66
|
+
}
|
|
67
|
+
export interface UseQuerySuggestionsEnhancedReturn {
|
|
68
|
+
/** Basic suggestion items */
|
|
69
|
+
suggestions: SuggestionItem[];
|
|
70
|
+
/** Loading state */
|
|
71
|
+
loading: boolean;
|
|
72
|
+
/** Error state */
|
|
73
|
+
error: Error | null;
|
|
74
|
+
/** Dropdown recommendations */
|
|
75
|
+
dropdownRecommendations: DropdownRecommendations | null;
|
|
76
|
+
/** Trending searches */
|
|
77
|
+
trendingSearches: TrendingSearch[];
|
|
78
|
+
/** Top searches */
|
|
79
|
+
topSearches: TopSearch[];
|
|
80
|
+
/** Related searches */
|
|
81
|
+
relatedSearches: RelatedSearch[];
|
|
82
|
+
/** Popular brands */
|
|
83
|
+
popularBrands: PopularBrand[];
|
|
84
|
+
/** Filtered tabs with products */
|
|
85
|
+
filteredTabs: FilteredTab[];
|
|
86
|
+
/** Trending products */
|
|
87
|
+
trendingProducts: ProductItem[];
|
|
88
|
+
/** Recent searches (from localStorage) */
|
|
89
|
+
recentSearches: RecentSearch[];
|
|
90
|
+
/** Processing time in ms */
|
|
91
|
+
processingTimeMs: number | null;
|
|
92
|
+
/** Total hits count */
|
|
93
|
+
totalHits: number;
|
|
94
|
+
/** Current page */
|
|
95
|
+
currentPage: number;
|
|
96
|
+
/** Total pages */
|
|
97
|
+
totalPages: number;
|
|
98
|
+
/** Original query */
|
|
99
|
+
originalQuery: string;
|
|
100
|
+
/** Add a search to recent searches */
|
|
101
|
+
addRecentSearch: (query: string, resultsCount?: number) => void;
|
|
102
|
+
/** Remove a search from recent searches */
|
|
103
|
+
removeRecentSearch: (query: string) => void;
|
|
104
|
+
/** Clear all recent searches */
|
|
105
|
+
clearRecentSearches: () => void;
|
|
106
|
+
/** Manually refetch suggestions */
|
|
107
|
+
refetch: () => Promise<void>;
|
|
108
|
+
/** Check if dropdown has any content to show */
|
|
109
|
+
hasContent: boolean;
|
|
110
|
+
/** Get all items for keyboard navigation (flattened) */
|
|
111
|
+
getAllNavigableItems: () => NavigableItem[];
|
|
112
|
+
}
|
|
113
|
+
export interface NavigableItem {
|
|
114
|
+
type: 'suggestion' | 'recent' | 'trending' | 'product' | 'category' | 'brand' | 'tab';
|
|
115
|
+
index: number;
|
|
116
|
+
data: SuggestionItem | RecentSearch | TrendingSearch | ProductItem | SuggestionCategory | PopularBrand | FilteredTab;
|
|
117
|
+
}
|
|
118
|
+
export declare function useQuerySuggestionsEnhanced(options: UseQuerySuggestionsEnhancedOptions): UseQuerySuggestionsEnhancedReturn;
|
|
119
|
+
export default useQuerySuggestionsEnhanced;
|
|
120
|
+
//# sourceMappingURL=useQuerySuggestionsEnhanced.d.ts.map
|