@seekora-ai/ui-sdk-react 0.2.4 → 0.2.5
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/FederatedDropdown.d.ts +6 -0
- package/dist/components/FederatedDropdown.d.ts.map +1 -1
- package/dist/components/FederatedDropdown.js +4 -2
- package/dist/components/SearchBarWithSuggestions.d.ts +4 -0
- package/dist/components/SearchBarWithSuggestions.d.ts.map +1 -1
- package/dist/components/SearchBarWithSuggestions.js +2 -2
- package/dist/docsearch/components/DocSearch.d.ts +1 -1
- package/dist/docsearch/components/DocSearch.d.ts.map +1 -1
- package/dist/docsearch/components/DocSearch.js +15 -5
- package/dist/docsearch/components/Results.d.ts +3 -1
- package/dist/docsearch/components/Results.d.ts.map +1 -1
- package/dist/docsearch/components/Results.js +66 -12
- package/dist/docsearch/hooks/useDocSearch.d.ts +1 -0
- package/dist/docsearch/hooks/useDocSearch.d.ts.map +1 -1
- package/dist/docsearch/hooks/useDocSearch.js +6 -3
- package/dist/docsearch/hooks/useSeekoraSearch.d.ts.map +1 -1
- package/dist/docsearch/hooks/useSeekoraSearch.js +46 -26
- package/dist/docsearch/types.d.ts +2 -0
- package/dist/docsearch/types.d.ts.map +1 -1
- package/dist/docsearch.css +1 -1
- package/dist/hooks/useQuerySuggestionsEnhanced.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +14 -1
- package/dist/src/index.esm.js +140 -51
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +140 -51
- package/dist/src/index.js.map +1 -1
- package/package.json +5 -4
- package/src/docsearch/docsearch.css +237 -0
package/dist/src/index.js
CHANGED
|
@@ -4566,7 +4566,7 @@ function transformFilteredTab(raw) {
|
|
|
4566
4566
|
// Main Hook
|
|
4567
4567
|
// ============================================================================
|
|
4568
4568
|
function useQuerySuggestionsEnhanced(options) {
|
|
4569
|
-
const { client, query, enabled = true, debounceMs = 200, maxSuggestions = 10, minQueryLength = 1, includeDropdownRecommendations = false, includeCategories =
|
|
4569
|
+
const { client, query, enabled = true, debounceMs = 200, maxSuggestions = 10, minQueryLength = 1, includeDropdownRecommendations = false, includeCategories = true, includeFacets = false, maxCategories = 3, maxFacets = 5, filteredTabs, minPopularity, timeRange, disableTypoTolerance, analyticsTags, enableRecentSearches = true, maxRecentSearches = MAX_RECENT_SEARCHES_DEFAULT, recentSearchesKey = RECENT_SEARCHES_DEFAULT_KEY, onSuggestionsLoaded, onError, } = options;
|
|
4570
4570
|
// State
|
|
4571
4571
|
const [suggestions, setSuggestions] = React.useState([]);
|
|
4572
4572
|
const [loading, setLoading] = React.useState(false);
|
|
@@ -5968,7 +5968,7 @@ const ImagePlaceholder = () => (React.createElement("svg", { viewBox: "0 0 24 24
|
|
|
5968
5968
|
// Component
|
|
5969
5969
|
// ============================================================================
|
|
5970
5970
|
const FederatedDropdown = React.forwardRef(function FederatedDropdown(props, ref) {
|
|
5971
|
-
const { query, isOpen = true, maxSuggestions = 8, maxProducts = 8, maxBrands = 8, minQueryLength = 0, debounceMs = 200, filteredTabs: tabsConfig, showProducts = true, showBrands = true, showFilteredTabs = true, showRecentSearches = true, layout = 'side-by-side', productsColumnWidth = '60%', suggestionsColumnWidth = '40%', showPrices = true, currencySymbol = '$', classNames = {}, style, renderProduct, renderSuggestion, renderBrand, renderTab, header, footer, viewAllProductsLink, width = '800px', maxHeight = '600px', zIndex = 1000, analyticsTags, onSuggestionSelect, onProductClick, onBrandClick, onTabSelect, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, } = props;
|
|
5971
|
+
const { query, isOpen = true, maxSuggestions = 8, maxProducts = 8, maxBrands = 8, minQueryLength = 0, debounceMs = 200, filteredTabs: tabsConfig, showProducts = true, showBrands = true, showFilteredTabs = true, showRecentSearches = true, layout = 'side-by-side', productsColumnWidth = '60%', suggestionsColumnWidth = '40%', showPrices = true, currencySymbol = '$', classNames = {}, style, renderProduct, renderSuggestion, renderBrand, renderTab, header, footer, viewAllProductsLink, width = '800px', maxHeight = '600px', zIndex = 1000, analyticsTags, includeFacets: includeFacetsProp = true, includeCategories: includeCategoriesProp = true, includeDropdownRecommendations: includeDropdownRecommendationsProp = true, onSuggestionSelect, onProductClick, onBrandClick, onTabSelect, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, } = props;
|
|
5972
5972
|
const { client } = useSearchContext();
|
|
5973
5973
|
const containerRef = React.useRef(null);
|
|
5974
5974
|
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
@@ -5983,7 +5983,9 @@ const FederatedDropdown = React.forwardRef(function FederatedDropdown(props, ref
|
|
|
5983
5983
|
debounceMs,
|
|
5984
5984
|
maxSuggestions,
|
|
5985
5985
|
minQueryLength,
|
|
5986
|
-
includeDropdownRecommendations:
|
|
5986
|
+
includeDropdownRecommendations: includeDropdownRecommendationsProp,
|
|
5987
|
+
includeCategories: includeCategoriesProp,
|
|
5988
|
+
includeFacets: includeFacetsProp,
|
|
5987
5989
|
filteredTabs: tabsConfig,
|
|
5988
5990
|
analyticsTags,
|
|
5989
5991
|
enableRecentSearches: showRecentSearches,
|
|
@@ -6522,7 +6524,7 @@ const ClearIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill
|
|
|
6522
6524
|
// Component
|
|
6523
6525
|
// ============================================================================
|
|
6524
6526
|
const SearchBarWithSuggestions = React.forwardRef(function SearchBarWithSuggestions(props, ref) {
|
|
6525
|
-
const { variant = 'classic', placeholder = 'Search...', initialQuery = '', value, onQueryChange, onSearch, onSuggestionSelect, onProductClick, showSearchButton = false, searchButtonText = 'Search', showClearButton = true, autoFocus = false, minQueryLength = 1, maxSuggestions = 8, debounceMs = 200, showRecentSearches = true, showTrendingOnEmpty = true, includeDropdownRecommendations = false, filteredTabs, enableAnalytics = true, analyticsTags, dropdownWidth, dropdownMaxHeight, classNames = {}, style, inputStyle, ariaLabel = 'Search', } = props;
|
|
6527
|
+
const { variant = 'classic', placeholder = 'Search...', initialQuery = '', value, onQueryChange, onSearch, onSuggestionSelect, onProductClick, showSearchButton = false, searchButtonText = 'Search', showClearButton = true, autoFocus = false, minQueryLength = 1, maxSuggestions = 8, debounceMs = 200, showRecentSearches = true, showTrendingOnEmpty = true, includeDropdownRecommendations = false, filteredTabs, enableAnalytics = true, analyticsTags, includeFacets, includeCategories, dropdownWidth, dropdownMaxHeight, classNames = {}, style, inputStyle, ariaLabel = 'Search', } = props;
|
|
6526
6528
|
const { client } = useSearchContext();
|
|
6527
6529
|
const inputRef = React.useRef(null);
|
|
6528
6530
|
const dropdownRef = React.useRef(null);
|
|
@@ -6681,7 +6683,7 @@ const SearchBarWithSuggestions = React.forwardRef(function SearchBarWithSuggesti
|
|
|
6681
6683
|
case 'rich':
|
|
6682
6684
|
return (React.createElement(RichQuerySuggestions, { ref: dropdownRef, ...commonProps, includeDropdownRecommendations: includeDropdownRecommendations, includeCategories: true, width: dropdownWidth || '100%', maxHeight: dropdownMaxHeight || '480px' }));
|
|
6683
6685
|
case 'federated':
|
|
6684
|
-
return (React.createElement(FederatedDropdown, { ref: dropdownRef, ...commonProps, filteredTabs: filteredTabs, showProducts: true, showBrands: true, showFilteredTabs: !!filteredTabs, onProductClick: handleProductClick, width: dropdownWidth || '800px', maxHeight: dropdownMaxHeight || '600px' }));
|
|
6686
|
+
return (React.createElement(FederatedDropdown, { ref: dropdownRef, ...commonProps, filteredTabs: filteredTabs, showProducts: true, showBrands: true, showFilteredTabs: !!filteredTabs, onProductClick: handleProductClick, width: dropdownWidth || '800px', maxHeight: dropdownMaxHeight || '600px', includeFacets: includeFacets, includeCategories: includeCategories, includeDropdownRecommendations: includeDropdownRecommendations }));
|
|
6685
6687
|
case 'compact':
|
|
6686
6688
|
return (React.createElement(QuerySuggestionsDropdown, { ref: dropdownRef, ...commonProps, maxSuggestions: 5, showCounts: false, width: dropdownWidth || '100%' }));
|
|
6687
6689
|
case 'classic':
|
|
@@ -11438,16 +11440,48 @@ function getTypeLevel(type) {
|
|
|
11438
11440
|
function isChildType(type) {
|
|
11439
11441
|
return getTypeLevel(type) >= 2;
|
|
11440
11442
|
}
|
|
11443
|
+
/** Build a stable grouping key from all hierarchy levels (lvl0 through lvl5). */
|
|
11444
|
+
function getHierarchyKey(hit) {
|
|
11445
|
+
const h = hit.hierarchy ?? {};
|
|
11446
|
+
const parts = [
|
|
11447
|
+
h.lvl0 ?? '',
|
|
11448
|
+
h.lvl1 ?? '',
|
|
11449
|
+
h.lvl2 ?? '',
|
|
11450
|
+
h.lvl3 ?? '',
|
|
11451
|
+
h.lvl4 ?? '',
|
|
11452
|
+
h.lvl5 ?? '',
|
|
11453
|
+
];
|
|
11454
|
+
return parts.join('\0');
|
|
11455
|
+
}
|
|
11456
|
+
/** Build a display breadcrumb from hierarchy, skipping consecutive duplicates (e.g. lvl0 === lvl1). */
|
|
11457
|
+
function getHierarchyBreadcrumb(hit) {
|
|
11458
|
+
const h = hit.hierarchy ?? {};
|
|
11459
|
+
const parts = [h.lvl0, h.lvl1, h.lvl2, h.lvl3, h.lvl4, h.lvl5].filter((v) => typeof v === 'string' && v.length > 0);
|
|
11460
|
+
const deduped = [];
|
|
11461
|
+
for (const p of parts) {
|
|
11462
|
+
if (deduped[deduped.length - 1] !== p)
|
|
11463
|
+
deduped.push(p);
|
|
11464
|
+
}
|
|
11465
|
+
return deduped.join(' › ');
|
|
11466
|
+
}
|
|
11441
11467
|
function groupHitsByHierarchy(hits) {
|
|
11468
|
+
const hitToIndex = new Map();
|
|
11469
|
+
hits.forEach((h, i) => hitToIndex.set(h, i));
|
|
11442
11470
|
const groups = new Map();
|
|
11443
11471
|
for (const hit of hits) {
|
|
11444
|
-
const
|
|
11445
|
-
if (!groups.has(
|
|
11446
|
-
groups.set(
|
|
11447
|
-
groups.get(
|
|
11448
|
-
}
|
|
11472
|
+
const key = getHierarchyKey(hit);
|
|
11473
|
+
if (!groups.has(key))
|
|
11474
|
+
groups.set(key, []);
|
|
11475
|
+
groups.get(key).push(hit);
|
|
11476
|
+
}
|
|
11477
|
+
const entries = Array.from(groups.entries());
|
|
11478
|
+
entries.sort(([, aHits], [, bHits]) => {
|
|
11479
|
+
const aMin = Math.min(...aHits.map(h => hitToIndex.get(h) ?? 0));
|
|
11480
|
+
const bMin = Math.min(...bHits.map(h => hitToIndex.get(h) ?? 0));
|
|
11481
|
+
return aMin - bMin;
|
|
11482
|
+
});
|
|
11449
11483
|
const result = [];
|
|
11450
|
-
for (const [
|
|
11484
|
+
for (const [, groupHits] of entries) {
|
|
11451
11485
|
const sortedHits = [...groupHits].sort((a, b) => {
|
|
11452
11486
|
const aType = a.type;
|
|
11453
11487
|
const bType = b.type;
|
|
@@ -11460,7 +11494,8 @@ function groupHitsByHierarchy(hits) {
|
|
|
11460
11494
|
const isLastChild = isChild && (!nextHit || !isChildType(nextHit.type));
|
|
11461
11495
|
return { ...hit, isChild, isLastChild };
|
|
11462
11496
|
});
|
|
11463
|
-
|
|
11497
|
+
const category = getHierarchyBreadcrumb(groupHits[0]);
|
|
11498
|
+
result.push({ category: category || null, hits: markedHits });
|
|
11464
11499
|
}
|
|
11465
11500
|
return result;
|
|
11466
11501
|
}
|
|
@@ -11475,15 +11510,36 @@ function getHitKey(hit, index) {
|
|
|
11475
11510
|
return hit.objectID;
|
|
11476
11511
|
return `suggestion-${hit.url}-${index}`;
|
|
11477
11512
|
}
|
|
11478
|
-
function Results({ hits, groupedHits, selectedIndex, onSelect, onHover, query, isLoading, error, translations = {}, sources: _sources = [], }) {
|
|
11513
|
+
function Results({ hits, groupedHits, selectedIndex, onSelect, onHover, scrollSelectionIntoViewRef, query, isLoading, error, translations = {}, sources: _sources = [], }) {
|
|
11479
11514
|
const listRef = React.useRef(null);
|
|
11480
11515
|
React.useEffect(() => {
|
|
11481
|
-
if (listRef.current
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11516
|
+
if (!listRef.current || hits.length === 0)
|
|
11517
|
+
return;
|
|
11518
|
+
// Only scroll when selection changed via keyboard (avoids scroll-to-selected on hover)
|
|
11519
|
+
if (scrollSelectionIntoViewRef && !scrollSelectionIntoViewRef.current)
|
|
11520
|
+
return;
|
|
11521
|
+
// listRef's direct children are groups (li.seekora-docsearch-results-group), not hits.
|
|
11522
|
+
// Find the actual hit element at flat selectedIndex.
|
|
11523
|
+
const groupEls = listRef.current.querySelectorAll('.seekora-docsearch-results-group');
|
|
11524
|
+
let idx = 0;
|
|
11525
|
+
for (const groupEl of groupEls) {
|
|
11526
|
+
const itemList = groupEl.querySelector('.seekora-docsearch-results-group-items');
|
|
11527
|
+
if (!itemList)
|
|
11528
|
+
continue;
|
|
11529
|
+
const items = itemList.children;
|
|
11530
|
+
for (let i = 0; i < items.length; i++) {
|
|
11531
|
+
if (idx === selectedIndex) {
|
|
11532
|
+
items[i].scrollIntoView({ block: 'nearest' });
|
|
11533
|
+
if (scrollSelectionIntoViewRef)
|
|
11534
|
+
scrollSelectionIntoViewRef.current = false;
|
|
11535
|
+
return;
|
|
11536
|
+
}
|
|
11537
|
+
idx++;
|
|
11538
|
+
}
|
|
11485
11539
|
}
|
|
11486
|
-
|
|
11540
|
+
if (scrollSelectionIntoViewRef)
|
|
11541
|
+
scrollSelectionIntoViewRef.current = false;
|
|
11542
|
+
}, [selectedIndex, hits.length, scrollSelectionIntoViewRef]);
|
|
11487
11543
|
if (!query) {
|
|
11488
11544
|
return (React.createElement("div", { className: "seekora-docsearch-empty" },
|
|
11489
11545
|
React.createElement("p", { className: "seekora-docsearch-empty-text" }, translations.searchPlaceholder || 'Type to start searching...')));
|
|
@@ -11670,7 +11726,7 @@ function reducer(state, action) {
|
|
|
11670
11726
|
}
|
|
11671
11727
|
}
|
|
11672
11728
|
function useDocSearch(options) {
|
|
11673
|
-
const { apiEndpoint, apiKey, sources, maxResults = 10, debounceMs = 200 } = options;
|
|
11729
|
+
const { apiEndpoint, apiKey, sources, maxResults = 10, debounceMs = 200, processGroupedResults } = options;
|
|
11674
11730
|
const searchSources = sources || (apiEndpoint ? [{
|
|
11675
11731
|
id: 'default',
|
|
11676
11732
|
name: 'Results',
|
|
@@ -11773,7 +11829,10 @@ function useDocSearch(options) {
|
|
|
11773
11829
|
const results = await Promise.all(searchSources.map(async (source) => {
|
|
11774
11830
|
const controller = new AbortController();
|
|
11775
11831
|
abortControllersRef.current.set(source.id, controller);
|
|
11776
|
-
|
|
11832
|
+
let items = await fetchFromSource(source, query, controller.signal);
|
|
11833
|
+
if (processGroupedResults) {
|
|
11834
|
+
items = processGroupedResults(source.id, items);
|
|
11835
|
+
}
|
|
11777
11836
|
return { source, items };
|
|
11778
11837
|
}));
|
|
11779
11838
|
const groupedResults = results.filter(r => r.items.length > 0);
|
|
@@ -11787,7 +11846,7 @@ function useDocSearch(options) {
|
|
|
11787
11846
|
finally {
|
|
11788
11847
|
dispatch({ type: 'SET_LOADING', payload: false });
|
|
11789
11848
|
}
|
|
11790
|
-
}, [searchSources, fetchFromSource]);
|
|
11849
|
+
}, [searchSources, fetchFromSource, processGroupedResults]);
|
|
11791
11850
|
const search = React.useCallback((q) => fetchSuggestions(q), [fetchSuggestions]);
|
|
11792
11851
|
const setQuery = React.useCallback((query) => {
|
|
11793
11852
|
dispatch({ type: 'SET_QUERY', payload: query });
|
|
@@ -11831,41 +11890,59 @@ function useDocSearch(options) {
|
|
|
11831
11890
|
};
|
|
11832
11891
|
}
|
|
11833
11892
|
|
|
11893
|
+
/** Build hierarchy from doc: either nested doc.hierarchy or flat keys like doc['hierarchy.lvl0'] */
|
|
11894
|
+
function getHierarchy(doc) {
|
|
11895
|
+
const hierarchy = {};
|
|
11896
|
+
if (doc?.hierarchy && typeof doc.hierarchy === 'object') {
|
|
11897
|
+
hierarchy.lvl0 = doc.hierarchy.lvl0;
|
|
11898
|
+
hierarchy.lvl1 = doc.hierarchy.lvl1;
|
|
11899
|
+
hierarchy.lvl2 = doc.hierarchy.lvl2;
|
|
11900
|
+
hierarchy.lvl3 = doc.hierarchy.lvl3;
|
|
11901
|
+
hierarchy.lvl4 = doc.hierarchy.lvl4;
|
|
11902
|
+
hierarchy.lvl5 = doc.hierarchy.lvl5;
|
|
11903
|
+
}
|
|
11904
|
+
else if (doc && typeof doc === 'object') {
|
|
11905
|
+
hierarchy.lvl0 = doc['hierarchy.lvl0'];
|
|
11906
|
+
hierarchy.lvl1 = doc['hierarchy.lvl1'];
|
|
11907
|
+
hierarchy.lvl2 = doc['hierarchy.lvl2'];
|
|
11908
|
+
hierarchy.lvl3 = doc['hierarchy.lvl3'];
|
|
11909
|
+
hierarchy.lvl4 = doc['hierarchy.lvl4'];
|
|
11910
|
+
hierarchy.lvl5 = doc['hierarchy.lvl5'];
|
|
11911
|
+
}
|
|
11912
|
+
return hierarchy;
|
|
11913
|
+
}
|
|
11834
11914
|
function transformResults(results) {
|
|
11915
|
+
const stripMark = (s) => typeof s === 'string' ? s.replace(/<\/?mark>/g, '') : (s ? String(s) : '');
|
|
11835
11916
|
return results.map((result) => {
|
|
11836
|
-
const
|
|
11837
|
-
const
|
|
11838
|
-
const
|
|
11839
|
-
const
|
|
11840
|
-
const
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
if (result.category)
|
|
11848
|
-
hierarchy.lvl0 = result.category;
|
|
11849
|
-
if (result.parent_title || result.parentTitle)
|
|
11850
|
-
hierarchy.lvl1 = result.parent_title || result.parentTitle;
|
|
11851
|
-
}
|
|
11917
|
+
const doc = result?.document ?? result;
|
|
11918
|
+
const hierarchy = getHierarchy(doc);
|
|
11919
|
+
const url = doc.url || result.url || doc.route || result.route || doc.link || result.link || '';
|
|
11920
|
+
const rawTitle = doc.title || result.title || doc.name || result.name || hierarchy?.lvl3 || hierarchy?.lvl2 || hierarchy?.lvl1 || hierarchy?.lvl0 || '';
|
|
11921
|
+
const content = doc.content ?? result.content ?? doc.description ?? result.description ?? doc.snippet ?? result.snippet ?? '';
|
|
11922
|
+
const description = doc.description ?? result.description ?? (typeof content === 'string' ? content.substring(0, 150) : '');
|
|
11923
|
+
const plainTitle = stripMark(rawTitle) || stripMark(hierarchy?.lvl3) || stripMark(hierarchy?.lvl2) || stripMark(hierarchy?.lvl1) || stripMark(hierarchy?.lvl0) || 'Untitled';
|
|
11924
|
+
const plainContent = stripMark(content)?.substring(0, 200) || content;
|
|
11925
|
+
const apiHighlight = result?.highlight ?? doc?.highlight;
|
|
11926
|
+
const highlightTitle = typeof apiHighlight?.title === 'string' ? apiHighlight.title : undefined;
|
|
11927
|
+
const highlightContent = typeof apiHighlight?.content === 'string' ? apiHighlight.content : undefined;
|
|
11852
11928
|
return {
|
|
11853
11929
|
url,
|
|
11854
|
-
title:
|
|
11855
|
-
content:
|
|
11856
|
-
description: description
|
|
11857
|
-
category: result.category
|
|
11930
|
+
title: plainTitle,
|
|
11931
|
+
content: plainContent,
|
|
11932
|
+
description: stripMark(description) || description,
|
|
11933
|
+
category: doc.category ?? result.category ?? hierarchy?.lvl0 ?? '',
|
|
11858
11934
|
hierarchy,
|
|
11859
|
-
route: result.route,
|
|
11860
|
-
parentTitle: result.parent_title
|
|
11861
|
-
type: result.type
|
|
11862
|
-
anchor: result.anchor
|
|
11935
|
+
route: doc.route ?? result.route,
|
|
11936
|
+
parentTitle: doc.parent_title ?? doc.parentTitle ?? result.parent_title ?? result.parentTitle,
|
|
11937
|
+
type: doc.type ?? result.type ?? '',
|
|
11938
|
+
anchor: doc.anchor ?? result.anchor ?? '',
|
|
11863
11939
|
_source: 'seekora',
|
|
11940
|
+
highlight: (highlightTitle ?? highlightContent) ? { title: highlightTitle, content: highlightContent } : undefined,
|
|
11864
11941
|
};
|
|
11865
11942
|
});
|
|
11866
11943
|
}
|
|
11867
11944
|
function useSeekoraSearch$1(options) {
|
|
11868
|
-
const { storeId, storeSecret, apiEndpoint, maxResults = 20, debounceMs = 200, analyticsTags = ['docsearch'], groupField, groupSize, } = options;
|
|
11945
|
+
const { storeId, storeSecret, apiEndpoint, maxResults = 20, debounceMs = 200, analyticsTags = ['docsearch'], groupField = 'hierarchy.lvl3', groupSize = 10, } = options;
|
|
11869
11946
|
const [query, setQueryState] = React.useState('');
|
|
11870
11947
|
const [suggestions, setSuggestions] = React.useState([]);
|
|
11871
11948
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
@@ -11889,7 +11966,9 @@ function useSeekoraSearch$1(options) {
|
|
|
11889
11966
|
config.environment = apiEndpoint;
|
|
11890
11967
|
}
|
|
11891
11968
|
else {
|
|
11892
|
-
|
|
11969
|
+
// Search SDK path is /v1/search; backend serves at /api/v1/search. baseUrl must include /api.
|
|
11970
|
+
const base = apiEndpoint.replace(/\/$/, '');
|
|
11971
|
+
config.baseUrl = base.endsWith('/api') ? base : `${base}/api`;
|
|
11893
11972
|
}
|
|
11894
11973
|
}
|
|
11895
11974
|
try {
|
|
@@ -12017,8 +12096,9 @@ function useSeekoraSearch$1(options) {
|
|
|
12017
12096
|
};
|
|
12018
12097
|
}
|
|
12019
12098
|
|
|
12020
|
-
function DocSearch({ storeId, storeSecret, seekoraApiEndpoint, apiEndpoint, apiKey, sources, placeholder = 'Search documentation...', maxResults = 10, debounceMs = 200, onSelect, onClose, translations = {}, renderButton = true, buttonComponent: ButtonComponent = DocSearchButton, initialOpen = false, disableShortcut = false, shortcutKey = 'k', }) {
|
|
12099
|
+
function DocSearch({ storeId, storeSecret, seekoraApiEndpoint, apiEndpoint, apiKey, sources, placeholder = 'Search documentation...', maxResults = 10, debounceMs = 200, onSelect, onClose, translations = {}, renderButton = true, buttonComponent: ButtonComponent = DocSearchButton, initialOpen = false, disableShortcut = false, shortcutKey = 'k', processGroupedResults, }) {
|
|
12021
12100
|
const [isOpen, setIsOpen] = React.useState(initialOpen);
|
|
12101
|
+
const scrollSelectionIntoViewRef = React.useRef(false);
|
|
12022
12102
|
const useSeekoraSDK = !!storeId;
|
|
12023
12103
|
const seekoraSearch = useSeekoraSearch$1({
|
|
12024
12104
|
storeId: storeId || '',
|
|
@@ -12034,6 +12114,7 @@ function DocSearch({ storeId, storeSecret, seekoraApiEndpoint, apiEndpoint, apiK
|
|
|
12034
12114
|
sources,
|
|
12035
12115
|
maxResults,
|
|
12036
12116
|
debounceMs,
|
|
12117
|
+
processGroupedResults,
|
|
12037
12118
|
});
|
|
12038
12119
|
const { query, suggestions, isLoading, error, selectedIndex, setQuery, selectNext, selectPrev, setSelectedIndex, reset, getSelectedItem, } = useSeekoraSDK ? seekoraSearch : legacySearch;
|
|
12039
12120
|
const groupedSuggestions = useSeekoraSDK ? undefined : legacySearch.groupedSuggestions;
|
|
@@ -12065,12 +12146,20 @@ function DocSearch({ storeId, storeSecret, seekoraApiEndpoint, apiEndpoint, apiK
|
|
|
12065
12146
|
if (selectedItem)
|
|
12066
12147
|
handleSelect(selectedItem);
|
|
12067
12148
|
}, [getSelectedItem, handleSelect]);
|
|
12149
|
+
const handleSelectNext = React.useCallback(() => {
|
|
12150
|
+
scrollSelectionIntoViewRef.current = true;
|
|
12151
|
+
selectNext();
|
|
12152
|
+
}, [selectNext]);
|
|
12153
|
+
const handleSelectPrev = React.useCallback(() => {
|
|
12154
|
+
scrollSelectionIntoViewRef.current = true;
|
|
12155
|
+
selectPrev();
|
|
12156
|
+
}, [selectPrev]);
|
|
12068
12157
|
const { handleModalKeyDown } = useKeyboard({
|
|
12069
12158
|
isOpen,
|
|
12070
12159
|
onOpen: handleOpen,
|
|
12071
12160
|
onClose: handleClose,
|
|
12072
|
-
onSelectNext:
|
|
12073
|
-
onSelectPrev:
|
|
12161
|
+
onSelectNext: handleSelectNext,
|
|
12162
|
+
onSelectPrev: handleSelectPrev,
|
|
12074
12163
|
onEnter: handleEnter,
|
|
12075
12164
|
disableShortcut,
|
|
12076
12165
|
shortcutKey,
|
|
@@ -12086,7 +12175,7 @@ function DocSearch({ storeId, storeSecret, seekoraApiEndpoint, apiEndpoint, apiK
|
|
|
12086
12175
|
React.createElement("button", { type: "button", className: "seekora-docsearch-close", onClick: handleClose, "aria-label": "Close search" },
|
|
12087
12176
|
React.createElement("span", { className: "seekora-docsearch-close-text" }, "esc"))),
|
|
12088
12177
|
React.createElement("div", { className: "seekora-docsearch-body" },
|
|
12089
|
-
React.createElement(Results, { hits: displayHits, groupedHits: groupedSuggestions, selectedIndex: selectedIndex, onSelect: handleSelect, onHover: setSelectedIndex, query: query, isLoading: isLoading, error: error, translations: translations, sources: searchSources })),
|
|
12178
|
+
React.createElement(Results, { hits: displayHits, groupedHits: groupedSuggestions, selectedIndex: selectedIndex, onSelect: handleSelect, onHover: setSelectedIndex, scrollSelectionIntoViewRef: scrollSelectionIntoViewRef, query: query, isLoading: isLoading, error: error, translations: translations, sources: searchSources })),
|
|
12090
12179
|
React.createElement(Footer, { translations: translations })))));
|
|
12091
12180
|
}
|
|
12092
12181
|
|