@seekora-ai/ui-sdk-react 0.2.15 → 0.2.17
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/FacetDropdown.d.ts +2 -0
- package/dist/components/FacetDropdown.d.ts.map +1 -1
- package/dist/components/FacetDropdown.js +47 -25
- package/dist/components/Facets.d.ts +4 -0
- package/dist/components/Facets.d.ts.map +1 -1
- package/dist/components/Facets.js +21 -2
- package/dist/components/InfiniteHits.d.ts +0 -7
- package/dist/components/InfiniteHits.d.ts.map +1 -1
- package/dist/components/InfiniteHits.js +2 -13
- package/dist/components/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination.js +27 -9
- package/dist/components/QuerySuggestions.d.ts +0 -4
- package/dist/components/QuerySuggestions.d.ts.map +1 -1
- package/dist/components/QuerySuggestions.js +1 -17
- package/dist/components/QuerySuggestionsDropdown.d.ts +0 -4
- package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -1
- package/dist/components/QuerySuggestionsDropdown.js +1 -16
- package/dist/components/Recommendations.d.ts +0 -7
- package/dist/components/Recommendations.d.ts.map +1 -1
- package/dist/components/Recommendations.js +3 -23
- package/dist/components/RichQuerySuggestions.d.ts +0 -4
- package/dist/components/RichQuerySuggestions.d.ts.map +1 -1
- package/dist/components/RichQuerySuggestions.js +1 -10
- package/dist/components/SearchBar.d.ts +0 -4
- package/dist/components/SearchBar.d.ts.map +1 -1
- package/dist/components/SearchBar.js +2 -4
- package/dist/components/SearchBarWithSuggestions.js +1 -1
- package/dist/components/SearchLayout.d.ts.map +1 -1
- package/dist/components/SearchLayout.js +13 -17
- package/dist/components/SearchProvider.d.ts.map +1 -1
- package/dist/components/SearchProvider.js +1 -3
- package/dist/components/SearchResults.d.ts +0 -6
- package/dist/components/SearchResults.d.ts.map +1 -1
- package/dist/components/SearchResults.js +1 -14
- package/dist/components/primitives/ImageDisplay.d.ts.map +1 -1
- package/dist/components/primitives/ImageDisplay.js +24 -14
- package/dist/components/primitives/ImageZoom.d.ts.map +1 -1
- package/dist/components/primitives/ImageZoom.js +59 -4
- package/dist/components/primitives/VariantSwatches.d.ts.map +1 -1
- package/dist/components/primitives/VariantSwatches.js +25 -10
- package/dist/components/section-primitives/SectionItemGrid.d.ts +1 -3
- package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -1
- package/dist/components/section-primitives/SectionItemGrid.js +1 -4
- package/dist/components/section-primitives/index.d.ts +0 -1
- package/dist/components/section-primitives/index.d.ts.map +1 -1
- package/dist/components/section-primitives/index.js +0 -1
- package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/AmazonDropdown.js +3 -21
- package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/GoogleDropdown.js +3 -20
- package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/MinimalDropdown.js +2 -2
- package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/MobileSheetDropdown.js +60 -60
- package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/PinterestDropdown.js +41 -41
- package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/ShopifyDropdown.js +3 -4
- package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -1
- package/dist/components/suggestions/SpotlightDropdown.js +2 -3
- package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -1
- package/dist/components/suggestions/SuggestionSearchBar.js +2 -15
- package/dist/components/suggestions/types.d.ts +0 -6
- package/dist/components/suggestions/types.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ItemCard.js +32 -8
- package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ItemGrid.js +9 -2
- package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ProductCard.js +14 -5
- package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ProductCardLayouts.js +32 -12
- package/dist/components/suggestions-primitives/ProductGrid.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ProductGrid.js +8 -3
- package/dist/components/suggestions-primitives/RecentSearchesList.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/RecentSearchesList.js +12 -5
- package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SearchInput.js +1 -1
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SuggestionItem.js +5 -3
- package/dist/components/suggestions-primitives/SuggestionList.d.ts +1 -8
- package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SuggestionList.js +1 -7
- package/dist/components/suggestions-primitives/TrendingList.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/TrendingList.js +14 -7
- package/dist/components/suggestions-primitives/index.d.ts +1 -3
- package/dist/components/suggestions-primitives/index.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/index.js +1 -2
- package/dist/docsearch/components/DocSearch.d.ts.map +1 -1
- package/dist/docsearch/components/DocSearch.js +1 -1
- package/dist/docsearch/components/Footer.d.ts.map +1 -1
- package/dist/docsearch/components/Footer.js +11 -1
- package/dist/docsearch/components/Results.d.ts +1 -3
- package/dist/docsearch/components/Results.d.ts.map +1 -1
- package/dist/docsearch/components/Results.js +1 -9
- package/dist/docsearch/components/SearchBox.d.ts +1 -2
- package/dist/docsearch/components/SearchBox.d.ts.map +1 -1
- package/dist/docsearch/components/SearchBox.js +4 -6
- package/dist/docsearch/hooks/useDocSearch.d.ts.map +1 -1
- package/dist/docsearch/hooks/useDocSearch.js +25 -12
- package/dist/docsearch/hooks/useSeekoraSearch.d.ts.map +1 -1
- package/dist/docsearch/hooks/useSeekoraSearch.js +6 -0
- package/dist/docsearch/types.d.ts +0 -1
- package/dist/docsearch/types.d.ts.map +1 -1
- package/dist/docsearch.css +2 -5
- package/dist/hooks/useClickTracking.d.ts.map +1 -1
- package/dist/hooks/useClickTracking.js +4 -11
- package/dist/hooks/useExperiment.d.ts.map +1 -1
- package/dist/hooks/useExperiment.js +10 -33
- package/dist/hooks/useFilters.d.ts +27 -0
- package/dist/hooks/useFilters.d.ts.map +1 -0
- package/dist/hooks/useFilters.js +66 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +39 -79
- package/dist/src/index.esm.js +836 -465
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +836 -466
- package/dist/src/index.js.map +1 -1
- package/dist/utils/responsive.d.ts +130 -0
- package/dist/utils/responsive.d.ts.map +1 -0
- package/dist/utils/responsive.js +231 -0
- package/package.json +7 -7
- package/src/docsearch/docsearch.css +2 -5
|
@@ -10,16 +10,12 @@
|
|
|
10
10
|
import React, { useEffect, useState, useMemo } from 'react';
|
|
11
11
|
import { useSearchContext } from './SearchProvider';
|
|
12
12
|
import { clsx } from 'clsx';
|
|
13
|
-
export const RelatedProducts = ({ productId, items: itemsProp, loading: loadingProp = false,
|
|
13
|
+
export const RelatedProducts = ({ productId, items: itemsProp, loading: loadingProp = false, title = 'Related Products', maxItems = 6, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
|
|
14
14
|
const { theme } = useSearchContext();
|
|
15
15
|
const recommendationTheme = customTheme || {};
|
|
16
16
|
// If items are provided, use them directly
|
|
17
17
|
const items = itemsProp?.slice(0, maxItems) || [];
|
|
18
18
|
const loading = loadingProp;
|
|
19
|
-
if (loading && items.length === 0 && showLoadingState) {
|
|
20
|
-
return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
|
|
21
|
-
React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading related products...")));
|
|
22
|
-
}
|
|
23
19
|
if (loading && items.length === 0)
|
|
24
20
|
return null;
|
|
25
21
|
if (items.length === 0) {
|
|
@@ -27,15 +23,11 @@ export const RelatedProducts = ({ productId, items: itemsProp, loading: loadingP
|
|
|
27
23
|
}
|
|
28
24
|
return (React.createElement(RecommendationSection, { title: title, items: items, renderItem: renderItem, onItemClick: onItemClick, className: className, style: style, theme: customTheme, layout: layout, currencySymbol: currencySymbol }));
|
|
29
25
|
};
|
|
30
|
-
export const TrendingItems = ({ items: itemsProp, loading: loadingProp = false,
|
|
26
|
+
export const TrendingItems = ({ items: itemsProp, loading: loadingProp = false, title = 'Trending Now', maxItems = 8, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
|
|
31
27
|
const { theme } = useSearchContext();
|
|
32
28
|
const recommendationTheme = customTheme || {};
|
|
33
29
|
const items = itemsProp?.slice(0, maxItems) || [];
|
|
34
30
|
const loading = loadingProp;
|
|
35
|
-
if (loading && items.length === 0 && showLoadingState) {
|
|
36
|
-
return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
|
|
37
|
-
React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading trending items...")));
|
|
38
|
-
}
|
|
39
31
|
if (loading && items.length === 0)
|
|
40
32
|
return null;
|
|
41
33
|
if (items.length === 0) {
|
|
@@ -43,7 +35,7 @@ export const TrendingItems = ({ items: itemsProp, loading: loadingProp = false,
|
|
|
43
35
|
}
|
|
44
36
|
return (React.createElement(RecommendationSection, { title: title, items: items, renderItem: renderItem, onItemClick: onItemClick, className: className, style: style, theme: customTheme, layout: layout, currencySymbol: currencySymbol }));
|
|
45
37
|
};
|
|
46
|
-
export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading: loadingProp = false,
|
|
38
|
+
export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading: loadingProp = false, title = 'Frequently Bought Together', maxItems = 4, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', showAddAllButton = true, onAddAll, }) => {
|
|
47
39
|
const { theme } = useSearchContext();
|
|
48
40
|
const recommendationTheme = customTheme || {};
|
|
49
41
|
const items = itemsProp?.slice(0, maxItems) || [];
|
|
@@ -56,10 +48,6 @@ export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading:
|
|
|
56
48
|
return sum + price;
|
|
57
49
|
}, 0);
|
|
58
50
|
}, [items]);
|
|
59
|
-
if (loading && items.length === 0 && showLoadingState) {
|
|
60
|
-
return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
|
|
61
|
-
React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading recommendations...")));
|
|
62
|
-
}
|
|
63
51
|
if (loading && items.length === 0)
|
|
64
52
|
return null;
|
|
65
53
|
if (items.length === 0) {
|
|
@@ -266,11 +254,3 @@ const DefaultRecommendationItem = ({ item, theme: recommendationTheme, currencyS
|
|
|
266
254
|
currencySymbol,
|
|
267
255
|
typeof price === 'number' ? price.toFixed(2) : price)))));
|
|
268
256
|
};
|
|
269
|
-
// Helper function
|
|
270
|
-
function getLoadingStyle(theme) {
|
|
271
|
-
return {
|
|
272
|
-
padding: theme.spacing.large,
|
|
273
|
-
textAlign: 'center',
|
|
274
|
-
color: theme.colors.textSecondary,
|
|
275
|
-
};
|
|
276
|
-
}
|
|
@@ -57,10 +57,6 @@ export interface RichQuerySuggestionsProps extends QuerySuggestionsEventHandlers
|
|
|
57
57
|
header?: React.ReactNode;
|
|
58
58
|
/** Custom footer content */
|
|
59
59
|
footer?: React.ReactNode;
|
|
60
|
-
/** Show loading overlay when fetching (default false: show previous results until new results render) */
|
|
61
|
-
showLoadingOverlay?: boolean;
|
|
62
|
-
/** Custom render for loading overlay (only when showLoadingOverlay is true) */
|
|
63
|
-
renderLoading?: () => React.ReactNode;
|
|
64
60
|
/** Dropdown width */
|
|
65
61
|
width?: string | number;
|
|
66
62
|
/** Dropdown max height */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/RichQuerySuggestions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EAGd,kBAAkB,EAClB,0BAA0B,EAC1B,6BAA6B,EAE7B,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAuBlC,MAAM,WAAW,yBAA0B,SAAQ,6BAA6B;IAC9E,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACnC,sCAAsC;IACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,sEAAsE;IACtE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yBAAyB;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,wBAAwB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IACtF,sCAAsC;IACtC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,KAAK,CAAC,SAAS,CAAC;IACnE,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,
|
|
1
|
+
{"version":3,"file":"RichQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/RichQuerySuggestions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EAGd,kBAAkB,EAClB,0BAA0B,EAC1B,6BAA6B,EAE7B,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAuBlC,MAAM,WAAW,yBAA0B,SAAQ,6BAA6B;IAC9E,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACnC,sCAAsC;IACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,sEAAsE;IACtE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yBAAyB;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,wBAAwB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IACtF,sCAAsC;IACtC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,KAAK,CAAC,SAAS,CAAC;IACnE,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACtC,cAAc,CAAC,EAAE,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,YAAY,CAAC;KACrE,CAAC;CACH;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,MAAM,CAAC;CAC7B;AA6OD,eAAO,MAAM,oBAAoB,2GA+bhC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
|
|
@@ -210,14 +210,6 @@ const styles = {
|
|
|
210
210
|
fontSize: '12px',
|
|
211
211
|
color: 'var(--seekora-text-secondary, inherit)',
|
|
212
212
|
},
|
|
213
|
-
loadingOverlay: {
|
|
214
|
-
position: 'absolute',
|
|
215
|
-
inset: 0,
|
|
216
|
-
display: 'flex',
|
|
217
|
-
alignItems: 'center',
|
|
218
|
-
justifyContent: 'center',
|
|
219
|
-
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
|
220
|
-
},
|
|
221
213
|
emptyState: {
|
|
222
214
|
padding: '32px 16px',
|
|
223
215
|
textAlign: 'center',
|
|
@@ -247,7 +239,7 @@ const CloseIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill
|
|
|
247
239
|
// Component
|
|
248
240
|
// ============================================================================
|
|
249
241
|
export const RichQuerySuggestions = forwardRef(function RichQuerySuggestions(props, ref) {
|
|
250
|
-
const { query, isOpen = true, sections = DEFAULT_SECTIONS, maxSuggestionsPerSection = 8, minQueryLength = 0, debounceMs = 200, includeDropdownRecommendations = true, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, maxCategories = 3, showCounts = true, showCategoryCounts = true, showSectionHeaders = true, classNames = {}, style, renderSuggestion, renderCategory, renderTrendingItem, renderRecentItem, header, footer, width = '100%', maxHeight = '480px', zIndex = 1000, ariaLabel = 'Search suggestions', analyticsTags, onSuggestionSelect, onCategoryClick, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose,
|
|
242
|
+
const { query, isOpen = true, sections = DEFAULT_SECTIONS, maxSuggestionsPerSection = 8, minQueryLength = 0, debounceMs = 200, includeDropdownRecommendations = true, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, maxCategories = 3, showCounts = true, showCategoryCounts = true, showSectionHeaders = true, classNames = {}, style, renderSuggestion, renderCategory, renderTrendingItem, renderRecentItem, header, footer, width = '100%', maxHeight = '480px', zIndex = 1000, ariaLabel = 'Search suggestions', analyticsTags, onSuggestionSelect, onCategoryClick, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, } = props;
|
|
251
243
|
const { client } = useSearchContext();
|
|
252
244
|
const containerRef = useRef(null);
|
|
253
245
|
const [activeIndex, setActiveIndex] = useState(-1);
|
|
@@ -466,7 +458,6 @@ export const RichQuerySuggestions = forwardRef(function RichQuerySuggestions(pro
|
|
|
466
458
|
} },
|
|
467
459
|
header && React.createElement("div", { style: styles.header }, header),
|
|
468
460
|
React.createElement("div", { style: { ...styles.content, maxHeight } },
|
|
469
|
-
loading && showLoadingOverlay && (React.createElement("div", { style: styles.loadingOverlay }, renderLoading ? renderLoading() : React.createElement("span", null, "Loading..."))),
|
|
470
461
|
enabledSections.map((section, index) => {
|
|
471
462
|
let content = null;
|
|
472
463
|
switch (section.id) {
|
|
@@ -14,7 +14,6 @@ export interface SearchBarTheme {
|
|
|
14
14
|
suggestionItem?: string;
|
|
15
15
|
suggestionItemHover?: string;
|
|
16
16
|
suggestionItemActive?: string;
|
|
17
|
-
loadingIndicator?: string;
|
|
18
17
|
searchIcon?: string;
|
|
19
18
|
clearButton?: string;
|
|
20
19
|
submitButton?: string;
|
|
@@ -37,10 +36,7 @@ export interface SearchBarProps {
|
|
|
37
36
|
className?: string;
|
|
38
37
|
style?: React.CSSProperties;
|
|
39
38
|
theme?: SearchBarTheme;
|
|
40
|
-
/** Show loading state when fetching and no previous suggestions (default false: show previous results until new render) */
|
|
41
|
-
showLoadingState?: boolean;
|
|
42
39
|
renderSuggestion?: (suggestion: string, index: number) => React.ReactNode;
|
|
43
|
-
renderLoading?: () => React.ReactNode;
|
|
44
40
|
/** Custom render for the search icon. If not provided, a default magnifying glass SVG is rendered. */
|
|
45
41
|
renderSearchIcon?: () => React.ReactNode;
|
|
46
42
|
/** Whether to show a clear button when the query is non-empty (default: true) */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../src/components/SearchBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,
|
|
1
|
+
{"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../src/components/SearchBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1E,sGAAsG;IACtG,gBAAgB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACzC,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACxC,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC3C,yEAAyE;IACzE,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAgED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAib9C,CAAC"}
|
|
@@ -51,7 +51,7 @@ const DefaultSearchIcon = ({ size = 18 }) => (React.createElement("svg", { width
|
|
|
51
51
|
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" },
|
|
52
52
|
React.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
53
53
|
React.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })));
|
|
54
|
-
export const SearchBar = ({ placeholder = '
|
|
54
|
+
export 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', }) => {
|
|
55
55
|
const { client, theme, enableAnalytics, autoTrackSearch } = useSearchContext();
|
|
56
56
|
const { query, setQuery, search: triggerSearch, results, loading: searchLoading, error: searchError } = useSearchState();
|
|
57
57
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -181,12 +181,11 @@ export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, d
|
|
|
181
181
|
}, 200);
|
|
182
182
|
}, []);
|
|
183
183
|
const defaultRenderSuggestion = (suggestion, index) => (React.createElement("div", { key: index }, suggestion));
|
|
184
|
-
const defaultRenderLoading = () => (React.createElement("div", { style: { padding: theme.spacing.medium, textAlign: 'center' } }, "Loading suggestions..."));
|
|
185
184
|
const searchBarTheme = customTheme || {};
|
|
186
185
|
const isLoading = suggestionsLoading || searchLoading;
|
|
187
186
|
// Show list when we have suggestions (including previous while loading) or when loading and showLoadingState
|
|
188
187
|
const hasSuggestions = displayedSuggestions.length > 0;
|
|
189
|
-
const showSuggestionsList = isFocused && showSuggestions && query.length >= minQueryLength &&
|
|
188
|
+
const showSuggestionsList = isFocused && showSuggestions && query.length >= minQueryLength && hasSuggestions;
|
|
190
189
|
// Get processing time from results
|
|
191
190
|
const res = results;
|
|
192
191
|
const processingTime = res?.processingTimeMS
|
|
@@ -317,7 +316,6 @@ export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, d
|
|
|
317
316
|
zIndex: Z_INDEX.dropdown,
|
|
318
317
|
boxSizing: 'border-box',
|
|
319
318
|
} },
|
|
320
|
-
isLoading && displayedSuggestions.length === 0 && showLoadingState && (renderLoading ? renderLoading() : defaultRenderLoading()),
|
|
321
319
|
displayedSuggestions.length > 0 && (React.createElement(React.Fragment, null, displayedSuggestions.map((suggestion, index) => {
|
|
322
320
|
const isSelected = index === selectedIndex;
|
|
323
321
|
const renderFn = renderSuggestion || defaultRenderSuggestion;
|
|
@@ -92,7 +92,7 @@ const ClearIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill
|
|
|
92
92
|
// Component
|
|
93
93
|
// ============================================================================
|
|
94
94
|
export const SearchBarWithSuggestions = forwardRef(function SearchBarWithSuggestions(props, ref) {
|
|
95
|
-
const { variant = 'classic', placeholder = '
|
|
95
|
+
const { variant = 'classic', placeholder = 'Powered by Seekora', initialQuery = '', value, onQueryChange, onSearch, onSuggestionSelect, onProductClick, showSearchButton = false, searchButtonText = 'Search', showClearButton = true, autoFocus = false, minQueryLength = 1, maxSuggestions = 8, maxProducts = 8, debounceMs = 200, showRecentSearches = true, showTrendingOnEmpty = true, includeDropdownRecommendations = false, filteredTabs, enableAnalytics = true, analyticsTags, includeFacets, includeCategories, dropdownWidth, dropdownMaxHeight, classNames = {}, style, inputStyle, ariaLabel = 'Search', } = props;
|
|
96
96
|
const { client } = useSearchContext();
|
|
97
97
|
const inputRef = useRef(null);
|
|
98
98
|
const dropdownRef = useRef(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchLayout.d.ts","sourceRoot":"","sources":["../../src/components/SearchLayout.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchLayout.d.ts","sourceRoot":"","sources":["../../src/components/SearchLayout.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,qBAAqB;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,qBAAqB;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,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,iBAAiB,CAAC;IAC1B,6BAA6B;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAoGpD,CAAC"}
|
|
@@ -3,21 +3,16 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides a layout structure for search interfaces with sidebar and main content
|
|
5
5
|
*/
|
|
6
|
-
import React
|
|
6
|
+
import React from 'react';
|
|
7
7
|
import { useSearchContext } from './SearchProvider';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
|
+
import { useIsMobile, useResponsivePadding, useResponsiveGap } from '../utils/responsive';
|
|
9
10
|
export const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth = '300px', className, style, theme: customTheme, showSidebarOnMobile = false, }) => {
|
|
10
11
|
const { theme } = useSearchContext();
|
|
11
12
|
const layoutTheme = customTheme || {};
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
setIsMobile(window.innerWidth <= 768);
|
|
16
|
-
};
|
|
17
|
-
checkMobile();
|
|
18
|
-
window.addEventListener('resize', checkMobile);
|
|
19
|
-
return () => window.removeEventListener('resize', checkMobile);
|
|
20
|
-
}, []);
|
|
13
|
+
const isMobile = useIsMobile();
|
|
14
|
+
const responsivePadding = useResponsivePadding(parseInt(theme.spacing.medium) || 16);
|
|
15
|
+
const responsiveGap = useResponsiveGap(parseInt(theme.spacing.large) || 24);
|
|
21
16
|
return (React.createElement("div", { className: clsx(layoutTheme.container, className), style: {
|
|
22
17
|
display: 'flex',
|
|
23
18
|
flexDirection: 'column',
|
|
@@ -28,7 +23,7 @@ export const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth =
|
|
|
28
23
|
...style,
|
|
29
24
|
} },
|
|
30
25
|
header && (React.createElement("header", { className: layoutTheme.header, style: {
|
|
31
|
-
padding:
|
|
26
|
+
padding: responsivePadding,
|
|
32
27
|
borderBottom: `1px solid ${theme.colors.border}`,
|
|
33
28
|
backgroundColor: theme.colors.background,
|
|
34
29
|
} }, header)),
|
|
@@ -37,15 +32,16 @@ export const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth =
|
|
|
37
32
|
flex: 1,
|
|
38
33
|
width: '100%',
|
|
39
34
|
maxWidth: '100%',
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
flexDirection: isMobile ? 'column' : 'row',
|
|
36
|
+
gap: responsiveGap,
|
|
37
|
+
padding: responsivePadding,
|
|
42
38
|
backgroundColor: theme.colors.background,
|
|
43
39
|
color: theme.colors.text,
|
|
44
|
-
overflow: 'hidden',
|
|
40
|
+
overflow: isMobile ? 'visible' : 'hidden',
|
|
45
41
|
} },
|
|
46
42
|
sidebar && (!isMobile || showSidebarOnMobile) && (React.createElement("aside", { className: layoutTheme.sidebar, style: {
|
|
47
|
-
width: sidebarWidth,
|
|
48
|
-
minWidth: sidebarWidth,
|
|
43
|
+
width: isMobile ? '100%' : sidebarWidth,
|
|
44
|
+
minWidth: isMobile ? '100%' : sidebarWidth,
|
|
49
45
|
flexShrink: 0,
|
|
50
46
|
} }, sidebar)),
|
|
51
47
|
React.createElement("main", { className: layoutTheme.main, style: {
|
|
@@ -58,7 +54,7 @@ export const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth =
|
|
|
58
54
|
overflow: 'auto',
|
|
59
55
|
} }, children)),
|
|
60
56
|
footer && (React.createElement("footer", { className: layoutTheme.footer, style: {
|
|
61
|
-
padding:
|
|
57
|
+
padding: responsivePadding,
|
|
62
58
|
borderTop: `1px solid ${theme.colors.border}`,
|
|
63
59
|
backgroundColor: theme.colors.background,
|
|
64
60
|
} }, footer))));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchProvider.d.ts","sourceRoot":"","sources":["../../src/components/SearchProvider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EAA6B,SAAS,EAAsB,MAAM,OAAO,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAO,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI1D,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAID,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"SearchProvider.d.ts","sourceRoot":"","sources":["../../src/components/SearchProvider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EAA6B,SAAS,EAAsB,MAAM,OAAO,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAO,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI1D,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAID,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAkDxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,kBAQnC,CAAC"}
|
|
@@ -30,9 +30,7 @@ export const SearchProvider = ({ client, theme: themeConfig, enableAnalytics = t
|
|
|
30
30
|
useEffect(() => {
|
|
31
31
|
if (abTestId !== undefined || abVariant !== undefined) {
|
|
32
32
|
stateManager.setAbTest(abTestId, abVariant);
|
|
33
|
-
|
|
34
|
-
client.setAbTest(abTestId, abVariant);
|
|
35
|
-
}
|
|
33
|
+
client.setAbTest(abTestId, abVariant);
|
|
36
34
|
}
|
|
37
35
|
}, [stateManager, client, abTestId, abVariant]);
|
|
38
36
|
const value = useMemo(() => ({
|
|
@@ -18,7 +18,6 @@ export interface SearchResultsTheme {
|
|
|
18
18
|
resultImage?: string;
|
|
19
19
|
resultPrice?: string;
|
|
20
20
|
emptyState?: string;
|
|
21
|
-
loadingState?: string;
|
|
22
21
|
errorState?: string;
|
|
23
22
|
pagination?: string;
|
|
24
23
|
/** Custom min-height class override */
|
|
@@ -33,9 +32,6 @@ export interface SearchResultsProps {
|
|
|
33
32
|
onResultClick?: (result: ResultItem, index: number) => void;
|
|
34
33
|
renderResult?: (result: ResultItem, index: number, isActive?: boolean) => React.ReactNode;
|
|
35
34
|
renderEmpty?: () => React.ReactNode;
|
|
36
|
-
/** Show loading state when fetching and no previous results (default false: show previous results until new render) */
|
|
37
|
-
showLoadingState?: boolean;
|
|
38
|
-
renderLoading?: () => React.ReactNode;
|
|
39
35
|
renderError?: (error: Error) => React.ReactNode;
|
|
40
36
|
className?: string;
|
|
41
37
|
style?: React.CSSProperties;
|
|
@@ -56,8 +52,6 @@ export interface SearchResultsProps {
|
|
|
56
52
|
minHeight?: string;
|
|
57
53
|
/** Minimum width to prevent container shrinking (default: '100%') */
|
|
58
54
|
minWidth?: string;
|
|
59
|
-
/** Opacity applied to results while loading new results (default: 0.7, set to 1 to disable) */
|
|
60
|
-
loadingOpacity?: number;
|
|
61
55
|
}
|
|
62
56
|
export declare const SearchResults: React.FC<SearchResultsProps>;
|
|
63
57
|
//# sourceMappingURL=SearchResults.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/components/SearchResults.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,
|
|
1
|
+
{"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/components/SearchResults.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1F,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC;IAC1C,+DAA+D;IAC/D,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAoBD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAqlBtD,CAAC"}
|
|
@@ -29,7 +29,7 @@ const formatPrice = (value, currency = '₹') => {
|
|
|
29
29
|
}
|
|
30
30
|
return String(value);
|
|
31
31
|
};
|
|
32
|
-
export const SearchResults = ({ results: resultsProp, loading: loadingProp, error: errorProp, onResultClick, renderResult, renderEmpty,
|
|
32
|
+
export const SearchResults = ({ results: resultsProp, loading: loadingProp, error: errorProp, onResultClick, renderResult, renderEmpty, renderError, className, style, theme: customTheme, itemsPerPage = 20, showPagination = false, viewMode = 'list', fieldMapping, extractResults, enableKeyboardNavigation = true, autoFocus = false, minHeight = '400px', minWidth = '100%', }) => {
|
|
33
33
|
const { theme, client, enableAnalytics } = useSearchContext();
|
|
34
34
|
const { results: stateResults, loading: stateLoading, error: stateError, currentPage, itemsPerPage: stateItemsPerPage } = useSearchState();
|
|
35
35
|
const searchResultsTheme = customTheme || {};
|
|
@@ -299,11 +299,6 @@ export const SearchResults = ({ results: resultsProp, loading: loadingProp, erro
|
|
|
299
299
|
textAlign: 'center',
|
|
300
300
|
color: theme.colors.text,
|
|
301
301
|
} }, "No results found"));
|
|
302
|
-
const defaultRenderLoading = () => (React.createElement("div", { className: searchResultsTheme.loadingState, style: {
|
|
303
|
-
padding: theme.spacing.large,
|
|
304
|
-
textAlign: 'center',
|
|
305
|
-
color: theme.colors.text,
|
|
306
|
-
} }, "Loading results..."));
|
|
307
302
|
const defaultRenderError = (err) => (React.createElement("div", { className: searchResultsTheme.errorState, style: {
|
|
308
303
|
padding: theme.spacing.large,
|
|
309
304
|
textAlign: 'center',
|
|
@@ -412,8 +407,6 @@ export const SearchResults = ({ results: resultsProp, loading: loadingProp, erro
|
|
|
412
407
|
const containerStyle = {
|
|
413
408
|
minHeight: `var(--seekora-results-min-height, ${minHeight})`,
|
|
414
409
|
minWidth: `var(--seekora-results-min-width, ${minWidth})`,
|
|
415
|
-
transition: 'opacity 200ms ease-in-out',
|
|
416
|
-
opacity: loading && resultItems.length > 0 ? loadingOpacity : 1,
|
|
417
410
|
...style,
|
|
418
411
|
};
|
|
419
412
|
// Determine results list style based on view mode
|
|
@@ -437,12 +430,6 @@ export const SearchResults = ({ results: resultsProp, loading: loadingProp, erro
|
|
|
437
430
|
hasError: !!error,
|
|
438
431
|
isLoading: loading,
|
|
439
432
|
});
|
|
440
|
-
// When loading with no previous results, show loading only if showLoadingState (default: show previous results, no loading screen)
|
|
441
|
-
if (loading && resultItems.length === 0 && showLoadingState) {
|
|
442
|
-
log.verbose('SearchResults: Rendering loading state');
|
|
443
|
-
return (React.createElement("div", { className: clsx(searchResultsTheme.container, className), style: containerStyle }, renderLoading ? renderLoading() : defaultRenderLoading()));
|
|
444
|
-
}
|
|
445
|
-
// When loading with previous results, fall through and render them (with opacity transition)
|
|
446
433
|
if (error) {
|
|
447
434
|
log.error('SearchResults: Rendering error state', {
|
|
448
435
|
error: error.message,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageDisplay.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ImageDisplay.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageDisplay.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ImageDisplay.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,YAAY,GAAG,WAAW,CAAC;AAE/F,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gCAAgC;IAChC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAaD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,OAAkB,EAClB,GAAQ,EACR,SAAS,EACT,KAAK,EACL,gBAAwB,EACxB,kBAAyB,EACzB,UAAkB,EAClB,QAAiB,EACjB,SAAe,EACf,QAAe,GAChB,EAAE,iBAAiB,qBA8NnB"}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import React, { useState } from 'react';
|
|
8
8
|
import { clsx } from 'clsx';
|
|
9
9
|
import { ImageZoom } from './ImageZoom';
|
|
10
|
+
import { useIsMobile, useTouchTargetSize, useResponsiveGap } from '../../utils/responsive';
|
|
10
11
|
const imgBaseStyle = {
|
|
11
12
|
width: '100%',
|
|
12
13
|
height: 'auto',
|
|
@@ -22,6 +23,11 @@ export function ImageDisplay({ images, variant = 'single', alt = '', className,
|
|
|
22
23
|
const [hovering, setHovering] = useState(false);
|
|
23
24
|
const safeImages = Array.isArray(images) ? images.filter(Boolean) : [];
|
|
24
25
|
const current = safeImages[index] ?? safeImages[0];
|
|
26
|
+
// Responsive values
|
|
27
|
+
const isMobile = useIsMobile();
|
|
28
|
+
const arrowSize = useTouchTargetSize(32); // 44px on mobile, 32px on desktop
|
|
29
|
+
const thumbSize = isMobile ? 56 : 48; // Larger thumbnails on mobile
|
|
30
|
+
const responsiveGap = useResponsiveGap(8);
|
|
25
31
|
if (safeImages.length === 0) {
|
|
26
32
|
return React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-placeholder', className), style: { ...imgBaseStyle, ...style }, "aria-hidden": true });
|
|
27
33
|
}
|
|
@@ -58,22 +64,24 @@ export function ImageDisplay({ images, variant = 'single', alt = '', className,
|
|
|
58
64
|
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-carousel', className), style: { position: 'relative', ...style } },
|
|
59
65
|
mainImage,
|
|
60
66
|
safeImages.length > 1 && (React.createElement(React.Fragment, null,
|
|
61
|
-
React.createElement("button", { type: "button", "aria-label": "Previous", className: "seekora-img-carousel-prev", style: arrowStyle(true), onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); go(-1); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg-hover, rgba(255,255,255,1))'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg, rgba(255,255,255,0.9))'; } }, "\u2039"),
|
|
62
|
-
React.createElement("button", { type: "button", "aria-label": "Next", className: "seekora-img-carousel-next", style: arrowStyle(false), onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); go(1); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg-hover, rgba(255,255,255,1))'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg, rgba(255,255,255,0.9))'; } }, "\u203A"),
|
|
67
|
+
React.createElement("button", { type: "button", "aria-label": "Previous", className: "seekora-img-carousel-prev", style: arrowStyle(true, arrowSize), onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); go(-1); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg-hover, rgba(255,255,255,1))'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg, rgba(255,255,255,0.9))'; } }, "\u2039"),
|
|
68
|
+
React.createElement("button", { type: "button", "aria-label": "Next", className: "seekora-img-carousel-next", style: arrowStyle(false, arrowSize), onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); go(1); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg-hover, rgba(255,255,255,1))'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'var(--seekora-carousel-btn-bg, rgba(255,255,255,0.9))'; } }, "\u203A"),
|
|
63
69
|
showDots && (React.createElement("div", { className: "seekora-img-carousel-dots", style: {
|
|
64
70
|
position: 'absolute',
|
|
65
|
-
bottom: 8,
|
|
71
|
+
bottom: isMobile ? 12 : 8,
|
|
66
72
|
left: '50%',
|
|
67
73
|
transform: 'translateX(-50%)',
|
|
68
74
|
display: 'flex',
|
|
69
|
-
gap: 6,
|
|
70
|
-
padding: '6px 12px',
|
|
75
|
+
gap: isMobile ? 8 : 6,
|
|
76
|
+
padding: isMobile ? '8px 16px' : '6px 12px',
|
|
71
77
|
backgroundColor: 'var(--seekora-carousel-dots-bg, rgba(0,0,0,0.5))',
|
|
72
78
|
borderRadius: 12,
|
|
73
79
|
zIndex: 10,
|
|
74
80
|
} }, safeImages.map((_, i) => (React.createElement("button", { key: i, type: "button", "aria-label": `Go to image ${i + 1}`, onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); setIndex(i); }, style: {
|
|
75
|
-
width: 8,
|
|
76
|
-
height: 8,
|
|
81
|
+
width: isMobile ? 10 : 8,
|
|
82
|
+
height: isMobile ? 10 : 8,
|
|
83
|
+
minWidth: isMobile ? 44 : 32, // Ensure touch target
|
|
84
|
+
minHeight: isMobile ? 44 : 32,
|
|
77
85
|
borderRadius: '50%',
|
|
78
86
|
border: 'none',
|
|
79
87
|
padding: 0,
|
|
@@ -85,26 +93,28 @@ export function ImageDisplay({ images, variant = 'single', alt = '', className,
|
|
|
85
93
|
if (variant === 'thumbStrip' || variant === 'thumbList') {
|
|
86
94
|
const thumbMainStyle = style?.aspectRatio ? { ...imgBaseStyle, aspectRatio: style.aspectRatio } : imgBaseStyle;
|
|
87
95
|
const mainImage = enableZoom ? (React.createElement(ImageZoom, { src: current, alt: alt, mode: zoomMode, zoomLevel: zoomLevel, images: safeImages, currentIndex: index, className: "seekora-img-thumb-main", style: thumbMainStyle })) : (React.createElement("img", { src: current, alt: alt, className: "seekora-img-thumb-main", style: thumbMainStyle, loading: "lazy" }));
|
|
88
|
-
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-thumbstrip', className), style: { display: 'flex', flexDirection: 'column', gap:
|
|
96
|
+
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-thumbstrip', className), style: { display: 'flex', flexDirection: 'column', gap: responsiveGap, ...style } },
|
|
89
97
|
mainImage,
|
|
90
|
-
React.createElement("div", { className: "seekora-img-thumbs", style: { display: 'flex', gap: 4, overflowX: 'auto', paddingBottom: 4 } }, safeImages.map((src, i) => (React.createElement("button", { type: "button", key: i, className: clsx('seekora-img-thumb', i === index && 'seekora-img-thumb--active'), style: { flexShrink: 0, width:
|
|
98
|
+
React.createElement("div", { className: "seekora-img-thumbs", style: { display: 'flex', gap: isMobile ? 6 : 4, overflowX: 'auto', paddingBottom: isMobile ? 6 : 4 } }, safeImages.map((src, i) => (React.createElement("button", { type: "button", key: i, className: clsx('seekora-img-thumb', i === index && 'seekora-img-thumb--active'), style: { flexShrink: 0, width: thumbSize, height: thumbSize, minWidth: thumbSize, minHeight: thumbSize, padding: 0, border: i === index ? '2px solid var(--seekora-primary)' : '1px solid transparent', borderRadius: 4, overflow: 'hidden', cursor: 'pointer', background: 'none' }, onMouseDown: (e) => { e.stopPropagation(); e.preventDefault(); setIndex(i); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); } },
|
|
91
99
|
React.createElement("img", { src: src, alt: "", style: { width: '100%', height: '100%', objectFit: 'cover' } })))))));
|
|
92
100
|
}
|
|
93
101
|
return React.createElement("img", { src: current, alt: alt, className: clsx('seekora-img-display', className), style: { ...imgBaseStyle, ...style }, loading: "lazy" });
|
|
94
102
|
}
|
|
95
|
-
function arrowStyle(left) {
|
|
103
|
+
function arrowStyle(left, size = 32) {
|
|
96
104
|
return {
|
|
97
105
|
position: 'absolute',
|
|
98
106
|
top: '50%',
|
|
99
|
-
[left ? 'left' : 'right']: 8,
|
|
107
|
+
[left ? 'left' : 'right']: size >= 44 ? 4 : 8, // Less offset on mobile for larger buttons
|
|
100
108
|
transform: 'translateY(-50%)',
|
|
101
|
-
width:
|
|
102
|
-
height:
|
|
109
|
+
width: size,
|
|
110
|
+
height: size,
|
|
111
|
+
minWidth: size,
|
|
112
|
+
minHeight: size,
|
|
103
113
|
borderRadius: '50%',
|
|
104
114
|
border: 'none',
|
|
105
115
|
backgroundColor: 'var(--seekora-carousel-btn-bg, rgba(255, 255, 255, 0.9))',
|
|
106
116
|
color: 'var(--seekora-carousel-btn-text, #111)',
|
|
107
|
-
fontSize: '1.25rem',
|
|
117
|
+
fontSize: size >= 44 ? '1.5rem' : '1.25rem', // Larger font on mobile
|
|
108
118
|
fontWeight: 'bold',
|
|
109
119
|
cursor: 'pointer',
|
|
110
120
|
display: 'flex',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageZoom.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ImageZoom.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAGxE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,GAAQ,EACR,IAAa,EACb,SAAe,EACf,SAAS,EACT,KAAK,EACL,iBAAwB,EACxB,QAAc,EACd,aAA2C,EAC3C,MAAM,EACN,YAAgB,GACjB,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"ImageZoom.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/ImageZoom.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAGxE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEhE,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,aAAa,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,GAAQ,EACR,IAAa,EACb,SAAe,EACf,SAAS,EACT,KAAK,EACL,iBAAwB,EACxB,QAAc,EACd,aAA2C,EAC3C,MAAM,EACN,YAAgB,GACjB,EAAE,cAAc,qBAiiBhB"}
|
|
@@ -114,10 +114,66 @@ export function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, class
|
|
|
114
114
|
const rect = containerRef.current.getBoundingClientRect();
|
|
115
115
|
const bgPosX = (cursorPos.x / rect.width) * 100;
|
|
116
116
|
const bgPosY = (cursorPos.y / rect.height) * 100;
|
|
117
|
+
// Calculate available space in all directions
|
|
118
|
+
const viewportWidth = window.innerWidth;
|
|
119
|
+
const viewportHeight = window.innerHeight;
|
|
120
|
+
const gap = 16;
|
|
121
|
+
const mouseBuffer = 50; // Minimum distance from mouse cursor
|
|
122
|
+
// Calculate mouse position in viewport
|
|
123
|
+
const mouseX = rect.left + cursorPos.x;
|
|
124
|
+
const mouseY = rect.top + cursorPos.y;
|
|
125
|
+
// Calculate space available in each direction
|
|
126
|
+
const spaceRight = viewportWidth - rect.right - gap;
|
|
127
|
+
const spaceLeft = rect.left - gap;
|
|
128
|
+
// Determine optimal horizontal position
|
|
129
|
+
let left;
|
|
130
|
+
let top = rect.top;
|
|
131
|
+
// Try right side first (default Amazon-style)
|
|
132
|
+
if (spaceRight >= zoomPanelSize.width) {
|
|
133
|
+
left = rect.right + gap;
|
|
134
|
+
}
|
|
135
|
+
// Try left side
|
|
136
|
+
else if (spaceLeft >= zoomPanelSize.width) {
|
|
137
|
+
left = rect.left - zoomPanelSize.width - gap;
|
|
138
|
+
}
|
|
139
|
+
// Not enough space on either side - center on the side with more space
|
|
140
|
+
else if (spaceRight > spaceLeft) {
|
|
141
|
+
left = rect.right + gap;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
left = Math.max(gap, rect.left - zoomPanelSize.width - gap);
|
|
145
|
+
}
|
|
146
|
+
// Adjust vertical position to keep within viewport
|
|
147
|
+
// Try to align with image top by default
|
|
148
|
+
if (rect.top + zoomPanelSize.height > viewportHeight - gap) {
|
|
149
|
+
// Panel would overflow bottom - adjust upward
|
|
150
|
+
top = Math.max(gap, viewportHeight - zoomPanelSize.height - gap);
|
|
151
|
+
}
|
|
152
|
+
// Ensure panel doesn't overlap with mouse cursor
|
|
153
|
+
const panelRight = left + zoomPanelSize.width;
|
|
154
|
+
const panelBottom = top + zoomPanelSize.height;
|
|
155
|
+
// Check if mouse is inside the panel area
|
|
156
|
+
if (mouseX >= left - mouseBuffer &&
|
|
157
|
+
mouseX <= panelRight + mouseBuffer &&
|
|
158
|
+
mouseY >= top - mouseBuffer &&
|
|
159
|
+
mouseY <= panelBottom + mouseBuffer) {
|
|
160
|
+
// Mouse is too close - try to reposition
|
|
161
|
+
// If on right side and there's space on left, flip to left
|
|
162
|
+
if (left > rect.right && spaceLeft >= zoomPanelSize.width) {
|
|
163
|
+
left = rect.left - zoomPanelSize.width - gap;
|
|
164
|
+
}
|
|
165
|
+
// If on left side and there's space on right, flip to right
|
|
166
|
+
else if (left < rect.left && spaceRight >= zoomPanelSize.width) {
|
|
167
|
+
left = rect.right + gap;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Clamp to viewport boundaries
|
|
171
|
+
left = Math.max(gap, Math.min(left, viewportWidth - zoomPanelSize.width - gap));
|
|
172
|
+
top = Math.max(gap, Math.min(top, viewportHeight - zoomPanelSize.height - gap));
|
|
117
173
|
return {
|
|
118
|
-
position: 'fixed',
|
|
119
|
-
top
|
|
120
|
-
left
|
|
174
|
+
position: 'fixed',
|
|
175
|
+
top,
|
|
176
|
+
left,
|
|
121
177
|
width: zoomPanelSize.width,
|
|
122
178
|
height: zoomPanelSize.height,
|
|
123
179
|
backgroundImage: `url(${src})`,
|
|
@@ -154,7 +210,6 @@ export function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, class
|
|
|
154
210
|
if (!containerRef.current || !imageRef.current)
|
|
155
211
|
return {};
|
|
156
212
|
const rect = containerRef.current.getBoundingClientRect();
|
|
157
|
-
const imgRect = imageRef.current.getBoundingClientRect();
|
|
158
213
|
return {
|
|
159
214
|
position: 'absolute',
|
|
160
215
|
width: rect.width * zoomLevel,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariantSwatches.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/VariantSwatches.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"VariantSwatches.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/VariantSwatches.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG9E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,gDAAgD;IAChD,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,iDAAiD;IACjD,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AA4DD,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,cAAc,EACd,SAAa,EACb,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,gBAAuB,EACvB,aAAa,EACb,aAAa,EACb,SAAS,EACT,KAAK,GACN,EAAE,oBAAoB,4BAwLtB"}
|