@seekora-ai/ui-sdk-react 0.2.5 → 0.2.8
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/SearchBarWithSuggestions.d.ts +2 -0
- package/dist/components/SearchBarWithSuggestions.d.ts.map +1 -1
- package/dist/components/SearchBarWithSuggestions.js +2 -2
- package/dist/components/primitives/ImageDisplay.d.ts +19 -0
- package/dist/components/primitives/ImageDisplay.d.ts.map +1 -0
- package/dist/components/primitives/ImageDisplay.js +74 -0
- package/dist/components/primitives/index.d.ts +2 -0
- package/dist/components/primitives/index.d.ts.map +1 -0
- package/dist/components/primitives/index.js +1 -0
- package/dist/components/product-page/ProductGallery.d.ts +19 -0
- package/dist/components/product-page/ProductGallery.d.ts.map +1 -0
- package/dist/components/product-page/ProductGallery.js +13 -0
- package/dist/components/product-page/ProductInfo.d.ts +21 -0
- package/dist/components/product-page/ProductInfo.d.ts.map +1 -0
- package/dist/components/product-page/ProductInfo.js +19 -0
- package/dist/components/product-page/ProductRecommendations.d.ts +21 -0
- package/dist/components/product-page/ProductRecommendations.d.ts.map +1 -0
- package/dist/components/product-page/ProductRecommendations.js +17 -0
- package/dist/components/product-page/index.d.ts +4 -0
- package/dist/components/product-page/index.d.ts.map +1 -0
- package/dist/components/product-page/index.js +3 -0
- package/dist/components/section-primitives/SectionError.d.ts +11 -0
- package/dist/components/section-primitives/SectionError.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionError.js +13 -0
- package/dist/components/section-primitives/SectionItemGrid.d.ts +18 -0
- package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionItemGrid.js +16 -0
- package/dist/components/section-primitives/SectionLoading.d.ts +11 -0
- package/dist/components/section-primitives/SectionLoading.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionLoading.js +11 -0
- package/dist/components/section-primitives/SectionSearchContext.d.ts +17 -0
- package/dist/components/section-primitives/SectionSearchContext.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionSearchContext.js +17 -0
- package/dist/components/section-primitives/SectionSearchProvider.d.ts +23 -0
- package/dist/components/section-primitives/SectionSearchProvider.d.ts.map +1 -0
- package/dist/components/section-primitives/SectionSearchProvider.js +105 -0
- package/dist/components/section-primitives/index.d.ts +6 -0
- package/dist/components/section-primitives/index.d.ts.map +1 -0
- package/dist/components/section-primitives/index.js +5 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.d.ts +13 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/CategoriesTabs.js +35 -0
- package/dist/components/suggestions-primitives/DropdownPanel.d.ts +24 -0
- package/dist/components/suggestions-primitives/DropdownPanel.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/DropdownPanel.js +54 -0
- package/dist/components/suggestions-primitives/ItemCard.d.ts +39 -0
- package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ItemCard.js +52 -0
- package/dist/components/suggestions-primitives/ItemGrid.d.ts +28 -0
- package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ItemGrid.js +42 -0
- package/dist/components/suggestions-primitives/ProductCard.d.ts +21 -0
- package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ProductCard.js +46 -0
- package/dist/components/suggestions-primitives/ProductGrid.d.ts +17 -0
- package/dist/components/suggestions-primitives/ProductGrid.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/ProductGrid.js +36 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.d.ts +17 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/RecentSearchesList.js +39 -0
- package/dist/components/suggestions-primitives/SearchInput.d.ts +23 -0
- package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SearchInput.js +95 -0
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts +18 -0
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionItem.js +34 -0
- package/dist/components/suggestions-primitives/SuggestionList.d.ts +15 -0
- package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionList.js +36 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts +41 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsContext.js +18 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts +24 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.js +32 -0
- package/dist/components/suggestions-primitives/SuggestionsError.d.ts +11 -0
- package/dist/components/suggestions-primitives/SuggestionsError.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsError.js +19 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts +11 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsLoading.js +17 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts +38 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/SuggestionsProvider.js +222 -0
- package/dist/components/suggestions-primitives/TrendingList.d.ts +17 -0
- package/dist/components/suggestions-primitives/TrendingList.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/TrendingList.js +41 -0
- package/dist/components/suggestions-primitives/index.d.ts +39 -0
- package/dist/components/suggestions-primitives/index.d.ts.map +1 -0
- package/dist/components/suggestions-primitives/index.js +24 -0
- package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -1
- package/dist/hooks/useQuerySuggestionsEnhanced.js +30 -8
- package/dist/hooks/useSuggestionsAnalytics.d.ts +6 -6
- package/dist/hooks/useSuggestionsAnalytics.js +6 -6
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +630 -130
- package/dist/src/index.esm.js +1110 -43
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +1134 -42
- package/dist/src/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -35,6 +35,8 @@ export interface SearchBarWithSuggestionsProps {
|
|
|
35
35
|
minQueryLength?: number;
|
|
36
36
|
/** Max suggestions to show */
|
|
37
37
|
maxSuggestions?: number;
|
|
38
|
+
/** Max products to show in dropdown (federated/rich) */
|
|
39
|
+
maxProducts?: number;
|
|
38
40
|
/** Debounce delay (ms) */
|
|
39
41
|
debounceMs?: number;
|
|
40
42
|
/** Show recent searches */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBarWithSuggestions.d.ts","sourceRoot":"","sources":["../../src/components/SearchBarWithSuggestions.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SearchBarWithSuggestions.d.ts","sourceRoot":"","sources":["../../src/components/SearchBarWithSuggestions.tsx"],"names":[],"mappings":"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"}
|
|
@@ -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 = 'Search...', initialQuery = '', value, onQueryChange, onSearch, onSuggestionSelect, onProductClick, showSearchButton = false, searchButtonText = 'Search', showClearButton = true, autoFocus = false, minQueryLength = 1, maxSuggestions = 8, debounceMs = 200, showRecentSearches = true, showTrendingOnEmpty = true, includeDropdownRecommendations = false, filteredTabs, enableAnalytics = true, analyticsTags, includeFacets, includeCategories, dropdownWidth, dropdownMaxHeight, classNames = {}, style, inputStyle, ariaLabel = 'Search', } = props;
|
|
95
|
+
const { variant = 'classic', placeholder = 'Search...', 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);
|
|
@@ -251,7 +251,7 @@ export const SearchBarWithSuggestions = forwardRef(function SearchBarWithSuggest
|
|
|
251
251
|
case 'rich':
|
|
252
252
|
return (React.createElement(RichQuerySuggestions, { ref: dropdownRef, ...commonProps, includeDropdownRecommendations: includeDropdownRecommendations, includeCategories: true, width: dropdownWidth || '100%', maxHeight: dropdownMaxHeight || '480px' }));
|
|
253
253
|
case 'federated':
|
|
254
|
-
return (React.createElement(FederatedDropdown, { ref: dropdownRef, ...commonProps, filteredTabs: filteredTabs, showProducts: true, showBrands: true, showFilteredTabs: !!filteredTabs, onProductClick: handleProductClick, width: dropdownWidth || '800px', maxHeight: dropdownMaxHeight || '600px', includeFacets: includeFacets, includeCategories: includeCategories, includeDropdownRecommendations: includeDropdownRecommendations }));
|
|
254
|
+
return (React.createElement(FederatedDropdown, { ref: dropdownRef, ...commonProps, maxProducts: maxProducts, filteredTabs: filteredTabs, showProducts: true, showBrands: true, showFilteredTabs: !!filteredTabs, onProductClick: handleProductClick, width: dropdownWidth || '800px', maxHeight: dropdownMaxHeight || '600px', includeFacets: includeFacets, includeCategories: includeCategories, includeDropdownRecommendations: includeDropdownRecommendations }));
|
|
255
255
|
case 'compact':
|
|
256
256
|
return (React.createElement(QuerySuggestionsDropdown, { ref: dropdownRef, ...commonProps, maxSuggestions: 5, showCounts: false, width: dropdownWidth || '100%' }));
|
|
257
257
|
case 'classic':
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageDisplay – configurable multi-image display (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Variants: single, carousel, hover, thumbStrip, thumbList. Use in ItemCard,
|
|
5
|
+
* ProductCard, ProductGallery. Overridable via className/style.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export type ImageDisplayVariant = 'single' | 'carousel' | 'hover' | 'thumbStrip' | 'thumbList';
|
|
9
|
+
export interface ImageDisplayProps {
|
|
10
|
+
images: string[];
|
|
11
|
+
variant?: ImageDisplayVariant;
|
|
12
|
+
alt?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
carouselAutoplay?: boolean;
|
|
16
|
+
carouselIntervalMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function ImageDisplay({ images, variant, alt, className, style, carouselAutoplay, carouselIntervalMs, }: ImageDisplayProps): React.JSX.Element;
|
|
19
|
+
//# sourceMappingURL=ImageDisplay.d.ts.map
|
|
@@ -0,0 +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,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;CAC7B;AAUD,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,OAAkB,EAClB,GAAQ,EACR,SAAS,EACT,KAAK,EACL,gBAAwB,EACxB,kBAAyB,GAC1B,EAAE,iBAAiB,qBAiFnB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ImageDisplay – configurable multi-image display (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Variants: single, carousel, hover, thumbStrip, thumbList. Use in ItemCard,
|
|
5
|
+
* ProductCard, ProductGallery. Overridable via className/style.
|
|
6
|
+
*/
|
|
7
|
+
import React, { useState } from 'react';
|
|
8
|
+
import { clsx } from 'clsx';
|
|
9
|
+
const imgBaseStyle = {
|
|
10
|
+
width: '100%',
|
|
11
|
+
aspectRatio: '1',
|
|
12
|
+
objectFit: 'cover',
|
|
13
|
+
borderRadius: 4,
|
|
14
|
+
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
15
|
+
};
|
|
16
|
+
export function ImageDisplay({ images, variant = 'single', alt = '', className, style, carouselAutoplay = false, carouselIntervalMs = 4000, }) {
|
|
17
|
+
const [index, setIndex] = useState(0);
|
|
18
|
+
const [hovering, setHovering] = useState(false);
|
|
19
|
+
const safeImages = Array.isArray(images) ? images.filter(Boolean) : [];
|
|
20
|
+
const current = safeImages[index] ?? safeImages[0];
|
|
21
|
+
if (safeImages.length === 0) {
|
|
22
|
+
return React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-placeholder', className), style: { ...imgBaseStyle, ...style }, "aria-hidden": true });
|
|
23
|
+
}
|
|
24
|
+
if (variant === 'single') {
|
|
25
|
+
return (React.createElement("img", { src: safeImages[0], alt: alt, className: clsx('seekora-img-display', 'seekora-img-single', className), style: { ...imgBaseStyle, ...style }, loading: "lazy" }));
|
|
26
|
+
}
|
|
27
|
+
if (variant === 'hover') {
|
|
28
|
+
const showSecond = safeImages.length > 1 && hovering;
|
|
29
|
+
const src = showSecond ? safeImages[1] : safeImages[0];
|
|
30
|
+
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-hover', className), style: { position: 'relative', ...style }, onMouseEnter: () => setHovering(true), onMouseLeave: () => setHovering(false) },
|
|
31
|
+
React.createElement("img", { src: src, alt: alt, className: "seekora-img-hover-img", style: imgBaseStyle, loading: "lazy" })));
|
|
32
|
+
}
|
|
33
|
+
if (variant === 'carousel') {
|
|
34
|
+
const go = (delta) => {
|
|
35
|
+
setIndex((i) => {
|
|
36
|
+
const next = i + delta;
|
|
37
|
+
if (next < 0)
|
|
38
|
+
return safeImages.length - 1;
|
|
39
|
+
if (next >= safeImages.length)
|
|
40
|
+
return 0;
|
|
41
|
+
return next;
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-carousel', className), style: { position: 'relative', ...style } },
|
|
45
|
+
React.createElement("img", { src: current, alt: alt, className: "seekora-img-carousel-main", style: imgBaseStyle, loading: "lazy" }),
|
|
46
|
+
safeImages.length > 1 && (React.createElement(React.Fragment, null,
|
|
47
|
+
React.createElement("button", { type: "button", "aria-label": "Previous", className: "seekora-img-carousel-prev", style: arrowStyle(true), onMouseDown: () => go(-1) }),
|
|
48
|
+
React.createElement("button", { type: "button", "aria-label": "Next", className: "seekora-img-carousel-next", style: arrowStyle(false), onMouseDown: () => go(1) })))));
|
|
49
|
+
}
|
|
50
|
+
if (variant === 'thumbStrip' || variant === 'thumbList') {
|
|
51
|
+
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-thumbstrip', className), style: { display: 'flex', flexDirection: 'column', gap: 8, ...style } },
|
|
52
|
+
React.createElement("img", { src: current, alt: alt, className: "seekora-img-thumb-main", style: imgBaseStyle, loading: "lazy" }),
|
|
53
|
+
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: 48, height: 48, padding: 0, border: i === index ? '2px solid var(--seekora-primary)' : '1px solid transparent', borderRadius: 4, overflow: 'hidden', cursor: 'pointer', background: 'none' }, onMouseDown: () => setIndex(i) },
|
|
54
|
+
React.createElement("img", { src: src, alt: "", style: { width: '100%', height: '100%', objectFit: 'cover' } })))))));
|
|
55
|
+
}
|
|
56
|
+
return React.createElement("img", { src: current, alt: alt, className: clsx('seekora-img-display', className), style: { ...imgBaseStyle, ...style }, loading: "lazy" });
|
|
57
|
+
}
|
|
58
|
+
function arrowStyle(left) {
|
|
59
|
+
return {
|
|
60
|
+
position: 'absolute',
|
|
61
|
+
top: '50%',
|
|
62
|
+
[left ? 'left' : 'right']: 8,
|
|
63
|
+
transform: 'translateY(-50%)',
|
|
64
|
+
width: 32,
|
|
65
|
+
height: 32,
|
|
66
|
+
borderRadius: '50%',
|
|
67
|
+
border: '1px solid var(--seekora-border-color)',
|
|
68
|
+
backgroundColor: 'var(--seekora-bg-surface)',
|
|
69
|
+
cursor: 'pointer',
|
|
70
|
+
display: 'flex',
|
|
71
|
+
alignItems: 'center',
|
|
72
|
+
justifyContent: 'center',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { ImageDisplay } from './ImageDisplay';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductGallery – product detail image gallery (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Uses ImageDisplay with configurable variant (carousel, thumbStrip, etc.).
|
|
5
|
+
* For use on individual product page.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { type ImageDisplayVariant } from '../primitives/ImageDisplay';
|
|
9
|
+
export interface ProductGalleryProps {
|
|
10
|
+
images: string[];
|
|
11
|
+
variant?: ImageDisplayVariant;
|
|
12
|
+
alt?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
carouselAutoplay?: boolean;
|
|
16
|
+
carouselIntervalMs?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function ProductGallery({ images, variant, alt, className, style, carouselAutoplay, carouselIntervalMs, }: ProductGalleryProps): React.JSX.Element;
|
|
19
|
+
//# sourceMappingURL=ProductGallery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductGallery.d.ts","sourceRoot":"","sources":["../../../src/components/product-page/ProductGallery.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEpF,MAAM,WAAW,mBAAmB;IAClC,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;CAC7B;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAsB,EACtB,GAAe,EACf,SAAS,EACT,KAAK,EACL,gBAAgB,EAChB,kBAAkB,GACnB,EAAE,mBAAmB,qBAYrB"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductGallery – product detail image gallery (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Uses ImageDisplay with configurable variant (carousel, thumbStrip, etc.).
|
|
5
|
+
* For use on individual product page.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { clsx } from 'clsx';
|
|
9
|
+
import { ImageDisplay } from '../primitives/ImageDisplay';
|
|
10
|
+
export function ProductGallery({ images, variant = 'thumbStrip', alt = 'Product', className, style, carouselAutoplay, carouselIntervalMs, }) {
|
|
11
|
+
return (React.createElement("div", { className: clsx('seekora-product-gallery', className), style: style },
|
|
12
|
+
React.createElement(ImageDisplay, { images: images, variant: variant, alt: alt, carouselAutoplay: carouselAutoplay, carouselIntervalMs: carouselIntervalMs })));
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductInfo – product detail block (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Title, description, price, optional variant selector and CTA. Minimal layout;
|
|
5
|
+
* override with className/style. For use on individual product page.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface ProductInfoProps {
|
|
9
|
+
title: string;
|
|
10
|
+
description?: string;
|
|
11
|
+
price?: number | string;
|
|
12
|
+
currency?: string;
|
|
13
|
+
/** Optional variant selector (e.g. size/color) */
|
|
14
|
+
renderVariantSelector?: () => React.ReactNode;
|
|
15
|
+
/** Optional CTA (e.g. Add to cart) */
|
|
16
|
+
renderCTA?: () => React.ReactNode;
|
|
17
|
+
className?: string;
|
|
18
|
+
style?: React.CSSProperties;
|
|
19
|
+
}
|
|
20
|
+
export declare function ProductInfo({ title, description, price, currency, renderVariantSelector, renderCTA, className, style, }: ProductInfoProps): React.JSX.Element;
|
|
21
|
+
//# sourceMappingURL=ProductInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductInfo.d.ts","sourceRoot":"","sources":["../../../src/components/product-page/ProductInfo.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,qBAAqB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC9C,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,WAAW,EACX,KAAK,EACL,QAAc,EACd,qBAAqB,EACrB,SAAS,EACT,SAAS,EACT,KAAK,GACN,EAAE,gBAAgB,qBAsBlB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductInfo – product detail block (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Title, description, price, optional variant selector and CTA. Minimal layout;
|
|
5
|
+
* override with className/style. For use on individual product page.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import { clsx } from 'clsx';
|
|
9
|
+
export function ProductInfo({ title, description, price, currency = '$', renderVariantSelector, renderCTA, className, style, }) {
|
|
10
|
+
const priceNum = price != null ? (typeof price === 'number' ? price : parseFloat(String(price))) : null;
|
|
11
|
+
return (React.createElement("div", { className: clsx('seekora-product-info', className), style: { display: 'flex', flexDirection: 'column', gap: 12, ...style } },
|
|
12
|
+
React.createElement("h1", { className: "seekora-product-info-title", style: { fontSize: '1.25rem', fontWeight: 600, margin: 0 } }, title),
|
|
13
|
+
priceNum != null && !Number.isNaN(priceNum) ? (React.createElement("span", { className: "seekora-product-info-price", style: { fontSize: '1.125rem', fontWeight: 600 } },
|
|
14
|
+
currency,
|
|
15
|
+
priceNum.toFixed(2))) : null,
|
|
16
|
+
description ? (React.createElement("p", { className: "seekora-product-info-description", style: { fontSize: '0.875rem', color: 'var(--seekora-text-secondary)', margin: 0, lineHeight: 1.5 } }, description)) : null,
|
|
17
|
+
renderVariantSelector?.(),
|
|
18
|
+
renderCTA?.()));
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductRecommendations – related / frequently bought (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Renders a section of recommended items (generic ItemGrid or product list).
|
|
5
|
+
* Pass items and onItemClick; or wrap SectionSearchProvider with preset query for "related".
|
|
6
|
+
* For use on individual product page.
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import type { GenericItem } from '../suggestions-primitives/ItemCard';
|
|
10
|
+
export interface ProductRecommendationsProps {
|
|
11
|
+
title?: string;
|
|
12
|
+
items: GenericItem[] | unknown[];
|
|
13
|
+
onItemClick?: (item: unknown, index: number) => void;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
columns?: number;
|
|
16
|
+
className?: string;
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
|
+
renderItem?: (item: unknown, index: number) => React.ReactNode;
|
|
19
|
+
}
|
|
20
|
+
export declare function ProductRecommendations({ title, items, onItemClick, maxItems, columns, className, style, renderItem, }: ProductRecommendationsProps): React.JSX.Element | null;
|
|
21
|
+
//# sourceMappingURL=ProductRecommendations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductRecommendations.d.ts","sourceRoot":"","sources":["../../../src/components/product-page/ProductRecommendations.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAEtE,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAChE;AAED,wBAAgB,sBAAsB,CAAC,EACrC,KAA2B,EAC3B,KAAK,EACL,WAAW,EACX,QAAY,EACZ,OAAW,EACX,SAAS,EACT,KAAK,EACL,UAAU,GACX,EAAE,2BAA2B,4BAiB7B"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProductRecommendations – related / frequently bought (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Renders a section of recommended items (generic ItemGrid or product list).
|
|
5
|
+
* Pass items and onItemClick; or wrap SectionSearchProvider with preset query for "related".
|
|
6
|
+
* For use on individual product page.
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { clsx } from 'clsx';
|
|
10
|
+
import { ItemGrid } from '../suggestions-primitives/ItemGrid';
|
|
11
|
+
export function ProductRecommendations({ title = 'You may also like', items, onItemClick, maxItems = 6, columns = 3, className, style, renderItem, }) {
|
|
12
|
+
if (!items?.length)
|
|
13
|
+
return null;
|
|
14
|
+
return (React.createElement("div", { className: clsx('seekora-product-recommendations', className), style: style },
|
|
15
|
+
React.createElement("h2", { className: "seekora-product-recommendations-title", style: { fontSize: '1rem', fontWeight: 600, marginBottom: 12 } }, title),
|
|
16
|
+
React.createElement(ItemGrid, { items: items, maxItems: maxItems, columns: columns, onItemClick: onItemClick, renderItem: renderItem })));
|
|
17
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ProductGallery, type ProductGalleryProps } from './ProductGallery';
|
|
2
|
+
export { ProductInfo, type ProductInfoProps } from './ProductInfo';
|
|
3
|
+
export { ProductRecommendations, type ProductRecommendationsProps } from './ProductRecommendations';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/product-page/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,sBAAsB,EAAE,KAAK,2BAA2B,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionError – error state for section (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export interface SectionErrorProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
render?: (error: Error) => React.ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare function SectionError({ className, style, render }: SectionErrorProps): React.JSX.Element | null;
|
|
11
|
+
//# sourceMappingURL=SectionError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionError.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/SectionError.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;CAC5C;AAED,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,iBAAiB,4BAS3E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionError – error state for section (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useSectionSearchContext } from './SectionSearchContext';
|
|
6
|
+
export function SectionError({ className, style, render }) {
|
|
7
|
+
const { error } = useSectionSearchContext();
|
|
8
|
+
if (!error)
|
|
9
|
+
return null;
|
|
10
|
+
if (render)
|
|
11
|
+
return React.createElement(React.Fragment, null, render(error));
|
|
12
|
+
return (React.createElement("div", { className: className, style: { padding: 16, color: 'var(--seekora-error,#dc2626)', fontSize: '0.875rem', ...style } }, error.message));
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionItemGrid – generic grid of items from SectionSearchProvider (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export interface SectionItemGridProps {
|
|
6
|
+
columns?: number;
|
|
7
|
+
maxItems?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
getItemId?: (item: unknown) => string;
|
|
11
|
+
getItemTitle?: (item: unknown) => string;
|
|
12
|
+
getItemImage?: (item: unknown) => string | undefined;
|
|
13
|
+
getItemDescription?: (item: unknown) => string | undefined;
|
|
14
|
+
getItemUrl?: (item: unknown) => string | undefined;
|
|
15
|
+
renderItem?: (item: unknown, index: number) => React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare function SectionItemGrid({ columns, maxItems, className, style, getItemId, getItemTitle, getItemImage, getItemDescription, getItemUrl, renderItem, }: SectionItemGridProps): React.JSX.Element;
|
|
18
|
+
//# sourceMappingURL=SectionItemGrid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionItemGrid.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/SectionItemGrid.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC;IACtC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACrD,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IAC3D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACnD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;CAChE;AAED,wBAAgB,eAAe,CAAC,EAC9B,OAAW,EACX,QAAa,EACb,SAAS,EACT,KAAK,EACL,SAA8E,EAC9E,YAAyE,EACzE,YAAmE,EACnE,kBAAqF,EACrF,UAA6D,EAC7D,UAAU,GACX,EAAE,oBAAoB,qBAsBtB"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionItemGrid – generic grid of items from SectionSearchProvider (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useSectionSearchContext } from './SectionSearchContext';
|
|
6
|
+
import { ItemGrid } from '../suggestions-primitives/ItemGrid';
|
|
7
|
+
import { SectionLoading } from './SectionLoading';
|
|
8
|
+
import { SectionError } from './SectionError';
|
|
9
|
+
export function SectionItemGrid({ columns = 4, maxItems = 12, className, style, getItemId = (i) => i.id ?? String(i?.objectID ?? ''), getItemTitle = (i) => i.title ?? i?.title ?? '', getItemImage = (i) => i.image ?? i?.image, getItemDescription = (i) => i.description ?? i?.description, getItemUrl = (i) => i.url ?? i?.url, renderItem, }) {
|
|
10
|
+
const { items, loading, error, trackClick } = useSectionSearchContext();
|
|
11
|
+
if (loading)
|
|
12
|
+
return React.createElement(SectionLoading, { className: className, style: style });
|
|
13
|
+
if (error)
|
|
14
|
+
return React.createElement(SectionError, { className: className, style: style });
|
|
15
|
+
return (React.createElement(ItemGrid, { items: items, maxItems: maxItems, columns: columns, className: className, style: style, getItemId: getItemId, getItemTitle: getItemTitle, getItemImage: getItemImage, getItemDescription: getItemDescription, getItemUrl: getItemUrl, renderItem: renderItem, onItemClick: (item, index) => trackClick(item, index) }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionLoading – loading state for section (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export interface SectionLoadingProps {
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
text?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function SectionLoading({ className, style, text }: SectionLoadingProps): React.JSX.Element | null;
|
|
11
|
+
//# sourceMappingURL=SectionLoading.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionLoading.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/SectionLoading.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,IAAmB,EAAE,EAAE,mBAAmB,4BAQ5F"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionLoading – loading state for section (primitive)
|
|
3
|
+
*/
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { useSectionSearchContext } from './SectionSearchContext';
|
|
6
|
+
export function SectionLoading({ className, style, text = 'Loading...' }) {
|
|
7
|
+
const { loading } = useSectionSearchContext();
|
|
8
|
+
if (!loading)
|
|
9
|
+
return null;
|
|
10
|
+
return (React.createElement("div", { className: className, style: { padding: 16, color: 'var(--seekora-text-secondary)', fontSize: '0.875rem', ...style } }, text));
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionSearchContext – preset query/filter section state
|
|
3
|
+
*
|
|
4
|
+
* For menus, sidebar, front-page blocks. Independent of main search state.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
export interface SectionSearchContextValue {
|
|
8
|
+
items: unknown[];
|
|
9
|
+
loading: boolean;
|
|
10
|
+
error: Error | null;
|
|
11
|
+
totalCount: number;
|
|
12
|
+
sectionId?: string;
|
|
13
|
+
trackClick: (item: unknown, position: number) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare const SectionSearchContext: React.Context<SectionSearchContextValue | null>;
|
|
16
|
+
export declare function useSectionSearchContext(): SectionSearchContextValue;
|
|
17
|
+
//# sourceMappingURL=SectionSearchContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionSearchContext.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/SectionSearchContext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAoC,MAAM,OAAO,CAAC;AAGzD,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACvD;AAED,eAAO,MAAM,oBAAoB,iDAAwD,CAAC;AAE1F,wBAAgB,uBAAuB,IAAI,yBAAyB,CAQnE"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionSearchContext – preset query/filter section state
|
|
3
|
+
*
|
|
4
|
+
* For menus, sidebar, front-page blocks. Independent of main search state.
|
|
5
|
+
*/
|
|
6
|
+
import { createContext, useContext } from 'react';
|
|
7
|
+
import { log } from '@seekora-ai/ui-sdk-core';
|
|
8
|
+
export const SectionSearchContext = createContext(null);
|
|
9
|
+
export function useSectionSearchContext() {
|
|
10
|
+
const context = useContext(SectionSearchContext);
|
|
11
|
+
if (!context) {
|
|
12
|
+
const error = new Error('useSectionSearchContext must be used within a SectionSearchProvider');
|
|
13
|
+
log.error('SectionSearchContext: not available', { error: error.message });
|
|
14
|
+
throw error;
|
|
15
|
+
}
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionSearchProvider – preset query + filter section
|
|
3
|
+
*
|
|
4
|
+
* Runs client.search(query, { refinements, hitsPerPage, sortBy }) on mount and when
|
|
5
|
+
* query/filters change. Does not use global SearchStateManager. Use for menus,
|
|
6
|
+
* sidebar, front-page blocks (e.g. "New arrivals", "On sale").
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
export interface RefinementInput {
|
|
10
|
+
field: string;
|
|
11
|
+
value: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SectionSearchProviderProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
query: string;
|
|
16
|
+
refinements?: RefinementInput[];
|
|
17
|
+
maxItems?: number;
|
|
18
|
+
sortBy?: string;
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
sectionId?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function SectionSearchProvider({ children, query, refinements, maxItems, sortBy, enabled, sectionId, }: SectionSearchProviderProps): React.JSX.Element;
|
|
23
|
+
//# sourceMappingURL=SectionSearchProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SectionSearchProvider.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/SectionSearchProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AAIzE,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsBD,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,KAAK,EACL,WAAgB,EAChB,QAAa,EACb,MAAM,EACN,OAAc,EACd,SAAS,GACV,EAAE,0BAA0B,qBAgF5B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SectionSearchProvider – preset query + filter section
|
|
3
|
+
*
|
|
4
|
+
* Runs client.search(query, { refinements, hitsPerPage, sortBy }) on mount and when
|
|
5
|
+
* query/filters change. Does not use global SearchStateManager. Use for menus,
|
|
6
|
+
* sidebar, front-page blocks (e.g. "New arrivals", "On sale").
|
|
7
|
+
*/
|
|
8
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
|
9
|
+
import { useSearchContext } from '../SearchProvider';
|
|
10
|
+
import { SectionSearchContext } from './SectionSearchContext';
|
|
11
|
+
function extractItems(response) {
|
|
12
|
+
if (!response)
|
|
13
|
+
return [];
|
|
14
|
+
if (Array.isArray(response.results))
|
|
15
|
+
return response.results;
|
|
16
|
+
if (Array.isArray(response.hits))
|
|
17
|
+
return response.hits;
|
|
18
|
+
const data = response.data;
|
|
19
|
+
if (data && Array.isArray(data.results))
|
|
20
|
+
return data.results;
|
|
21
|
+
if (data && Array.isArray(data.data))
|
|
22
|
+
return data.data;
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
function extractTotal(response) {
|
|
26
|
+
if (!response)
|
|
27
|
+
return 0;
|
|
28
|
+
const n = response.totalResults ?? response.total ?? response.total_results;
|
|
29
|
+
if (typeof n === 'number')
|
|
30
|
+
return n;
|
|
31
|
+
const data = response.data;
|
|
32
|
+
if (data?.total_results != null)
|
|
33
|
+
return Number(data.total_results);
|
|
34
|
+
if (data?.data?.total_results != null)
|
|
35
|
+
return Number(data.data.total_results);
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
export function SectionSearchProvider({ children, query, refinements = [], maxItems = 12, sortBy, enabled = true, sectionId, }) {
|
|
39
|
+
const { client } = useSearchContext();
|
|
40
|
+
const [items, setItems] = useState([]);
|
|
41
|
+
const [loading, setLoading] = useState(true);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
const [totalCount, setTotalCount] = useState(0);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!enabled || !client?.search) {
|
|
46
|
+
setItems([]);
|
|
47
|
+
setLoading(false);
|
|
48
|
+
setError(null);
|
|
49
|
+
setTotalCount(0);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
let cancelled = false;
|
|
53
|
+
setLoading(true);
|
|
54
|
+
setError(null);
|
|
55
|
+
const options = {
|
|
56
|
+
per_page: maxItems,
|
|
57
|
+
page: 1,
|
|
58
|
+
};
|
|
59
|
+
if (sortBy)
|
|
60
|
+
options.sort_by = sortBy;
|
|
61
|
+
if (refinements.length > 0) {
|
|
62
|
+
options.filter_by = refinements.map((r) => `${r.field}:${r.value}`).join(',');
|
|
63
|
+
}
|
|
64
|
+
client
|
|
65
|
+
.search(query, options)
|
|
66
|
+
.then((response) => {
|
|
67
|
+
if (cancelled)
|
|
68
|
+
return;
|
|
69
|
+
setItems(extractItems(response));
|
|
70
|
+
setTotalCount(extractTotal(response));
|
|
71
|
+
setLoading(false);
|
|
72
|
+
})
|
|
73
|
+
.catch((err) => {
|
|
74
|
+
if (cancelled)
|
|
75
|
+
return;
|
|
76
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
77
|
+
setItems([]);
|
|
78
|
+
setLoading(false);
|
|
79
|
+
});
|
|
80
|
+
return () => {
|
|
81
|
+
cancelled = true;
|
|
82
|
+
};
|
|
83
|
+
}, [client, enabled, query, maxItems, sortBy, refinements]);
|
|
84
|
+
const trackClick = useCallback((item, position) => {
|
|
85
|
+
if (!client?.trackEvent)
|
|
86
|
+
return;
|
|
87
|
+
const id = item?.id ?? item?.objectID;
|
|
88
|
+
client.trackEvent({
|
|
89
|
+
event_name: 'section_result_click',
|
|
90
|
+
clicked_item_id: id,
|
|
91
|
+
position,
|
|
92
|
+
section: sectionId,
|
|
93
|
+
metadata: { section_id: sectionId },
|
|
94
|
+
}, undefined);
|
|
95
|
+
}, [client, sectionId]);
|
|
96
|
+
const value = useMemo(() => ({
|
|
97
|
+
items,
|
|
98
|
+
loading,
|
|
99
|
+
error,
|
|
100
|
+
totalCount,
|
|
101
|
+
sectionId,
|
|
102
|
+
trackClick,
|
|
103
|
+
}), [items, loading, error, totalCount, sectionId, trackClick]);
|
|
104
|
+
return React.createElement(SectionSearchContext.Provider, { value: value }, children);
|
|
105
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { SectionSearchProvider, type RefinementInput, type SectionSearchProviderProps } from './SectionSearchProvider';
|
|
2
|
+
export { SectionSearchContext, useSectionSearchContext, type SectionSearchContextValue } from './SectionSearchContext';
|
|
3
|
+
export { SectionItemGrid, type SectionItemGridProps } from './SectionItemGrid';
|
|
4
|
+
export { SectionLoading, type SectionLoadingProps } from './SectionLoading';
|
|
5
|
+
export { SectionError, type SectionErrorProps } from './SectionError';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/section-primitives/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACvH,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACvH,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SectionSearchProvider } from './SectionSearchProvider';
|
|
2
|
+
export { SectionSearchContext, useSectionSearchContext } from './SectionSearchContext';
|
|
3
|
+
export { SectionItemGrid } from './SectionItemGrid';
|
|
4
|
+
export { SectionLoading } from './SectionLoading';
|
|
5
|
+
export { SectionError } from './SectionError';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CategoriesTabs – horizontal tabs (e.g. filtered tabs) (primitive)
|
|
3
|
+
*
|
|
4
|
+
* Active tab from context; on select updates context and tracks analytics.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
export interface CategoriesTabsProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: React.CSSProperties;
|
|
10
|
+
tabClassName?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function CategoriesTabs({ className, style, tabClassName }: CategoriesTabsProps): React.JSX.Element | null;
|
|
13
|
+
//# sourceMappingURL=CategoriesTabs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CategoriesTabs.d.ts","sourceRoot":"","sources":["../../../src/components/suggestions-primitives/CategoriesTabs.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,mBAAmB,4BA+CrF"}
|