@seekora-ai/ui-sdk-react 0.2.17 → 0.2.20
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/SearchBar.d.ts +3 -0
- package/dist/components/SearchBar.d.ts.map +1 -1
- package/dist/components/SearchBar.js +32 -4
- package/dist/components/suggestions-primitives/CategoriesTabs.js +1 -1
- package/dist/components/suggestions-primitives/ItemCard.js +3 -3
- package/dist/components/suggestions-primitives/ProductCard.js +3 -3
- package/dist/components/suggestions-primitives/ProductCardLayouts.js +6 -6
- package/dist/components/suggestions-primitives/RecentSearchesList.js +3 -3
- package/dist/components/suggestions-primitives/SearchInput.js +2 -2
- package/dist/components/suggestions-primitives/SuggestionItem.js +3 -3
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts +3 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SuggestionsProvider.js +46 -9
- package/dist/components/suggestions-primitives/TrendingList.js +4 -4
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts +2 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -1
- package/dist/hooks/useQuerySuggestionsEnhanced.js +26 -2
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.esm.js +129 -40
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +129 -40
- package/dist/src/index.js.map +1 -1
- package/package.json +5 -5
package/dist/src/index.js
CHANGED
|
@@ -1687,7 +1687,7 @@ const DefaultSearchIcon = ({ size = 18 }) => (React.createElement("svg", { width
|
|
|
1687
1687
|
const DefaultClearIcon = ({ size = 14 }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
1688
1688
|
React.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1689
1689
|
React.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })));
|
|
1690
|
-
const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, renderSuggestion, renderSearchIcon, showClearButton = true, renderClearIcon, showSubmitButton = false, renderSubmitButton, size = 'medium', }) => {
|
|
1690
|
+
const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, renderSuggestion, renderSearchIcon, showClearButton = true, renderClearIcon, showSubmitButton = false, renderSubmitButton, size = 'medium', searchAsYouType = false, }) => {
|
|
1691
1691
|
const { client, theme, enableAnalytics, autoTrackSearch } = useSearchContext();
|
|
1692
1692
|
const { query, setQuery, search: triggerSearch, results, loading: searchLoading, error: searchError } = useSearchState();
|
|
1693
1693
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
@@ -1695,6 +1695,14 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
|
|
|
1695
1695
|
const inputRef = React.useRef(null);
|
|
1696
1696
|
const containerRef = React.useRef(null);
|
|
1697
1697
|
const isSearchingRef = React.useRef(false); // Flag to prevent blur handler from interfering
|
|
1698
|
+
const searchAsYouTypeRef = React.useRef(null);
|
|
1699
|
+
// Cleanup searchAsYouType timer on unmount
|
|
1700
|
+
React.useEffect(() => {
|
|
1701
|
+
return () => {
|
|
1702
|
+
if (searchAsYouTypeRef.current)
|
|
1703
|
+
clearTimeout(searchAsYouTypeRef.current);
|
|
1704
|
+
};
|
|
1705
|
+
}, []);
|
|
1698
1706
|
const { suggestions, loading: suggestionsLoading } = useQuerySuggestions({
|
|
1699
1707
|
client,
|
|
1700
1708
|
query,
|
|
@@ -1724,6 +1732,11 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
|
|
|
1724
1732
|
}
|
|
1725
1733
|
}, [query, onQueryChange]);
|
|
1726
1734
|
const handleSearch = React.useCallback(async (searchQuery) => {
|
|
1735
|
+
// Cancel any pending searchAsYouType debounce — user explicitly submitted
|
|
1736
|
+
if (searchAsYouTypeRef.current) {
|
|
1737
|
+
clearTimeout(searchAsYouTypeRef.current);
|
|
1738
|
+
searchAsYouTypeRef.current = null;
|
|
1739
|
+
}
|
|
1727
1740
|
// Allow empty queries - use empty string for search
|
|
1728
1741
|
const query = searchQuery.trim();
|
|
1729
1742
|
log.info('SearchBar: Triggering search', { query, originalQuery: searchQuery, isEmpty: !query });
|
|
@@ -1760,10 +1773,18 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
|
|
|
1760
1773
|
const handleInputChange = React.useCallback((e) => {
|
|
1761
1774
|
const value = e.target.value;
|
|
1762
1775
|
// Update query in state manager but don't trigger search immediately
|
|
1763
|
-
// Search will be triggered on Enter or
|
|
1776
|
+
// Search will be triggered on Enter, suggestion select, or after debounce if searchAsYouType
|
|
1764
1777
|
setQuery(value, false); // false = don't trigger search immediately
|
|
1765
1778
|
setSelectedIndex(-1);
|
|
1766
|
-
|
|
1779
|
+
if (searchAsYouType) {
|
|
1780
|
+
if (searchAsYouTypeRef.current)
|
|
1781
|
+
clearTimeout(searchAsYouTypeRef.current);
|
|
1782
|
+
searchAsYouTypeRef.current = setTimeout(() => {
|
|
1783
|
+
searchAsYouTypeRef.current = null;
|
|
1784
|
+
triggerSearch();
|
|
1785
|
+
}, debounceMs);
|
|
1786
|
+
}
|
|
1787
|
+
}, [setQuery, searchAsYouType, debounceMs, triggerSearch]);
|
|
1767
1788
|
const handleKeyDown = React.useCallback((e) => {
|
|
1768
1789
|
switch (e.key) {
|
|
1769
1790
|
case 'ArrowDown':
|
|
@@ -1839,10 +1860,17 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
|
|
|
1839
1860
|
? `0 0 0 3px var(--seekora-border-focus-alpha, ${theme.colors.focus}33)`
|
|
1840
1861
|
: undefined;
|
|
1841
1862
|
const handleClear = React.useCallback(() => {
|
|
1863
|
+
if (searchAsYouTypeRef.current) {
|
|
1864
|
+
clearTimeout(searchAsYouTypeRef.current);
|
|
1865
|
+
searchAsYouTypeRef.current = null;
|
|
1866
|
+
}
|
|
1842
1867
|
setQuery('', false);
|
|
1843
1868
|
setSelectedIndex(-1);
|
|
1844
1869
|
inputRef.current?.focus();
|
|
1845
|
-
|
|
1870
|
+
if (searchAsYouType) {
|
|
1871
|
+
triggerSearch();
|
|
1872
|
+
}
|
|
1873
|
+
}, [setQuery, searchAsYouType, triggerSearch]);
|
|
1846
1874
|
const handleSubmit = React.useCallback(() => {
|
|
1847
1875
|
const currentValue = inputRef.current?.value || query;
|
|
1848
1876
|
handleSearch(currentValue);
|
|
@@ -6802,7 +6830,7 @@ function transformFilteredTab(raw) {
|
|
|
6802
6830
|
// Main Hook
|
|
6803
6831
|
// ============================================================================
|
|
6804
6832
|
function useQuerySuggestionsEnhanced(options) {
|
|
6805
|
-
const { client, query, enabled = true, debounceMs = 200, maxSuggestions = 10, minQueryLength = 1, includeDropdownRecommendations = false, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, includeFacets = true, // CHANGED: Enable facets by default
|
|
6833
|
+
const { client, query, enabled = true, prefetch = false, debounceMs = 200, maxSuggestions = 10, minQueryLength = 1, includeDropdownRecommendations = false, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, includeFacets = true, // CHANGED: Enable facets by default
|
|
6806
6834
|
maxCategories = 3, maxFacets = 5, filteredTabs, minPopularity, timeRange, disableTypoTolerance, analyticsTags, enableRecentSearches = true, maxRecentSearches = MAX_RECENT_SEARCHES_DEFAULT, recentSearchesKey = RECENT_SEARCHES_DEFAULT_KEY, onSuggestionsLoaded, onError, } = options;
|
|
6807
6835
|
// State
|
|
6808
6836
|
const [suggestions, setSuggestions] = React.useState([]);
|
|
@@ -6975,17 +7003,41 @@ function useQuerySuggestionsEnhanced(options) {
|
|
|
6975
7003
|
onSuggestionsLoaded,
|
|
6976
7004
|
onError,
|
|
6977
7005
|
]);
|
|
7006
|
+
// Prefetch: fire initial empty-query fetch once client is ready (before dropdown opens)
|
|
7007
|
+
const prefetchedRef = React.useRef(false);
|
|
7008
|
+
React.useEffect(() => {
|
|
7009
|
+
if (!prefetch || prefetchedRef.current)
|
|
7010
|
+
return;
|
|
7011
|
+
if (minQueryLength > 0)
|
|
7012
|
+
return;
|
|
7013
|
+
if (!client?.getSuggestions)
|
|
7014
|
+
return;
|
|
7015
|
+
prefetchedRef.current = true;
|
|
7016
|
+
fetchSuggestions('');
|
|
7017
|
+
}, [prefetch, client, minQueryLength, fetchSuggestions]);
|
|
6978
7018
|
// Debounced fetch effect
|
|
6979
7019
|
React.useEffect(() => {
|
|
6980
7020
|
if (debounceTimerRef.current) {
|
|
6981
7021
|
clearTimeout(debounceTimerRef.current);
|
|
6982
7022
|
}
|
|
6983
7023
|
if (!enabled || query.length < minQueryLength) {
|
|
7024
|
+
// Don't clear prefetched data when dropdown is closed
|
|
7025
|
+
if (prefetch && prefetchedRef.current && query === '') {
|
|
7026
|
+
// Keep prefetched data intact
|
|
7027
|
+
setLoading(false);
|
|
7028
|
+
setError(null);
|
|
7029
|
+
return;
|
|
7030
|
+
}
|
|
6984
7031
|
setSuggestions([]);
|
|
7032
|
+
setDropdownRecommendations(null);
|
|
6985
7033
|
setLoading(false);
|
|
6986
7034
|
setError(null);
|
|
6987
7035
|
return;
|
|
6988
7036
|
}
|
|
7037
|
+
// When dropdown opens with empty query and we already have prefetched data, skip re-fetch
|
|
7038
|
+
if (prefetch && prefetchedRef.current && query === '') {
|
|
7039
|
+
return;
|
|
7040
|
+
}
|
|
6989
7041
|
setLoading(true);
|
|
6990
7042
|
debounceTimerRef.current = setTimeout(() => {
|
|
6991
7043
|
fetchSuggestions(query);
|
|
@@ -6995,7 +7047,7 @@ function useQuerySuggestionsEnhanced(options) {
|
|
|
6995
7047
|
clearTimeout(debounceTimerRef.current);
|
|
6996
7048
|
}
|
|
6997
7049
|
};
|
|
6998
|
-
}, [query, enabled, minQueryLength, debounceMs, fetchSuggestions]);
|
|
7050
|
+
}, [query, enabled, prefetch, minQueryLength, debounceMs, fetchSuggestions]);
|
|
6999
7051
|
// Recent search management
|
|
7000
7052
|
const addRecentSearch = React.useCallback((searchQuery, resultsCount) => {
|
|
7001
7053
|
if (!enableRecentSearches || !searchQuery.trim())
|
|
@@ -9030,10 +9082,28 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9030
9082
|
const [isOpen, setIsOpenState] = React.useState(false);
|
|
9031
9083
|
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
9032
9084
|
const [activeTabId, setActiveTabId] = React.useState('');
|
|
9085
|
+
const [prefetchedProducts, setPrefetchedProducts] = React.useState([]);
|
|
9086
|
+
// Prefetch product results on mount so they're available instantly when dropdown opens
|
|
9087
|
+
const prefetchedProductsRef = React.useRef(false);
|
|
9088
|
+
React.useEffect(() => {
|
|
9089
|
+
if (prefetchedProductsRef.current || !client?.search)
|
|
9090
|
+
return;
|
|
9091
|
+
prefetchedProductsRef.current = true;
|
|
9092
|
+
client.search('*', { per_page: 12, page: 1 })
|
|
9093
|
+
.then((res) => {
|
|
9094
|
+
const data = res?.data;
|
|
9095
|
+
const items = data?.results || data?.data || res?.results || res?.hits || [];
|
|
9096
|
+
if (Array.isArray(items) && items.length > 0) {
|
|
9097
|
+
setPrefetchedProducts(items);
|
|
9098
|
+
}
|
|
9099
|
+
})
|
|
9100
|
+
.catch(() => { });
|
|
9101
|
+
}, [client]);
|
|
9033
9102
|
const suggestionsData = useQuerySuggestionsEnhanced({
|
|
9034
9103
|
client,
|
|
9035
9104
|
query,
|
|
9036
9105
|
enabled: isOpen,
|
|
9106
|
+
prefetch: minQueryLength === 0,
|
|
9037
9107
|
minQueryLength,
|
|
9038
9108
|
debounceMs,
|
|
9039
9109
|
maxSuggestions,
|
|
@@ -9051,7 +9121,22 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9051
9121
|
trackClicks: true,
|
|
9052
9122
|
trackImpressions: true,
|
|
9053
9123
|
});
|
|
9054
|
-
const { suggestions, recentSearches, trendingSearches, trendingProducts, filteredTabs: filteredTabsData, loading, error, hasContent, getAllNavigableItems, addRecentSearch, } = suggestionsData;
|
|
9124
|
+
const { suggestions, recentSearches, trendingSearches, trendingProducts, filteredTabs: filteredTabsData, loading, error, hasContent, getAllNavigableItems, addRecentSearch, clearRecentSearches, } = suggestionsData;
|
|
9125
|
+
// Wrap getAllNavigableItems to include prefetchedProducts when trendingProducts is empty
|
|
9126
|
+
const getAllNavigableItemsWithPrefetched = React.useCallback(() => {
|
|
9127
|
+
const items = getAllNavigableItems();
|
|
9128
|
+
// If there are already product items in the list, return as-is
|
|
9129
|
+
if (items.some(i => i.type === 'product'))
|
|
9130
|
+
return items;
|
|
9131
|
+
// Otherwise append prefetchedProducts as navigable product items
|
|
9132
|
+
if (prefetchedProducts.length > 0) {
|
|
9133
|
+
let idx = items.length;
|
|
9134
|
+
prefetchedProducts.forEach(product => {
|
|
9135
|
+
items.push({ type: 'product', index: idx++, data: product });
|
|
9136
|
+
});
|
|
9137
|
+
}
|
|
9138
|
+
return items;
|
|
9139
|
+
}, [getAllNavigableItems, prefetchedProducts]);
|
|
9055
9140
|
const onSearchRef = React.useRef(onSearch);
|
|
9056
9141
|
const onSuggestionSelectRef = React.useRef(onSuggestionSelect);
|
|
9057
9142
|
const onProductClickRef = React.useRef(onProductClick);
|
|
@@ -9129,19 +9214,19 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9129
9214
|
onSearchRef.current?.(trimmed);
|
|
9130
9215
|
}, [analytics, addRecentSearch, close]);
|
|
9131
9216
|
const navigateNext = React.useCallback(() => {
|
|
9132
|
-
const items =
|
|
9217
|
+
const items = getAllNavigableItemsWithPrefetched();
|
|
9133
9218
|
if (items.length === 0)
|
|
9134
9219
|
return;
|
|
9135
9220
|
setActiveIndex((i) => (i < items.length - 1 ? i + 1 : 0));
|
|
9136
|
-
}, [
|
|
9221
|
+
}, [getAllNavigableItemsWithPrefetched]);
|
|
9137
9222
|
const navigatePrev = React.useCallback(() => {
|
|
9138
|
-
const items =
|
|
9223
|
+
const items = getAllNavigableItemsWithPrefetched();
|
|
9139
9224
|
if (items.length === 0)
|
|
9140
9225
|
return;
|
|
9141
9226
|
setActiveIndex((i) => (i <= 0 ? items.length - 1 : i - 1));
|
|
9142
|
-
}, [
|
|
9227
|
+
}, [getAllNavigableItemsWithPrefetched]);
|
|
9143
9228
|
const selectActive = React.useCallback(() => {
|
|
9144
|
-
const items =
|
|
9229
|
+
const items = getAllNavigableItemsWithPrefetched();
|
|
9145
9230
|
if (activeIndex < 0 || activeIndex >= items.length) {
|
|
9146
9231
|
submitSearch(query);
|
|
9147
9232
|
return;
|
|
@@ -9163,7 +9248,7 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9163
9248
|
default:
|
|
9164
9249
|
submitSearch(query);
|
|
9165
9250
|
}
|
|
9166
|
-
}, [activeIndex,
|
|
9251
|
+
}, [activeIndex, getAllNavigableItemsWithPrefetched, query, submitSearch, selectSuggestion, selectProduct, selectRecentSearch, selectTrendingSearch]);
|
|
9167
9252
|
// Impression when open and content changes
|
|
9168
9253
|
React.useEffect(() => {
|
|
9169
9254
|
if (!isOpen || !hasContent || !query)
|
|
@@ -9186,19 +9271,21 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9186
9271
|
recentSearches,
|
|
9187
9272
|
trendingSearches,
|
|
9188
9273
|
trendingProducts,
|
|
9274
|
+
prefetchedProducts,
|
|
9189
9275
|
filteredTabs: filteredTabsData,
|
|
9190
9276
|
activeTabId,
|
|
9191
9277
|
setActiveTabId,
|
|
9192
9278
|
loading,
|
|
9193
9279
|
error,
|
|
9194
9280
|
hasContent,
|
|
9195
|
-
getAllNavigableItems,
|
|
9281
|
+
getAllNavigableItems: getAllNavigableItemsWithPrefetched,
|
|
9196
9282
|
selectSuggestion,
|
|
9197
9283
|
selectProduct,
|
|
9198
9284
|
selectRecentSearch,
|
|
9199
9285
|
selectTrendingSearch,
|
|
9200
9286
|
setActiveTab,
|
|
9201
9287
|
submitSearch,
|
|
9288
|
+
clearRecentSearches,
|
|
9202
9289
|
close,
|
|
9203
9290
|
navigateNext,
|
|
9204
9291
|
navigatePrev,
|
|
@@ -9214,19 +9301,21 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
9214
9301
|
recentSearches,
|
|
9215
9302
|
trendingSearches,
|
|
9216
9303
|
trendingProducts,
|
|
9304
|
+
prefetchedProducts,
|
|
9217
9305
|
filteredTabsData,
|
|
9218
9306
|
activeTabId,
|
|
9219
9307
|
setActiveTabId,
|
|
9220
9308
|
loading,
|
|
9221
9309
|
error,
|
|
9222
9310
|
hasContent,
|
|
9223
|
-
|
|
9311
|
+
getAllNavigableItemsWithPrefetched,
|
|
9224
9312
|
selectSuggestion,
|
|
9225
9313
|
selectProduct,
|
|
9226
9314
|
selectRecentSearch,
|
|
9227
9315
|
selectTrendingSearch,
|
|
9228
9316
|
setActiveTab,
|
|
9229
9317
|
submitSearch,
|
|
9318
|
+
clearRecentSearches,
|
|
9230
9319
|
close,
|
|
9231
9320
|
navigateNext,
|
|
9232
9321
|
navigatePrev,
|
|
@@ -9317,14 +9406,14 @@ function SearchInput({ placeholder = 'Powered by Seekora', autoFocus = false, sh
|
|
|
9317
9406
|
}, [setQuery]);
|
|
9318
9407
|
return (React.createElement("div", { className: clsx('seekora-suggestions-search-input-wrapper', className), style: { ...defaultStyles, ...style } },
|
|
9319
9408
|
React.createElement("div", { className: "seekora-suggestions-input-wrapper", style: inputWrapperStyles },
|
|
9320
|
-
leftIcon ? (React.createElement("span", { className: "seekora-suggestions-input-left-icon", style: { display: 'flex', flexShrink: 0, color: '
|
|
9409
|
+
leftIcon ? (React.createElement("span", { className: "seekora-suggestions-input-left-icon", style: { display: 'flex', flexShrink: 0, color: 'inherit', opacity: 0.5 } }, leftIcon)) : null,
|
|
9321
9410
|
React.createElement("input", { ref: inputRef, type: "text", value: query, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, placeholder: placeholder, autoFocus: autoFocus, autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false, "aria-label": ariaLabel, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-autocomplete": "list", role: "combobox", className: clsx('seekora-suggestions-input', inputClassName), style: { ...inputStyles, ...inputStyle } }),
|
|
9322
9411
|
showClearButton && query ? (React.createElement("button", { type: "button", onClick: handleClear, className: "seekora-suggestions-input-clear", "aria-label": "Clear search", style: {
|
|
9323
9412
|
padding: 8,
|
|
9324
9413
|
border: 'none',
|
|
9325
9414
|
background: 'transparent',
|
|
9326
9415
|
cursor: 'pointer',
|
|
9327
|
-
color: '
|
|
9416
|
+
color: 'inherit', opacity: 0.5,
|
|
9328
9417
|
display: 'flex',
|
|
9329
9418
|
alignItems: 'center',
|
|
9330
9419
|
justifyContent: 'center',
|
|
@@ -9475,7 +9564,7 @@ const defaultItemStyle = {
|
|
|
9475
9564
|
fontSize: 'inherit',
|
|
9476
9565
|
fontFamily: 'inherit',
|
|
9477
9566
|
backgroundColor: 'transparent',
|
|
9478
|
-
color: '
|
|
9567
|
+
color: 'inherit',
|
|
9479
9568
|
transition: 'background-color 120ms ease',
|
|
9480
9569
|
overflow: 'hidden',
|
|
9481
9570
|
textOverflow: 'ellipsis',
|
|
@@ -9492,14 +9581,14 @@ function SuggestionItem({ suggestion, index, isActive, onSelect, className, styl
|
|
|
9492
9581
|
const showHighlight = isActive || isHovered;
|
|
9493
9582
|
return (React.createElement("li", { role: "option", "aria-selected": isActive, id: `seekora-suggestion-${index}`, className: clsx('seekora-suggestions-item', isActive && 'seekora-suggestions-item--active', isHovered && 'seekora-suggestions-item--hover', className), style: {
|
|
9494
9583
|
...defaultItemStyle,
|
|
9495
|
-
...(showHighlight ? { backgroundColor: 'var(--seekora-bg-hover,
|
|
9584
|
+
...(showHighlight ? { backgroundColor: 'var(--seekora-bg-hover, rgba(0,0,0,0.05))' } : {}),
|
|
9496
9585
|
...style,
|
|
9497
9586
|
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onMouseDown: (e) => {
|
|
9498
9587
|
e.preventDefault();
|
|
9499
9588
|
onSelect();
|
|
9500
9589
|
} },
|
|
9501
9590
|
content,
|
|
9502
|
-
suggestion.count != null ? (React.createElement("span", { className: "seekora-suggestions-item-count", style: { marginLeft: 8, color: '
|
|
9591
|
+
suggestion.count != null ? (React.createElement("span", { className: "seekora-suggestions-item-count", style: { marginLeft: 8, color: 'inherit', opacity: 0.6, fontSize: '0.875em' } }, suggestion.count)) : null));
|
|
9503
9592
|
}
|
|
9504
9593
|
|
|
9505
9594
|
/**
|
|
@@ -10185,7 +10274,7 @@ const imgStyle$1 = {
|
|
|
10185
10274
|
aspectRatio: 'var(--seekora-card-aspect-ratio, 1)',
|
|
10186
10275
|
objectFit: 'cover',
|
|
10187
10276
|
borderRadius: BORDER_RADIUS$3.sm,
|
|
10188
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
10277
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(0,0,0,0.04))',
|
|
10189
10278
|
display: 'block',
|
|
10190
10279
|
overflow: 'hidden',
|
|
10191
10280
|
};
|
|
@@ -10211,7 +10300,7 @@ function ItemCard({ item, position, onSelect, className, style, asLink = true, i
|
|
|
10211
10300
|
// Hover style
|
|
10212
10301
|
const cardHoverStyle = isHovered
|
|
10213
10302
|
? {
|
|
10214
|
-
backgroundColor: 'var(--seekora-card-hover-bg, var(--seekora-bg-hover,
|
|
10303
|
+
backgroundColor: 'var(--seekora-card-hover-bg, var(--seekora-bg-hover, rgba(0,0,0,0.03)))',
|
|
10215
10304
|
boxShadow: 'var(--seekora-card-hover-shadow, 0 2px 8px rgba(0, 0, 0, 0.08))',
|
|
10216
10305
|
}
|
|
10217
10306
|
: {};
|
|
@@ -10220,7 +10309,7 @@ function ItemCard({ item, position, onSelect, className, style, asLink = true, i
|
|
|
10220
10309
|
actionButtons && actionButtons.length > 0 && actionButtonsPosition?.startsWith('overlay') && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" })))) : (React.createElement("div", { className: "seekora-item-card-placeholder", style: { ...imgStyle$1, ...(isHorizontal ? { minWidth: imageMinWidth, flexBasis: imageFlex, maxWidth: imageMaxWidth, height: imageHeight, flexShrink: 0 } : {}) }, "aria-hidden": true }));
|
|
10221
10310
|
const textBlock = (React.createElement("div", { style: isHorizontal ? { display: 'flex', flexDirection: 'column', gap: textGap, flex: 1, minWidth: 0 } : undefined },
|
|
10222
10311
|
React.createElement("span", { className: "seekora-item-card-title", style: { fontSize: titleFontSize, fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: isHorizontal ? 2 : 3, WebkitBoxOrient: 'vertical' } }, String(title)),
|
|
10223
|
-
description ? (React.createElement("span", { className: "seekora-item-card-description", style: { fontSize: descriptionFontSize, color: '
|
|
10312
|
+
description ? (React.createElement("span", { className: "seekora-item-card-description", style: { fontSize: descriptionFontSize, color: 'inherit', opacity: 0.6, lineHeight: 1.3, display: '-webkit-box', WebkitLineClamp: lineClamp, WebkitBoxOrient: 'vertical', overflow: 'hidden' } }, String(description))) : null,
|
|
10224
10313
|
actionButtons && actionButtons.length > 0 && actionButtonsPosition === 'inline' && (React.createElement(ActionButtons, { buttons: actionButtons, position: "inline", showLabels: showActionLabels, size: "small", layout: "horizontal" }))));
|
|
10225
10314
|
const content = isHorizontal ? (React.createElement("div", { style: { display: 'flex', gap: horizontalGap, alignItems: 'flex-start' } },
|
|
10226
10315
|
imageBlock,
|
|
@@ -11215,7 +11304,7 @@ const imgPlaceholderStyle = {
|
|
|
11215
11304
|
aspectRatio: '1',
|
|
11216
11305
|
objectFit: 'cover',
|
|
11217
11306
|
borderRadius: BORDER_RADIUS$1.sm,
|
|
11218
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
11307
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(0,0,0,0.04))',
|
|
11219
11308
|
};
|
|
11220
11309
|
function ImageBlock({ images, title, imageVariant, aspectRatio, enableZoom, zoomMode, zoomLevel }) {
|
|
11221
11310
|
const ar = aspectRatio
|
|
@@ -11235,7 +11324,7 @@ function MinimalLayout({ images, title, price, product, imageVariant, displayCon
|
|
|
11235
11324
|
return (React.createElement(React.Fragment, null,
|
|
11236
11325
|
React.createElement(ImageBlock, { images: images, title: title, imageVariant: imageVariant, aspectRatio: displayConfig.imageAspectRatio, enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel }),
|
|
11237
11326
|
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: titleFontSize, fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' } }, title),
|
|
11238
|
-
price != null && !Number.isNaN(price) && (React.createElement("span", { className: "seekora-product-card__price seekora-suggestions-product-card-price", style: { fontSize: priceFontSize, color: '
|
|
11327
|
+
price != null && !Number.isNaN(price) && (React.createElement("span", { className: "seekora-product-card__price seekora-suggestions-product-card-price", style: { fontSize: priceFontSize, color: 'inherit', opacity: 0.6 } },
|
|
11239
11328
|
product.currency ?? '$',
|
|
11240
11329
|
price.toFixed(2)))));
|
|
11241
11330
|
}
|
|
@@ -11255,7 +11344,7 @@ function StandardLayout({ images, title, price, comparePrice, brand, badges, opt
|
|
|
11255
11344
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left", maxBadges: 2 })),
|
|
11256
11345
|
actionButtons && actionButtons.length > 0 && isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
11257
11346
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: bodyGap } },
|
|
11258
|
-
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: brandFontSize, color: '
|
|
11347
|
+
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: brandFontSize, color: 'inherit', opacity: 0.6, textTransform: 'uppercase', letterSpacing: '0.02em' } }, brand)),
|
|
11259
11348
|
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: titleFontSize, fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical' } }, title),
|
|
11260
11349
|
React.createElement("div", { className: "seekora-product-card__price" },
|
|
11261
11350
|
React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: priceFontSize } })),
|
|
@@ -11274,7 +11363,7 @@ function DetailedLayout({ images, title, price, comparePrice, brand, badges, pri
|
|
|
11274
11363
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left" })),
|
|
11275
11364
|
actionButtons && actionButtons.length > 0 && isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
11276
11365
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: 4 } },
|
|
11277
|
-
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: '0.75rem', color: '
|
|
11366
|
+
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: '0.75rem', color: 'inherit', opacity: 0.6, textTransform: 'uppercase', letterSpacing: '0.02em' } }, brand)),
|
|
11278
11367
|
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis' } }, title),
|
|
11279
11368
|
cfg.showRating !== false && product.rating != null && (React.createElement(RatingDisplay, { rating: product.rating, reviewCount: product.reviewCount, variant: "compact", size: "small", showNumeric: false, showReviewCount: true, className: "seekora-product-card__rating" })),
|
|
11280
11369
|
React.createElement("div", { className: "seekora-product-card__price" }, cfg.showPriceRange && priceRange ? (React.createElement(PriceDisplay, { priceRange: priceRange, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, style: { fontSize: '0.875rem' } })) : (React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: '0.875rem' } }))),
|
|
@@ -11296,7 +11385,7 @@ function CompactLayout({ images, title, price, product, imageVariant, displayCon
|
|
|
11296
11385
|
textOverflow: 'ellipsis',
|
|
11297
11386
|
whiteSpace: 'nowrap',
|
|
11298
11387
|
} }, title),
|
|
11299
|
-
price != null && !Number.isNaN(price) && (React.createElement("span", { className: "seekora-product-card__price", style: { fontSize: '0.8125rem', color: '
|
|
11388
|
+
price != null && !Number.isNaN(price) && (React.createElement("span", { className: "seekora-product-card__price", style: { fontSize: '0.8125rem', color: 'inherit', opacity: 0.6 } },
|
|
11300
11389
|
product.currency ?? '$',
|
|
11301
11390
|
price.toFixed(2)))));
|
|
11302
11391
|
}
|
|
@@ -11320,7 +11409,7 @@ function HorizontalLayout({ images, title, price, comparePrice, brand, badges, o
|
|
|
11320
11409
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left", maxBadges: 1 })),
|
|
11321
11410
|
actionButtons && actionButtons.length > 0 && actionButtonsPosition?.startsWith('overlay') && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
11322
11411
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: bodyGap, flex: 1, minWidth: 0 } },
|
|
11323
|
-
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: brandFontSize, color: '
|
|
11412
|
+
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: brandFontSize, color: 'inherit', opacity: 0.6, textTransform: 'uppercase' } }, brand)),
|
|
11324
11413
|
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: titleFontSize, fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis', display: '-webkit-box', WebkitLineClamp: isMobile ? 3 : 2, WebkitBoxOrient: 'vertical' } }, title),
|
|
11325
11414
|
React.createElement("div", { className: "seekora-product-card__price" },
|
|
11326
11415
|
React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: priceFontSize } })),
|
|
@@ -11356,7 +11445,7 @@ const imgStyle = {
|
|
|
11356
11445
|
aspectRatio: '1',
|
|
11357
11446
|
objectFit: 'cover',
|
|
11358
11447
|
borderRadius: BORDER_RADIUS.sm,
|
|
11359
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
11448
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(0,0,0,0.04))',
|
|
11360
11449
|
};
|
|
11361
11450
|
function ProductCard({ product, position, section, tabId, onSelect, className, style, imageVariant = 'single', displayConfig, onVariantHover, onVariantClick, selectedVariants, asLink, actionButtons, actionButtonsPosition = 'inline', showActionLabels = false, enableImageZoom = false, imageZoomMode = 'both', imageZoomLevel = 2.5, }) {
|
|
11362
11451
|
// Find selected variant if selections are provided
|
|
@@ -11405,7 +11494,7 @@ function ProductCard({ product, position, section, tabId, onSelect, className, s
|
|
|
11405
11494
|
const [isHovered, setIsHovered] = React.useState(false);
|
|
11406
11495
|
const cardHoverStyle = isHovered
|
|
11407
11496
|
? {
|
|
11408
|
-
backgroundColor: 'var(--seekora-card-hover-bg, var(--seekora-bg-hover,
|
|
11497
|
+
backgroundColor: 'var(--seekora-card-hover-bg, var(--seekora-bg-hover, rgba(0,0,0,0.03)))',
|
|
11409
11498
|
boxShadow: 'var(--seekora-card-hover-shadow, 0 2px 8px rgba(0, 0, 0, 0.08))',
|
|
11410
11499
|
}
|
|
11411
11500
|
: {};
|
|
@@ -11419,7 +11508,7 @@ function ProductCard({ product, position, section, tabId, onSelect, className, s
|
|
|
11419
11508
|
}, "data-position": position, "data-section": section, "data-tab-id": tabId },
|
|
11420
11509
|
images.length > 0 ? (React.createElement(ImageDisplay, { images: images, variant: imageVariant, alt: title, className: "seekora-suggestions-product-card-image", enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel })) : (React.createElement("div", { className: "seekora-suggestions-product-card-placeholder", style: imgStyle, "aria-hidden": true })),
|
|
11421
11510
|
React.createElement("span", { className: "seekora-suggestions-product-card-title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
11422
|
-
price != null && !Number.isNaN(price) ? (React.createElement("span", { className: "seekora-suggestions-product-card-price", style: { fontSize: '0.875rem', color: '
|
|
11511
|
+
price != null && !Number.isNaN(price) ? (React.createElement("span", { className: "seekora-suggestions-product-card-price", style: { fontSize: '0.875rem', color: 'inherit', opacity: 0.6 } },
|
|
11423
11512
|
product.currency ?? '$',
|
|
11424
11513
|
price.toFixed(2))) : null));
|
|
11425
11514
|
}
|
|
@@ -11555,7 +11644,7 @@ function CategoriesTabs({ className, style, tabClassName }) {
|
|
|
11555
11644
|
border: 'none',
|
|
11556
11645
|
borderRadius: 'var(--seekora-border-radius, 6px)',
|
|
11557
11646
|
backgroundColor: isActive ? 'var(--seekora-primary-light, rgba(59, 130, 246, 0.1))' : 'transparent',
|
|
11558
|
-
color: isActive ? 'var(--seekora-primary, #3b82f6)' : '
|
|
11647
|
+
color: isActive ? 'var(--seekora-primary, #3b82f6)' : 'inherit',
|
|
11559
11648
|
cursor: 'pointer',
|
|
11560
11649
|
fontSize: '0.875rem',
|
|
11561
11650
|
fontWeight: isActive ? 600 : 400,
|
|
@@ -11579,7 +11668,7 @@ const itemStyle$1 = {
|
|
|
11579
11668
|
fontSize: 'inherit',
|
|
11580
11669
|
fontFamily: 'inherit',
|
|
11581
11670
|
backgroundColor: 'transparent',
|
|
11582
|
-
color: '
|
|
11671
|
+
color: 'inherit',
|
|
11583
11672
|
transition: 'background-color 120ms ease',
|
|
11584
11673
|
};
|
|
11585
11674
|
function RecentSearchItem({ search, onSelect }) {
|
|
@@ -11587,7 +11676,7 @@ function RecentSearchItem({ search, onSelect }) {
|
|
|
11587
11676
|
return (React.createElement("li", null,
|
|
11588
11677
|
React.createElement("button", { type: "button", className: clsx('seekora-suggestions-recent-item', isHovered && 'seekora-suggestions-recent-item--hover'), style: {
|
|
11589
11678
|
...itemStyle$1,
|
|
11590
|
-
...(isHovered ? { backgroundColor: 'var(--seekora-bg-hover,
|
|
11679
|
+
...(isHovered ? { backgroundColor: 'var(--seekora-bg-hover, rgba(0,0,0,0.05))' } : {}),
|
|
11591
11680
|
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onMouseDown: (e) => {
|
|
11592
11681
|
e.preventDefault();
|
|
11593
11682
|
onSelect();
|
|
@@ -11599,7 +11688,7 @@ function RecentSearchesList({ title = 'Recent', maxItems = 8, className, style,
|
|
|
11599
11688
|
if (items.length === 0)
|
|
11600
11689
|
return null;
|
|
11601
11690
|
return (React.createElement("div", { className: clsx('seekora-suggestions-recent-list', className), style: style },
|
|
11602
|
-
title ? (React.createElement("div", { className: "seekora-suggestions-recent-title", style: { padding: '8px 12px', fontSize: '0.75rem', fontWeight: 600, color: '
|
|
11691
|
+
title ? (React.createElement("div", { className: "seekora-suggestions-recent-title", style: { padding: '8px 12px', fontSize: '0.75rem', fontWeight: 600, color: 'inherit', opacity: 0.6, textTransform: 'uppercase' } }, title)) : null,
|
|
11603
11692
|
React.createElement("ul", { className: clsx('seekora-suggestions-recent-ul', listClassName), style: { margin: 0, padding: 0, listStyle: 'none' } }, items.map((search, i) => {
|
|
11604
11693
|
const onSelect = () => selectRecentSearch(search);
|
|
11605
11694
|
if (renderItem) {
|
|
@@ -11623,7 +11712,7 @@ const itemStyle = {
|
|
|
11623
11712
|
fontSize: 'inherit',
|
|
11624
11713
|
fontFamily: 'inherit',
|
|
11625
11714
|
backgroundColor: 'transparent',
|
|
11626
|
-
color: '
|
|
11715
|
+
color: 'inherit',
|
|
11627
11716
|
transition: 'background-color 120ms ease',
|
|
11628
11717
|
};
|
|
11629
11718
|
function TrendingItem({ trending, onSelect }) {
|
|
@@ -11631,13 +11720,13 @@ function TrendingItem({ trending, onSelect }) {
|
|
|
11631
11720
|
return (React.createElement("li", null,
|
|
11632
11721
|
React.createElement("button", { type: "button", className: clsx('seekora-suggestions-trending-item', isHovered && 'seekora-suggestions-trending-item--hover'), style: {
|
|
11633
11722
|
...itemStyle,
|
|
11634
|
-
...(isHovered ? { backgroundColor: 'var(--seekora-bg-hover,
|
|
11723
|
+
...(isHovered ? { backgroundColor: 'var(--seekora-bg-hover, rgba(0,0,0,0.05))' } : {}),
|
|
11635
11724
|
}, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onMouseDown: (e) => {
|
|
11636
11725
|
e.preventDefault();
|
|
11637
11726
|
onSelect();
|
|
11638
11727
|
} },
|
|
11639
11728
|
trending.query,
|
|
11640
|
-
trending.count != null ? (React.createElement("span", { style: { marginLeft: 8, color: '
|
|
11729
|
+
trending.count != null ? (React.createElement("span", { style: { marginLeft: 8, color: 'inherit', opacity: 0.6, fontSize: '0.875em' } }, trending.count)) : null)));
|
|
11641
11730
|
}
|
|
11642
11731
|
function TrendingList({ title = 'Trending', maxItems = 8, className, style, listClassName, renderItem, }) {
|
|
11643
11732
|
const { trendingSearches, selectTrendingSearch } = useSuggestionsContext();
|
|
@@ -11645,7 +11734,7 @@ function TrendingList({ title = 'Trending', maxItems = 8, className, style, list
|
|
|
11645
11734
|
if (items.length === 0)
|
|
11646
11735
|
return null;
|
|
11647
11736
|
return (React.createElement("div", { className: clsx('seekora-suggestions-trending-list', className), style: style },
|
|
11648
|
-
title ? (React.createElement("div", { className: "seekora-suggestions-trending-title", style: { padding: '8px 12px', fontSize: '0.75rem', fontWeight: 600, color: '
|
|
11737
|
+
title ? (React.createElement("div", { className: "seekora-suggestions-trending-title", style: { padding: '8px 12px', fontSize: '0.75rem', fontWeight: 600, color: 'inherit', opacity: 0.6, textTransform: 'uppercase' } }, title)) : null,
|
|
11649
11738
|
React.createElement("ul", { className: clsx('seekora-suggestions-trending-ul', listClassName), style: { margin: 0, padding: 0, listStyle: 'none' } }, items.map((trending, i) => {
|
|
11650
11739
|
const onSelect = () => selectTrendingSearch(trending, i);
|
|
11651
11740
|
if (renderItem) {
|