@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
|
+
* HierarchicalMenu Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a hierarchical menu for nested category navigation
|
|
5
|
+
* Example: Electronics > Phones > iPhone
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface HierarchicalMenuItem {
|
|
9
|
+
label: string;
|
|
10
|
+
value: string;
|
|
11
|
+
count?: number;
|
|
12
|
+
isRefined?: boolean;
|
|
13
|
+
data?: HierarchicalMenuItem[];
|
|
14
|
+
}
|
|
15
|
+
export interface HierarchicalMenuTheme {
|
|
16
|
+
root?: string;
|
|
17
|
+
list?: string;
|
|
18
|
+
item?: string;
|
|
19
|
+
itemSelected?: string;
|
|
20
|
+
itemParent?: string;
|
|
21
|
+
link?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
count?: string;
|
|
24
|
+
showMore?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface HierarchicalMenuProps {
|
|
27
|
+
/** Attributes for each level of hierarchy (e.g., ['category.lvl0', 'category.lvl1', 'category.lvl2']) */
|
|
28
|
+
attributes: string[];
|
|
29
|
+
/** Separator used in the hierarchical values (default: ' > ') */
|
|
30
|
+
separator?: string;
|
|
31
|
+
/** Maximum number of items to show per level (default: 10) */
|
|
32
|
+
limit?: number;
|
|
33
|
+
/** Show "Show more" button (default: true) */
|
|
34
|
+
showMore?: boolean;
|
|
35
|
+
/** Maximum items when "Show more" is clicked (default: 20) */
|
|
36
|
+
showMoreLimit?: number;
|
|
37
|
+
/** Custom render function for items */
|
|
38
|
+
renderItem?: (item: HierarchicalMenuItem, level: number) => React.ReactNode;
|
|
39
|
+
/** Callback when an item is selected */
|
|
40
|
+
onSelect?: (value: string, level: number) => void;
|
|
41
|
+
/** Custom className */
|
|
42
|
+
className?: string;
|
|
43
|
+
/** Custom styles */
|
|
44
|
+
style?: React.CSSProperties;
|
|
45
|
+
/** Custom theme */
|
|
46
|
+
theme?: HierarchicalMenuTheme;
|
|
47
|
+
/** Root path (for pre-selecting a category) */
|
|
48
|
+
rootPath?: string | null;
|
|
49
|
+
/** Sort by (default: 'name') */
|
|
50
|
+
sortBy?: 'name' | 'count' | 'isRefined';
|
|
51
|
+
/** Custom facet data (if not using StateManager) */
|
|
52
|
+
items?: HierarchicalMenuItem[];
|
|
53
|
+
}
|
|
54
|
+
export declare const HierarchicalMenu: React.FC<HierarchicalMenuProps>;
|
|
55
|
+
//# sourceMappingURL=HierarchicalMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HierarchicalMenu.d.ts","sourceRoot":"","sources":["../../src/components/HierarchicalMenu.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAiD,MAAM,OAAO,CAAC;AAKtE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,yGAAyG;IACzG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,qBAAqB,CAAC;IAC9B,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;IACxC,oDAAoD;IACpD,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAoW5D,CAAC"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HierarchicalMenu Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a hierarchical menu for nested category navigation
|
|
5
|
+
* Example: Electronics > Phones > iPhone
|
|
6
|
+
*/
|
|
7
|
+
import React, { useState, useMemo, useCallback, useRef } from 'react';
|
|
8
|
+
import { useSearchContext } from './SearchProvider';
|
|
9
|
+
import { useSearchState } from '../hooks/useSearchState';
|
|
10
|
+
import { clsx } from 'clsx';
|
|
11
|
+
export const HierarchicalMenu = ({ attributes, separator = ' > ', limit = 10, showMore = true, showMoreLimit = 20, renderItem, onSelect, className, style, theme: customTheme, rootPath = null, sortBy = 'name', items: itemsProp, }) => {
|
|
12
|
+
const { theme, stateManager } = useSearchContext();
|
|
13
|
+
const { results, refinements, addRefinement, removeRefinement } = useSearchState();
|
|
14
|
+
const hierarchicalTheme = customTheme || {};
|
|
15
|
+
const [expanded, setExpanded] = useState({});
|
|
16
|
+
// Get hierarchical facet data from results
|
|
17
|
+
const getHierarchicalData = useCallback(() => {
|
|
18
|
+
if (itemsProp)
|
|
19
|
+
return itemsProp;
|
|
20
|
+
if (!results)
|
|
21
|
+
return [];
|
|
22
|
+
// Try to find hierarchical facet data in various response formats
|
|
23
|
+
const facets = results.facets || results.facet_counts || {};
|
|
24
|
+
// Build hierarchy from flat facet data
|
|
25
|
+
const rootAttribute = attributes[0];
|
|
26
|
+
const rootFacet = facets[rootAttribute] || {};
|
|
27
|
+
const items = [];
|
|
28
|
+
Object.entries(rootFacet).forEach(([value, count]) => {
|
|
29
|
+
const isRefined = refinements.some(r => r.field === rootAttribute && r.value === value);
|
|
30
|
+
items.push({
|
|
31
|
+
label: value,
|
|
32
|
+
value,
|
|
33
|
+
count: count,
|
|
34
|
+
isRefined,
|
|
35
|
+
data: getChildItems(value, 1),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
return items;
|
|
39
|
+
}, [results, attributes, refinements, itemsProp]);
|
|
40
|
+
// Get child items for a parent value
|
|
41
|
+
const getChildItems = useCallback((parentValue, level) => {
|
|
42
|
+
if (level >= attributes.length)
|
|
43
|
+
return [];
|
|
44
|
+
if (!results)
|
|
45
|
+
return [];
|
|
46
|
+
const facets = results.facets || results.facet_counts || {};
|
|
47
|
+
const attribute = attributes[level];
|
|
48
|
+
const facet = facets[attribute] || {};
|
|
49
|
+
const items = [];
|
|
50
|
+
Object.entries(facet).forEach(([value, count]) => {
|
|
51
|
+
// Check if this item belongs to the parent
|
|
52
|
+
if (value.startsWith(parentValue + separator)) {
|
|
53
|
+
const label = value.replace(parentValue + separator, '').split(separator)[0];
|
|
54
|
+
const isRefined = refinements.some(r => r.field === attribute && r.value === value);
|
|
55
|
+
// Only add direct children
|
|
56
|
+
const remainingPath = value.replace(parentValue + separator, '');
|
|
57
|
+
if (!remainingPath.includes(separator)) {
|
|
58
|
+
items.push({
|
|
59
|
+
label,
|
|
60
|
+
value,
|
|
61
|
+
count: count,
|
|
62
|
+
isRefined,
|
|
63
|
+
data: getChildItems(value, level + 1),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return items;
|
|
69
|
+
}, [results, attributes, separator, refinements]);
|
|
70
|
+
// Get sorted and limited items
|
|
71
|
+
const processedItems = useMemo(() => {
|
|
72
|
+
let items = getHierarchicalData();
|
|
73
|
+
// Sort
|
|
74
|
+
items = [...items].sort((a, b) => {
|
|
75
|
+
if (sortBy === 'count') {
|
|
76
|
+
return (b.count || 0) - (a.count || 0);
|
|
77
|
+
}
|
|
78
|
+
if (sortBy === 'isRefined') {
|
|
79
|
+
if (a.isRefined && !b.isRefined)
|
|
80
|
+
return -1;
|
|
81
|
+
if (!a.isRefined && b.isRefined)
|
|
82
|
+
return 1;
|
|
83
|
+
}
|
|
84
|
+
return a.label.localeCompare(b.label);
|
|
85
|
+
});
|
|
86
|
+
return items;
|
|
87
|
+
}, [getHierarchicalData, sortBy]);
|
|
88
|
+
// Handle item click
|
|
89
|
+
const handleItemClick = useCallback((item, level) => {
|
|
90
|
+
const attribute = attributes[level] || attributes[0];
|
|
91
|
+
if (item.isRefined) {
|
|
92
|
+
// Remove this and all child refinements
|
|
93
|
+
attributes.slice(level).forEach((attr) => {
|
|
94
|
+
refinements
|
|
95
|
+
.filter(r => r.field === attr && r.value.startsWith(item.value))
|
|
96
|
+
.forEach(r => removeRefinement(r.field, r.value, false));
|
|
97
|
+
});
|
|
98
|
+
stateManager.search();
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Clear sibling refinements at this level
|
|
102
|
+
refinements
|
|
103
|
+
.filter(r => r.field === attribute && r.value !== item.value)
|
|
104
|
+
.forEach(r => removeRefinement(r.field, r.value, false));
|
|
105
|
+
// Add this refinement
|
|
106
|
+
addRefinement(attribute, item.value, true);
|
|
107
|
+
}
|
|
108
|
+
if (onSelect) {
|
|
109
|
+
onSelect(item.value, level);
|
|
110
|
+
}
|
|
111
|
+
}, [attributes, refinements, addRefinement, removeRefinement, stateManager, onSelect]);
|
|
112
|
+
// Toggle show more
|
|
113
|
+
const toggleShowMore = (level) => {
|
|
114
|
+
setExpanded(prev => ({ ...prev, [level]: !prev[level] }));
|
|
115
|
+
};
|
|
116
|
+
const containerRef = useRef(null);
|
|
117
|
+
// Collect all visible treeitem elements within the container
|
|
118
|
+
const getVisibleTreeItems = useCallback(() => {
|
|
119
|
+
if (!containerRef.current)
|
|
120
|
+
return [];
|
|
121
|
+
return Array.from(containerRef.current.querySelectorAll('[role="treeitem"]'));
|
|
122
|
+
}, []);
|
|
123
|
+
// Keyboard navigation handler for the tree
|
|
124
|
+
const handleKeyDown = useCallback((e) => {
|
|
125
|
+
const items = getVisibleTreeItems();
|
|
126
|
+
if (items.length === 0)
|
|
127
|
+
return;
|
|
128
|
+
const activeElement = document.activeElement;
|
|
129
|
+
// Find the treeitem that is or contains the active element
|
|
130
|
+
const currentItem = items.find(item => item === activeElement || item.contains(activeElement));
|
|
131
|
+
const currentIndex = currentItem ? items.indexOf(currentItem) : -1;
|
|
132
|
+
switch (e.key) {
|
|
133
|
+
case 'ArrowDown': {
|
|
134
|
+
e.preventDefault();
|
|
135
|
+
const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0;
|
|
136
|
+
const button = items[nextIndex].querySelector('button');
|
|
137
|
+
if (button)
|
|
138
|
+
button.focus();
|
|
139
|
+
else
|
|
140
|
+
items[nextIndex].focus();
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case 'ArrowUp': {
|
|
144
|
+
e.preventDefault();
|
|
145
|
+
const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1;
|
|
146
|
+
const button = items[prevIndex].querySelector('button');
|
|
147
|
+
if (button)
|
|
148
|
+
button.focus();
|
|
149
|
+
else
|
|
150
|
+
items[prevIndex].focus();
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case 'ArrowRight': {
|
|
154
|
+
if (!currentItem)
|
|
155
|
+
break;
|
|
156
|
+
const isExpanded = currentItem.getAttribute('aria-expanded');
|
|
157
|
+
if (isExpanded === 'false') {
|
|
158
|
+
// Expand (select) this item
|
|
159
|
+
e.preventDefault();
|
|
160
|
+
const button = currentItem.querySelector('button');
|
|
161
|
+
if (button)
|
|
162
|
+
button.click();
|
|
163
|
+
}
|
|
164
|
+
else if (isExpanded === 'true') {
|
|
165
|
+
// Move to first child
|
|
166
|
+
e.preventDefault();
|
|
167
|
+
const childList = currentItem.querySelector('[role="group"]');
|
|
168
|
+
if (childList) {
|
|
169
|
+
const firstChild = childList.querySelector('[role="treeitem"]');
|
|
170
|
+
if (firstChild) {
|
|
171
|
+
const button = firstChild.querySelector('button');
|
|
172
|
+
if (button)
|
|
173
|
+
button.focus();
|
|
174
|
+
else
|
|
175
|
+
firstChild.focus();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
case 'ArrowLeft': {
|
|
182
|
+
if (!currentItem)
|
|
183
|
+
break;
|
|
184
|
+
const isExpanded = currentItem.getAttribute('aria-expanded');
|
|
185
|
+
if (isExpanded === 'true') {
|
|
186
|
+
// Collapse this item
|
|
187
|
+
e.preventDefault();
|
|
188
|
+
const button = currentItem.querySelector('button');
|
|
189
|
+
if (button)
|
|
190
|
+
button.click();
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Move focus to parent treeitem
|
|
194
|
+
e.preventDefault();
|
|
195
|
+
const parentGroup = currentItem.closest('[role="group"]');
|
|
196
|
+
if (parentGroup) {
|
|
197
|
+
const parentItem = parentGroup.closest('[role="treeitem"]');
|
|
198
|
+
if (parentItem) {
|
|
199
|
+
const button = parentItem.querySelector(':scope > button');
|
|
200
|
+
if (button)
|
|
201
|
+
button.focus();
|
|
202
|
+
else
|
|
203
|
+
parentItem.focus();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 'Enter': {
|
|
210
|
+
if (!currentItem)
|
|
211
|
+
break;
|
|
212
|
+
e.preventDefault();
|
|
213
|
+
const button = currentItem.querySelector('button');
|
|
214
|
+
if (button)
|
|
215
|
+
button.click();
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
default:
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}, [getVisibleTreeItems]);
|
|
222
|
+
// Render a level of the hierarchy
|
|
223
|
+
const renderLevel = (items, level) => {
|
|
224
|
+
if (!items || items.length === 0)
|
|
225
|
+
return null;
|
|
226
|
+
const isExpanded = expanded[level] || false;
|
|
227
|
+
const displayLimit = isExpanded ? showMoreLimit : limit;
|
|
228
|
+
const displayItems = items.slice(0, displayLimit);
|
|
229
|
+
const hasMore = items.length > displayLimit;
|
|
230
|
+
return (React.createElement("ul", { role: level === 0 ? 'tree' : 'group', className: hierarchicalTheme.list, style: {
|
|
231
|
+
listStyle: 'none',
|
|
232
|
+
margin: 0,
|
|
233
|
+
padding: level > 0 ? `0 0 0 ${theme.spacing.medium}` : 0,
|
|
234
|
+
} },
|
|
235
|
+
displayItems.map((item, index) => (React.createElement("li", { key: item.value, role: "treeitem", ...(item.data && item.data.length > 0
|
|
236
|
+
? { 'aria-expanded': !!item.isRefined }
|
|
237
|
+
: {}), className: clsx(hierarchicalTheme.item, item.isRefined && hierarchicalTheme.itemSelected, item.data && item.data.length > 0 && hierarchicalTheme.itemParent), style: {
|
|
238
|
+
padding: `${theme.spacing.small} 0`,
|
|
239
|
+
} }, renderItem ? (renderItem(item, level)) : (React.createElement(React.Fragment, null,
|
|
240
|
+
React.createElement("button", { type: "button", onClick: () => handleItemClick(item, level), className: hierarchicalTheme.link, style: {
|
|
241
|
+
display: 'flex',
|
|
242
|
+
alignItems: 'center',
|
|
243
|
+
gap: theme.spacing.small,
|
|
244
|
+
width: '100%',
|
|
245
|
+
padding: 0,
|
|
246
|
+
background: 'none',
|
|
247
|
+
border: 'none',
|
|
248
|
+
cursor: 'pointer',
|
|
249
|
+
textAlign: 'left',
|
|
250
|
+
fontFamily: 'inherit',
|
|
251
|
+
fontSize: theme.typography.fontSize.small,
|
|
252
|
+
color: item.isRefined ? theme.colors.primary : theme.colors.text,
|
|
253
|
+
fontWeight: item.isRefined ? 600 : 400,
|
|
254
|
+
} },
|
|
255
|
+
React.createElement("span", { className: hierarchicalTheme.label, style: { flex: 1 } }, item.label),
|
|
256
|
+
item.count !== undefined && (React.createElement("span", { className: hierarchicalTheme.count, style: {
|
|
257
|
+
color: theme.colors.textSecondary,
|
|
258
|
+
fontSize: theme.typography.fontSize.small,
|
|
259
|
+
} }, item.count))),
|
|
260
|
+
item.isRefined && item.data && item.data.length > 0 && (renderLevel(item.data, level + 1))))))),
|
|
261
|
+
showMore && hasMore && (React.createElement("li", null,
|
|
262
|
+
React.createElement("button", { type: "button", onClick: () => toggleShowMore(level), className: hierarchicalTheme.showMore, style: {
|
|
263
|
+
padding: `${theme.spacing.small} 0`,
|
|
264
|
+
background: 'none',
|
|
265
|
+
border: 'none',
|
|
266
|
+
cursor: 'pointer',
|
|
267
|
+
fontSize: theme.typography.fontSize.small,
|
|
268
|
+
color: theme.colors.primary,
|
|
269
|
+
textDecoration: 'underline',
|
|
270
|
+
} }, isExpanded ? 'Show less' : `Show ${items.length - displayLimit} more`)))));
|
|
271
|
+
};
|
|
272
|
+
if (processedItems.length === 0) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
return (React.createElement("div", { ref: containerRef, className: clsx(hierarchicalTheme.root, className), style: style, tabIndex: 0, onKeyDown: handleKeyDown }, renderLevel(processedItems, 0)));
|
|
276
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Highlight Component
|
|
3
|
+
*
|
|
4
|
+
* Renders highlighted search result text with matching terms emphasized
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { HighlightPart } from '@seekora-ai/ui-sdk-core';
|
|
8
|
+
export interface HighlightTheme {
|
|
9
|
+
root?: string;
|
|
10
|
+
highlighted?: string;
|
|
11
|
+
nonHighlighted?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface HighlightProps {
|
|
14
|
+
/** The search hit containing highlight data */
|
|
15
|
+
hit: Record<string, any>;
|
|
16
|
+
/** The attribute to highlight */
|
|
17
|
+
attribute: string;
|
|
18
|
+
/** Custom className */
|
|
19
|
+
className?: string;
|
|
20
|
+
/** Custom styles */
|
|
21
|
+
style?: React.CSSProperties;
|
|
22
|
+
/** Custom theme */
|
|
23
|
+
theme?: HighlightTheme;
|
|
24
|
+
/** Tag name for root element (default: 'span') */
|
|
25
|
+
tagName?: keyof JSX.IntrinsicElements;
|
|
26
|
+
/** Custom render for highlighted parts */
|
|
27
|
+
renderHighlighted?: (part: HighlightPart, index: number) => React.ReactNode;
|
|
28
|
+
/** Custom render for non-highlighted parts */
|
|
29
|
+
renderNonHighlighted?: (part: HighlightPart, index: number) => React.ReactNode;
|
|
30
|
+
/** Fallback query for client-side highlighting (when server highlight not available) */
|
|
31
|
+
query?: string;
|
|
32
|
+
}
|
|
33
|
+
export declare const Highlight: React.FC<HighlightProps>;
|
|
34
|
+
/**
|
|
35
|
+
* Snippet Component
|
|
36
|
+
*
|
|
37
|
+
* Renders a truncated, highlighted excerpt from search results
|
|
38
|
+
*/
|
|
39
|
+
export interface SnippetTheme extends HighlightTheme {
|
|
40
|
+
ellipsis?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface SnippetProps extends Omit<HighlightProps, 'theme'> {
|
|
43
|
+
/** Maximum length of snippet (default: 100) */
|
|
44
|
+
maxLength?: number;
|
|
45
|
+
/** Ellipsis to use when truncating (default: '...') */
|
|
46
|
+
ellipsis?: string;
|
|
47
|
+
/** Custom theme */
|
|
48
|
+
theme?: SnippetTheme;
|
|
49
|
+
}
|
|
50
|
+
export declare const Snippet: React.FC<SnippetProps>;
|
|
51
|
+
//# sourceMappingURL=Highlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Highlight.d.ts","sourceRoot":"","sources":["../../src/components/Highlight.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,EAIL,aAAa,EACd,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC,iBAAiB,CAAC;IACtC,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC5E,8CAA8C;IAC9C,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC/E,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA8E9C,CAAC;AAEF;;;;GAIG;AAEH,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,cAAc,EAAE,OAAO,CAAC;IACjE,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,eAAO,MAAM,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA2G1C,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Highlight Component
|
|
3
|
+
*
|
|
4
|
+
* Renders highlighted search result text with matching terms emphasized
|
|
5
|
+
*/
|
|
6
|
+
import React, { useMemo } from 'react';
|
|
7
|
+
import { useSearchContext } from './SearchProvider';
|
|
8
|
+
import { getHighlightedValue, parseHighlightedParts, parseQueryHighlightParts, } from '@seekora-ai/ui-sdk-core';
|
|
9
|
+
export const Highlight = ({ hit, attribute, className, style, theme: customTheme, tagName: Tag = 'span', renderHighlighted, renderNonHighlighted, query, }) => {
|
|
10
|
+
const { theme } = useSearchContext();
|
|
11
|
+
const highlightTheme = customTheme || {};
|
|
12
|
+
// Get highlighted value from hit
|
|
13
|
+
const highlightedValue = useMemo(() => {
|
|
14
|
+
return getHighlightedValue({
|
|
15
|
+
hit,
|
|
16
|
+
attribute,
|
|
17
|
+
preTag: '<mark>',
|
|
18
|
+
postTag: '</mark>',
|
|
19
|
+
});
|
|
20
|
+
}, [hit, attribute]);
|
|
21
|
+
// Parse into parts
|
|
22
|
+
const parts = useMemo(() => {
|
|
23
|
+
// First try server-provided highlights
|
|
24
|
+
const serverParts = parseHighlightedParts(highlightedValue, '<mark>', '</mark>');
|
|
25
|
+
// If no highlights found and we have a query, do client-side highlighting
|
|
26
|
+
if (serverParts.every((p) => !p.isHighlighted) && query) {
|
|
27
|
+
const plainValue = hit[attribute] || highlightedValue;
|
|
28
|
+
return parseQueryHighlightParts(String(plainValue), query);
|
|
29
|
+
}
|
|
30
|
+
return serverParts;
|
|
31
|
+
}, [highlightedValue, query, hit, attribute]);
|
|
32
|
+
// Default highlight style
|
|
33
|
+
const defaultHighlightStyle = {
|
|
34
|
+
backgroundColor: theme.colors.warning || '#fff59d',
|
|
35
|
+
fontWeight: theme.typography.fontWeight?.semibold || 600,
|
|
36
|
+
padding: '0 2px',
|
|
37
|
+
borderRadius: '2px',
|
|
38
|
+
};
|
|
39
|
+
// Render parts
|
|
40
|
+
const renderedParts = parts.map((part, index) => {
|
|
41
|
+
if (part.isHighlighted) {
|
|
42
|
+
if (renderHighlighted) {
|
|
43
|
+
return React.createElement(React.Fragment, { key: index }, renderHighlighted(part, index));
|
|
44
|
+
}
|
|
45
|
+
return (React.createElement("mark", { key: index, className: highlightTheme.highlighted, style: defaultHighlightStyle }, part.value));
|
|
46
|
+
}
|
|
47
|
+
if (renderNonHighlighted) {
|
|
48
|
+
return React.createElement(React.Fragment, { key: index }, renderNonHighlighted(part, index));
|
|
49
|
+
}
|
|
50
|
+
return (React.createElement("span", { key: index, className: highlightTheme.nonHighlighted }, part.value));
|
|
51
|
+
});
|
|
52
|
+
return (React.createElement(Tag, { className: className || highlightTheme.root, style: style }, renderedParts));
|
|
53
|
+
};
|
|
54
|
+
export const Snippet = ({ hit, attribute, maxLength = 100, ellipsis = '...', className, style, theme: customTheme, tagName: Tag = 'span', renderHighlighted, renderNonHighlighted, query, }) => {
|
|
55
|
+
const { theme } = useSearchContext();
|
|
56
|
+
const snippetTheme = customTheme || {};
|
|
57
|
+
// Get snippet or truncated highlighted value
|
|
58
|
+
const snippetValue = useMemo(() => {
|
|
59
|
+
// Check for server-provided snippet
|
|
60
|
+
const snippetResult = hit._snippetResult?.[attribute]?.value ||
|
|
61
|
+
hit.snippet_result?.[attribute]?.value ||
|
|
62
|
+
hit._snippet?.[attribute] ||
|
|
63
|
+
hit.snippet?.[attribute];
|
|
64
|
+
if (snippetResult) {
|
|
65
|
+
return snippetResult
|
|
66
|
+
.replace(/<em>/g, '<mark>')
|
|
67
|
+
.replace(/<\/em>/g, '</mark>');
|
|
68
|
+
}
|
|
69
|
+
// Fall back to highlighted value, truncated
|
|
70
|
+
let text = getHighlightedValue({
|
|
71
|
+
hit,
|
|
72
|
+
attribute,
|
|
73
|
+
preTag: '<mark>',
|
|
74
|
+
postTag: '</mark>',
|
|
75
|
+
});
|
|
76
|
+
// Remove tags for length calculation
|
|
77
|
+
const plainText = text.replace(/<\/?mark>/g, '');
|
|
78
|
+
if (plainText.length > maxLength) {
|
|
79
|
+
// Need to truncate while preserving tags
|
|
80
|
+
const truncated = truncateWithTags(text, maxLength);
|
|
81
|
+
return truncated + ellipsis;
|
|
82
|
+
}
|
|
83
|
+
return text;
|
|
84
|
+
}, [hit, attribute, maxLength, ellipsis]);
|
|
85
|
+
// Parse into parts
|
|
86
|
+
const parts = useMemo(() => {
|
|
87
|
+
const serverParts = parseHighlightedParts(snippetValue, '<mark>', '</mark>');
|
|
88
|
+
if (serverParts.every((p) => !p.isHighlighted) && query) {
|
|
89
|
+
const plainValue = hit[attribute] || snippetValue;
|
|
90
|
+
let text = String(plainValue);
|
|
91
|
+
if (text.length > maxLength) {
|
|
92
|
+
text = text.substring(0, maxLength) + ellipsis;
|
|
93
|
+
}
|
|
94
|
+
return parseQueryHighlightParts(text, query);
|
|
95
|
+
}
|
|
96
|
+
return serverParts;
|
|
97
|
+
}, [snippetValue, query, hit, attribute, maxLength, ellipsis]);
|
|
98
|
+
// Default highlight style
|
|
99
|
+
const defaultHighlightStyle = {
|
|
100
|
+
backgroundColor: theme.colors.warning || '#fff59d',
|
|
101
|
+
fontWeight: theme.typography.fontWeight?.semibold || 600,
|
|
102
|
+
padding: '0 2px',
|
|
103
|
+
borderRadius: '2px',
|
|
104
|
+
};
|
|
105
|
+
// Render parts
|
|
106
|
+
const renderedParts = parts.map((part, index) => {
|
|
107
|
+
if (part.isHighlighted) {
|
|
108
|
+
if (renderHighlighted) {
|
|
109
|
+
return React.createElement(React.Fragment, { key: index }, renderHighlighted(part, index));
|
|
110
|
+
}
|
|
111
|
+
return (React.createElement("mark", { key: index, className: snippetTheme.highlighted, style: defaultHighlightStyle }, part.value));
|
|
112
|
+
}
|
|
113
|
+
if (renderNonHighlighted) {
|
|
114
|
+
return React.createElement(React.Fragment, { key: index }, renderNonHighlighted(part, index));
|
|
115
|
+
}
|
|
116
|
+
return (React.createElement("span", { key: index, className: snippetTheme.nonHighlighted }, part.value));
|
|
117
|
+
});
|
|
118
|
+
return (React.createElement(Tag, { className: className || snippetTheme.root, style: style }, renderedParts));
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Truncate text while preserving HTML tags
|
|
122
|
+
*/
|
|
123
|
+
function truncateWithTags(text, maxLength) {
|
|
124
|
+
let visibleLength = 0;
|
|
125
|
+
let result = '';
|
|
126
|
+
let inTag = false;
|
|
127
|
+
for (let i = 0; i < text.length; i++) {
|
|
128
|
+
const char = text[i];
|
|
129
|
+
if (char === '<') {
|
|
130
|
+
inTag = true;
|
|
131
|
+
result += char;
|
|
132
|
+
}
|
|
133
|
+
else if (char === '>') {
|
|
134
|
+
inTag = false;
|
|
135
|
+
result += char;
|
|
136
|
+
}
|
|
137
|
+
else if (inTag) {
|
|
138
|
+
result += char;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
if (visibleLength >= maxLength) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
result += char;
|
|
145
|
+
visibleLength++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Close any unclosed tags
|
|
149
|
+
const openTags = result.match(/<mark>/g)?.length || 0;
|
|
150
|
+
const closeTags = result.match(/<\/mark>/g)?.length || 0;
|
|
151
|
+
for (let i = 0; i < openTags - closeTags; i++) {
|
|
152
|
+
result += '</mark>';
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HitsPerPage Component
|
|
3
|
+
*
|
|
4
|
+
* A dropdown to let users change the number of displayed hits per page
|
|
5
|
+
* Integrates with SearchStateManager for automatic state sync
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface HitsPerPageItem {
|
|
9
|
+
value: number;
|
|
10
|
+
label: string;
|
|
11
|
+
default?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface HitsPerPageTheme {
|
|
14
|
+
root?: string;
|
|
15
|
+
select?: string;
|
|
16
|
+
option?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface HitsPerPageProps {
|
|
19
|
+
/** Available items per page options */
|
|
20
|
+
items: HitsPerPageItem[];
|
|
21
|
+
/** Callback when hits per page changes */
|
|
22
|
+
onHitsPerPageChange?: (value: number) => void;
|
|
23
|
+
/** Custom render function for select */
|
|
24
|
+
renderSelect?: (props: {
|
|
25
|
+
value: number;
|
|
26
|
+
onChange: (e: React.ChangeEvent<HTMLSelectElement>) => void;
|
|
27
|
+
items: HitsPerPageItem[];
|
|
28
|
+
}) => React.ReactNode;
|
|
29
|
+
/** Custom className */
|
|
30
|
+
className?: string;
|
|
31
|
+
/** Custom styles */
|
|
32
|
+
style?: React.CSSProperties;
|
|
33
|
+
/** Custom theme */
|
|
34
|
+
theme?: HitsPerPageTheme;
|
|
35
|
+
/** Label text before the select */
|
|
36
|
+
label?: string;
|
|
37
|
+
/** Whether to sync with SearchStateManager (default: true) */
|
|
38
|
+
syncWithState?: boolean;
|
|
39
|
+
}
|
|
40
|
+
export declare const HitsPerPage: React.FC<HitsPerPageProps>;
|
|
41
|
+
//# sourceMappingURL=HitsPerPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HitsPerPage.d.ts","sourceRoot":"","sources":["../../src/components/HitsPerPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAiC,MAAM,OAAO,CAAC;AAMtD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,uCAAuC;IACvC,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,0CAA0C;IAC1C,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,wCAAwC;IACxC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE;QACrB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;QAC5D,KAAK,EAAE,eAAe,EAAE,CAAC;KAC1B,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,mCAAmC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA8GlD,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HitsPerPage Component
|
|
3
|
+
*
|
|
4
|
+
* A dropdown to let users change the number of displayed hits per page
|
|
5
|
+
* Integrates with SearchStateManager for automatic state sync
|
|
6
|
+
*/
|
|
7
|
+
import React, { useEffect } from 'react';
|
|
8
|
+
import { useSearchContext } from './SearchProvider';
|
|
9
|
+
import { useSearchState } from '../hooks/useSearchState';
|
|
10
|
+
import { clsx } from 'clsx';
|
|
11
|
+
import { CustomSelect } from './primitives/CustomSelect';
|
|
12
|
+
export const HitsPerPage = ({ items, onHitsPerPageChange, renderSelect, className, style, theme: customTheme, label = 'Show', syncWithState = true, }) => {
|
|
13
|
+
const { theme } = useSearchContext();
|
|
14
|
+
const { itemsPerPage, setPage } = useSearchState();
|
|
15
|
+
const { stateManager } = useSearchContext();
|
|
16
|
+
const hitsPerPageTheme = customTheme || {};
|
|
17
|
+
// Find the default item or first item
|
|
18
|
+
const defaultItem = items.find(i => i.default) || items[0];
|
|
19
|
+
const [internalValue, setInternalValue] = React.useState(defaultItem?.value || 10);
|
|
20
|
+
// Initialize StateManager on mount if default is set
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (syncWithState && defaultItem && itemsPerPage !== defaultItem.value) {
|
|
23
|
+
stateManager.setItemsPerPage(defaultItem.value, false);
|
|
24
|
+
}
|
|
25
|
+
}, []);
|
|
26
|
+
// Determine the current value from StateManager or internal
|
|
27
|
+
const value = syncWithState ? itemsPerPage : internalValue;
|
|
28
|
+
const handleChange = (e) => {
|
|
29
|
+
const newValue = parseInt(e.target.value, 10);
|
|
30
|
+
setInternalValue(newValue);
|
|
31
|
+
// Update StateManager
|
|
32
|
+
if (syncWithState) {
|
|
33
|
+
stateManager.setItemsPerPage(newValue, false);
|
|
34
|
+
// Reset to page 1 when changing items per page
|
|
35
|
+
setPage(1, true);
|
|
36
|
+
}
|
|
37
|
+
// Call callback
|
|
38
|
+
if (onHitsPerPageChange) {
|
|
39
|
+
onHitsPerPageChange(newValue);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
// Custom render function
|
|
43
|
+
if (renderSelect) {
|
|
44
|
+
return (React.createElement("div", { className: clsx(hitsPerPageTheme.root, className), style: style }, renderSelect({
|
|
45
|
+
value,
|
|
46
|
+
onChange: handleChange,
|
|
47
|
+
items,
|
|
48
|
+
})));
|
|
49
|
+
}
|
|
50
|
+
return (React.createElement("div", { className: clsx(hitsPerPageTheme.root, className), style: {
|
|
51
|
+
display: 'flex',
|
|
52
|
+
alignItems: 'center',
|
|
53
|
+
gap: theme.spacing.small,
|
|
54
|
+
...style,
|
|
55
|
+
} },
|
|
56
|
+
label && (React.createElement("label", { style: {
|
|
57
|
+
fontSize: theme.typography.fontSize.medium,
|
|
58
|
+
color: theme.colors.text,
|
|
59
|
+
} }, label)),
|
|
60
|
+
React.createElement(CustomSelect, { value: String(value), onChange: (val) => {
|
|
61
|
+
const newValue = parseInt(val, 10);
|
|
62
|
+
setInternalValue(newValue);
|
|
63
|
+
if (syncWithState) {
|
|
64
|
+
stateManager.setItemsPerPage(newValue, false);
|
|
65
|
+
setPage(1, true);
|
|
66
|
+
}
|
|
67
|
+
if (onHitsPerPageChange) {
|
|
68
|
+
onHitsPerPageChange(newValue);
|
|
69
|
+
}
|
|
70
|
+
}, options: items.map((item) => ({
|
|
71
|
+
value: String(item.value),
|
|
72
|
+
label: item.label,
|
|
73
|
+
})), "aria-label": "Results per page", className: hitsPerPageTheme.select, style: {
|
|
74
|
+
'--seekora-select-font-size': theme.typography.fontSize.medium,
|
|
75
|
+
'--seekora-select-border': theme.colors.border,
|
|
76
|
+
'--seekora-select-radius': typeof theme.borderRadius === 'string'
|
|
77
|
+
? theme.borderRadius
|
|
78
|
+
: theme.borderRadius.medium,
|
|
79
|
+
'--seekora-select-bg': theme.colors.background,
|
|
80
|
+
'--seekora-select-color': theme.colors.text,
|
|
81
|
+
} })));
|
|
82
|
+
};
|