@seekora-ai/ui-sdk-react 0.2.14 → 0.2.15
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/CurrentRefinements.d.ts.map +1 -1
- package/dist/components/CurrentRefinements.js +69 -9
- package/dist/components/FacetDropdown.d.ts +92 -0
- package/dist/components/FacetDropdown.d.ts.map +1 -0
- package/dist/components/FacetDropdown.js +374 -0
- package/dist/components/Facets.d.ts +26 -0
- package/dist/components/Facets.d.ts.map +1 -1
- package/dist/components/Facets.js +195 -6
- package/dist/components/FederatedDropdown.d.ts.map +1 -1
- package/dist/components/FederatedDropdown.js +45 -31
- package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -1
- package/dist/components/QuerySuggestionsDropdown.js +32 -18
- package/dist/components/RangeInput.d.ts.map +1 -1
- package/dist/components/RangeInput.js +6 -6
- package/dist/components/RangeSlider.d.ts.map +1 -1
- package/dist/components/RangeSlider.js +54 -32
- package/dist/components/RichQuerySuggestions.d.ts.map +1 -1
- package/dist/components/RichQuerySuggestions.js +40 -26
- package/dist/components/SearchBar.d.ts.map +1 -1
- package/dist/components/SearchBar.js +15 -7
- package/dist/components/SearchBarWithSuggestions.js +3 -3
- package/dist/components/SearchLayout.d.ts.map +1 -1
- package/dist/components/SearchLayout.js +10 -1
- package/dist/components/SearchResults.d.ts.map +1 -1
- package/dist/components/SearchResults.js +37 -25
- package/dist/components/primitives/ActionButtons.d.ts.map +1 -1
- package/dist/components/primitives/ActionButtons.js +34 -10
- package/dist/components/primitives/BadgeList.d.ts.map +1 -1
- package/dist/components/primitives/BadgeList.js +33 -13
- package/dist/components/primitives/ImageDisplay.d.ts.map +1 -1
- package/dist/components/primitives/ImageDisplay.js +11 -8
- package/dist/components/primitives/ImageZoom.js +26 -26
- package/dist/components/primitives/VariantSelector.js +10 -10
- package/dist/components/primitives/VariantSwatches.js +3 -3
- package/dist/components/product-page/ProductGallery.d.ts +8 -1
- package/dist/components/product-page/ProductGallery.d.ts.map +1 -1
- package/dist/components/product-page/ProductGallery.js +2 -2
- package/dist/components/section-primitives/SectionSearchProvider.d.ts +3 -1
- package/dist/components/section-primitives/SectionSearchProvider.d.ts.map +1 -1
- package/dist/components/section-primitives/SectionSearchProvider.js +3 -2
- package/dist/components/suggestions/MobileSheetDropdown.js +18 -18
- package/dist/components/suggestions/ShopifyDropdown.js +37 -37
- package/dist/components/suggestions-primitives/DropdownPanel.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/DropdownPanel.js +15 -2
- package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ItemCard.js +21 -8
- package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ItemGrid.js +9 -3
- package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ProductCard.js +25 -10
- package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/ProductCardLayouts.js +24 -12
- package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SearchInput.js +28 -9
- package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -1
- package/dist/components/suggestions-primitives/SuggestionItem.js +3 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.umd.js +1 -1
- package/dist/src/index.d.ts +129 -4
- package/dist/src/index.esm.js +1361 -616
- package/dist/src/index.esm.js.map +1 -1
- package/dist/src/index.js +1361 -615
- package/dist/src/index.js.map +1 -1
- package/package.json +6 -6
package/dist/src/index.js
CHANGED
|
@@ -1570,6 +1570,9 @@ function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else i
|
|
|
1570
1570
|
*
|
|
1571
1571
|
* Interactive search input component with query suggestions support
|
|
1572
1572
|
*/
|
|
1573
|
+
// Z-index scale for consistent layering
|
|
1574
|
+
const Z_INDEX$2 = {
|
|
1575
|
+
dropdown: 100};
|
|
1573
1576
|
const SIZE_CONFIG = {
|
|
1574
1577
|
small: {
|
|
1575
1578
|
padding: '0.375rem 0.5rem',
|
|
@@ -1753,9 +1756,9 @@ const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounce
|
|
|
1753
1756
|
const inputPaddingLeft = sizeConfig.iconPaddingLeft ;
|
|
1754
1757
|
const inputPaddingRight = hasClearBtn ? sizeConfig.iconPaddingRight : sizeConfig.padding.split(' ')[1] || sizeConfig.padding;
|
|
1755
1758
|
const borderRadius = typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium;
|
|
1756
|
-
const focusBorderColor = isFocused ? theme.colors.focus : theme.colors.border
|
|
1759
|
+
const focusBorderColor = isFocused ? `var(--seekora-border-focus, ${theme.colors.focus})` : `var(--seekora-border, ${theme.colors.border})`;
|
|
1757
1760
|
const focusRingShadow = isFocused
|
|
1758
|
-
? `0 0 0 3px ${theme.colors.focus}33`
|
|
1761
|
+
? `0 0 0 3px var(--seekora-border-focus-alpha, ${theme.colors.focus}33)`
|
|
1759
1762
|
: undefined;
|
|
1760
1763
|
const handleClear = React.useCallback(() => {
|
|
1761
1764
|
setQuery('', false);
|
|
@@ -1789,7 +1792,7 @@ const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounce
|
|
|
1789
1792
|
justifyContent: 'center',
|
|
1790
1793
|
pointerEvents: 'none',
|
|
1791
1794
|
color: 'var(--seekora-searchbar-icon-color)',
|
|
1792
|
-
zIndex:
|
|
1795
|
+
zIndex: 2,
|
|
1793
1796
|
} }, renderSearchIcon ? renderSearchIcon() : React.createElement(DefaultSearchIcon, { size: sizeConfig.iconSize }))),
|
|
1794
1797
|
React.createElement("input", { ref: inputRef, type: "text", value: query, onChange: handleInputChange, onKeyDown: handleKeyDown, onFocus: handleFocus, onBlur: handleBlur, placeholder: placeholder, className: clsx(searchBarTheme.input, isFocused && searchBarTheme.inputFocused), style: {
|
|
1795
1798
|
width: '100%',
|
|
@@ -1825,7 +1828,7 @@ const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounce
|
|
|
1825
1828
|
borderRadius: '50%',
|
|
1826
1829
|
color: 'var(--seekora-searchbar-icon-color)',
|
|
1827
1830
|
transition: theme.transitions?.fast || '150ms ease-in-out',
|
|
1828
|
-
zIndex:
|
|
1831
|
+
zIndex: 2,
|
|
1829
1832
|
}, onMouseDown: (e) => {
|
|
1830
1833
|
// Prevent input blur so the clear action doesn't race with blur handler
|
|
1831
1834
|
e.preventDefault();
|
|
@@ -1836,8 +1839,8 @@ const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounce
|
|
|
1836
1839
|
fontSize: sizeConfig.fontSize,
|
|
1837
1840
|
fontFamily: theme.typography.fontFamily,
|
|
1838
1841
|
fontWeight: theme.typography.fontWeight?.medium ?? 500,
|
|
1839
|
-
backgroundColor: theme.colors.primary
|
|
1840
|
-
color: '#ffffff',
|
|
1842
|
+
backgroundColor: `var(--seekora-primary, ${theme.colors.primary})`,
|
|
1843
|
+
color: 'var(--seekora-primary-text, #ffffff)',
|
|
1841
1844
|
border: 'none',
|
|
1842
1845
|
borderRadius: 'var(--seekora-searchbar-radius)',
|
|
1843
1846
|
cursor: 'pointer',
|
|
@@ -1865,7 +1868,8 @@ const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounce
|
|
|
1865
1868
|
boxShadow: theme.shadows.medium,
|
|
1866
1869
|
maxHeight: '400px',
|
|
1867
1870
|
overflowY: 'auto',
|
|
1868
|
-
zIndex:
|
|
1871
|
+
zIndex: Z_INDEX$2.dropdown,
|
|
1872
|
+
boxSizing: 'border-box',
|
|
1869
1873
|
} },
|
|
1870
1874
|
isLoading && displayedSuggestions.length === 0 && showLoadingState && (renderLoading ? renderLoading() : defaultRenderLoading()),
|
|
1871
1875
|
displayedSuggestions.length > 0 && (React.createElement(React.Fragment, null, displayedSuggestions.map((suggestion, index) => {
|
|
@@ -1934,6 +1938,43 @@ const SearchResults = ({ results: resultsProp, loading: loadingProp, error: erro
|
|
|
1934
1938
|
}
|
|
1935
1939
|
}
|
|
1936
1940
|
}, [activeIndex, enableKeyboardNavigation]);
|
|
1941
|
+
// Global keyboard listener for seamless navigation from search box to results
|
|
1942
|
+
React.useEffect(() => {
|
|
1943
|
+
if (!enableKeyboardNavigation)
|
|
1944
|
+
return;
|
|
1945
|
+
const handleGlobalKeyDown = (e) => {
|
|
1946
|
+
// Only handle if we have results and the container exists
|
|
1947
|
+
if (!containerRef.current)
|
|
1948
|
+
return;
|
|
1949
|
+
const resultElements = containerRef.current.querySelectorAll('[data-result-index]');
|
|
1950
|
+
const maxIndex = resultElements.length - 1;
|
|
1951
|
+
if (maxIndex < 0)
|
|
1952
|
+
return;
|
|
1953
|
+
// Check if focus is on an input/textarea (search box)
|
|
1954
|
+
const activeElement = document.activeElement;
|
|
1955
|
+
const isInputFocused = activeElement?.tagName === 'INPUT' || activeElement?.tagName === 'TEXTAREA';
|
|
1956
|
+
if (e.key === 'ArrowDown') {
|
|
1957
|
+
// If in search box or no result selected, select first result
|
|
1958
|
+
if (isInputFocused || activeIndex === -1) {
|
|
1959
|
+
e.preventDefault();
|
|
1960
|
+
setActiveIndex(0);
|
|
1961
|
+
containerRef.current?.focus();
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
else if (e.key === 'ArrowUp') {
|
|
1965
|
+
// If first result is selected, go back to search box
|
|
1966
|
+
if (activeIndex === 0) {
|
|
1967
|
+
e.preventDefault();
|
|
1968
|
+
setActiveIndex(-1);
|
|
1969
|
+
// Find and focus the search input
|
|
1970
|
+
const searchInput = document.querySelector('input[type="text"], input[type="search"]');
|
|
1971
|
+
searchInput?.focus();
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
document.addEventListener('keydown', handleGlobalKeyDown);
|
|
1976
|
+
return () => document.removeEventListener('keydown', handleGlobalKeyDown);
|
|
1977
|
+
}, [enableKeyboardNavigation, activeIndex]);
|
|
1937
1978
|
// Keyboard navigation handler
|
|
1938
1979
|
const handleKeyDown = React.useCallback((e) => {
|
|
1939
1980
|
if (!enableKeyboardNavigation)
|
|
@@ -2309,31 +2350,6 @@ const SearchResults = ({ results: resultsProp, loading: loadingProp, error: erro
|
|
|
2309
2350
|
results?.totalResults || results?.data?.total_results || 0,
|
|
2310
2351
|
" result",
|
|
2311
2352
|
(results?.totalResults || results?.data?.total_results || 0) !== 1 ? 's' : '')),
|
|
2312
|
-
enableKeyboardNavigation && resultItems.length > 0 && (React.createElement("div", { style: {
|
|
2313
|
-
fontSize: '12px',
|
|
2314
|
-
color: theme.colors.text,
|
|
2315
|
-
opacity: 0.6,
|
|
2316
|
-
marginBottom: theme.spacing.small,
|
|
2317
|
-
display: 'flex',
|
|
2318
|
-
gap: '8px',
|
|
2319
|
-
alignItems: 'center',
|
|
2320
|
-
} },
|
|
2321
|
-
React.createElement("span", { style: {
|
|
2322
|
-
display: 'inline-flex',
|
|
2323
|
-
gap: '4px',
|
|
2324
|
-
padding: '2px 6px',
|
|
2325
|
-
backgroundColor: theme.colors.hover,
|
|
2326
|
-
borderRadius: '4px',
|
|
2327
|
-
fontSize: '11px',
|
|
2328
|
-
} }, "\u2191\u2193 navigate"),
|
|
2329
|
-
React.createElement("span", { style: {
|
|
2330
|
-
display: 'inline-flex',
|
|
2331
|
-
gap: '4px',
|
|
2332
|
-
padding: '2px 6px',
|
|
2333
|
-
backgroundColor: theme.colors.hover,
|
|
2334
|
-
borderRadius: '4px',
|
|
2335
|
-
fontSize: '11px',
|
|
2336
|
-
} }, "\u21B5 select"))),
|
|
2337
2353
|
React.createElement("div", { className: searchResultsTheme.resultsList, style: resultsListStyle }, resultItems.map((result, index) => renderFn(result, index, index === activeIndex)))));
|
|
2338
2354
|
};
|
|
2339
2355
|
|
|
@@ -2995,6 +3011,261 @@ const SortBy = ({ options, value: valueProp, defaultValue, onSortChange, renderS
|
|
|
2995
3011
|
return null;
|
|
2996
3012
|
};
|
|
2997
3013
|
|
|
3014
|
+
/**
|
|
3015
|
+
* RangeSlider Component
|
|
3016
|
+
*
|
|
3017
|
+
* Visual slider for numeric range filtering
|
|
3018
|
+
* Alternative to RangeInput for a more interactive UX
|
|
3019
|
+
*/
|
|
3020
|
+
const SHADOWS$1 = {
|
|
3021
|
+
md: '0 2px 4px rgba(0,0,0,0.1)'};
|
|
3022
|
+
const RangeSlider = ({ field, label, min, max, step = 1, currentMin: currentMinProp, currentMax: currentMaxProp, onRangeChange, formatValue = (v) => v.toString(), className, style, theme: customTheme, showValues = true, syncWithState = true, debounceMs = 300, }) => {
|
|
3023
|
+
const { theme } = useSearchContext();
|
|
3024
|
+
const { refinements, addRefinement, removeRefinement } = useSearchState();
|
|
3025
|
+
const rangeSliderTheme = customTheme || {};
|
|
3026
|
+
const thumbClass = rangeSliderTheme.thumb || 'seekora-range-slider__thumb';
|
|
3027
|
+
// Parse current range from StateManager
|
|
3028
|
+
// NOTE: computed every render (no useMemo) because the state manager mutates
|
|
3029
|
+
// the refinements array in place — the reference never changes.
|
|
3030
|
+
let stateRange;
|
|
3031
|
+
if (!syncWithState) {
|
|
3032
|
+
stateRange = { min: undefined, max: undefined };
|
|
3033
|
+
}
|
|
3034
|
+
else {
|
|
3035
|
+
let minVal;
|
|
3036
|
+
let maxVal;
|
|
3037
|
+
refinements.forEach(r => {
|
|
3038
|
+
if (r.field === field) {
|
|
3039
|
+
const minMatch = r.value.match(/^>=(\d+(?:\.\d+)?)$/);
|
|
3040
|
+
if (minMatch)
|
|
3041
|
+
minVal = parseFloat(minMatch[1]);
|
|
3042
|
+
const maxMatch = r.value.match(/^<=(\d+(?:\.\d+)?)$/);
|
|
3043
|
+
if (maxMatch)
|
|
3044
|
+
maxVal = parseFloat(maxMatch[1]);
|
|
3045
|
+
}
|
|
3046
|
+
});
|
|
3047
|
+
stateRange = { min: minVal, max: maxVal };
|
|
3048
|
+
}
|
|
3049
|
+
const [internalMin, setInternalMin] = React.useState(currentMinProp ?? stateRange.min ?? min);
|
|
3050
|
+
const [internalMax, setInternalMax] = React.useState(currentMaxProp ?? stateRange.max ?? max);
|
|
3051
|
+
const isDraggingRef = React.useRef(false);
|
|
3052
|
+
const debounceRef = React.useRef(null);
|
|
3053
|
+
const pendingMinRef = React.useRef(internalMin);
|
|
3054
|
+
const pendingMaxRef = React.useRef(internalMax);
|
|
3055
|
+
// Sync with StateManager changes (only when stateRange actually changes, not on drag)
|
|
3056
|
+
React.useEffect(() => {
|
|
3057
|
+
if (syncWithState && !isDraggingRef.current) {
|
|
3058
|
+
if (stateRange.min !== undefined)
|
|
3059
|
+
setInternalMin(stateRange.min);
|
|
3060
|
+
else
|
|
3061
|
+
setInternalMin(min);
|
|
3062
|
+
if (stateRange.max !== undefined)
|
|
3063
|
+
setInternalMax(stateRange.max);
|
|
3064
|
+
else
|
|
3065
|
+
setInternalMax(max);
|
|
3066
|
+
}
|
|
3067
|
+
}, [syncWithState, stateRange.min, stateRange.max, min, max]);
|
|
3068
|
+
// Update StateManager with range refinements
|
|
3069
|
+
const updateStateManager = React.useCallback((minVal, maxVal) => {
|
|
3070
|
+
if (!syncWithState)
|
|
3071
|
+
return;
|
|
3072
|
+
// Remove existing range refinements for this field
|
|
3073
|
+
refinements.forEach(r => {
|
|
3074
|
+
if (r.field === field) {
|
|
3075
|
+
removeRefinement(field, r.value, false);
|
|
3076
|
+
}
|
|
3077
|
+
});
|
|
3078
|
+
// Add new range refinements — trigger search on the last one added
|
|
3079
|
+
const setMin = minVal > min;
|
|
3080
|
+
const setMax = maxVal < max;
|
|
3081
|
+
if (setMin && setMax) {
|
|
3082
|
+
addRefinement(field, `>=${minVal}`, false);
|
|
3083
|
+
addRefinement(field, `<=${maxVal}`, true);
|
|
3084
|
+
}
|
|
3085
|
+
else if (setMin) {
|
|
3086
|
+
addRefinement(field, `>=${minVal}`, true);
|
|
3087
|
+
}
|
|
3088
|
+
else if (setMax) {
|
|
3089
|
+
addRefinement(field, `<=${maxVal}`, true);
|
|
3090
|
+
}
|
|
3091
|
+
}, [syncWithState, field, refinements, addRefinement, removeRefinement, min, max]);
|
|
3092
|
+
// Debounced update (during drag only)
|
|
3093
|
+
const debouncedUpdate = React.useCallback((minVal, maxVal) => {
|
|
3094
|
+
pendingMinRef.current = minVal;
|
|
3095
|
+
pendingMaxRef.current = maxVal;
|
|
3096
|
+
if (debounceRef.current) {
|
|
3097
|
+
clearTimeout(debounceRef.current);
|
|
3098
|
+
}
|
|
3099
|
+
debounceRef.current = setTimeout(() => {
|
|
3100
|
+
updateStateManager(minVal, maxVal);
|
|
3101
|
+
if (onRangeChange) {
|
|
3102
|
+
onRangeChange(minVal, maxVal);
|
|
3103
|
+
}
|
|
3104
|
+
}, debounceMs);
|
|
3105
|
+
}, [updateStateManager, onRangeChange, debounceMs]);
|
|
3106
|
+
// Handle min slider change
|
|
3107
|
+
const handleMinChange = (e) => {
|
|
3108
|
+
const value = Math.min(Number(e.target.value), internalMax - step);
|
|
3109
|
+
setInternalMin(value);
|
|
3110
|
+
isDraggingRef.current = true;
|
|
3111
|
+
debouncedUpdate(value, internalMax);
|
|
3112
|
+
};
|
|
3113
|
+
// Handle max slider change
|
|
3114
|
+
const handleMaxChange = (e) => {
|
|
3115
|
+
const value = Math.max(Number(e.target.value), internalMin + step);
|
|
3116
|
+
setInternalMax(value);
|
|
3117
|
+
isDraggingRef.current = true;
|
|
3118
|
+
debouncedUpdate(internalMin, value);
|
|
3119
|
+
};
|
|
3120
|
+
// Handle drag end — flush pending update immediately
|
|
3121
|
+
const handleDragEnd = () => {
|
|
3122
|
+
isDraggingRef.current = false;
|
|
3123
|
+
// Cancel the debounce and commit immediately
|
|
3124
|
+
if (debounceRef.current) {
|
|
3125
|
+
clearTimeout(debounceRef.current);
|
|
3126
|
+
debounceRef.current = null;
|
|
3127
|
+
}
|
|
3128
|
+
updateStateManager(pendingMinRef.current, pendingMaxRef.current);
|
|
3129
|
+
if (onRangeChange) {
|
|
3130
|
+
onRangeChange(pendingMinRef.current, pendingMaxRef.current);
|
|
3131
|
+
}
|
|
3132
|
+
};
|
|
3133
|
+
// Handle keyboard navigation for enhanced control (Shift+Arrow for 10x step, Home/End)
|
|
3134
|
+
const handleMinKeyDown = (e) => {
|
|
3135
|
+
let newValue = null;
|
|
3136
|
+
if (e.key === 'Home') {
|
|
3137
|
+
e.preventDefault();
|
|
3138
|
+
newValue = min;
|
|
3139
|
+
}
|
|
3140
|
+
else if (e.key === 'End') {
|
|
3141
|
+
e.preventDefault();
|
|
3142
|
+
newValue = internalMax - step;
|
|
3143
|
+
}
|
|
3144
|
+
else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
|
|
3145
|
+
e.preventDefault();
|
|
3146
|
+
newValue = Math.max(min, internalMin - step * 10);
|
|
3147
|
+
}
|
|
3148
|
+
else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
|
|
3149
|
+
e.preventDefault();
|
|
3150
|
+
newValue = Math.min(internalMax - step, internalMin + step * 10);
|
|
3151
|
+
}
|
|
3152
|
+
if (newValue !== null) {
|
|
3153
|
+
setInternalMin(newValue);
|
|
3154
|
+
debouncedUpdate(newValue, internalMax);
|
|
3155
|
+
}
|
|
3156
|
+
};
|
|
3157
|
+
const handleMaxKeyDown = (e) => {
|
|
3158
|
+
let newValue = null;
|
|
3159
|
+
if (e.key === 'Home') {
|
|
3160
|
+
e.preventDefault();
|
|
3161
|
+
newValue = internalMin + step;
|
|
3162
|
+
}
|
|
3163
|
+
else if (e.key === 'End') {
|
|
3164
|
+
e.preventDefault();
|
|
3165
|
+
newValue = max;
|
|
3166
|
+
}
|
|
3167
|
+
else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
|
|
3168
|
+
e.preventDefault();
|
|
3169
|
+
newValue = Math.max(internalMin + step, internalMax - step * 10);
|
|
3170
|
+
}
|
|
3171
|
+
else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
|
|
3172
|
+
e.preventDefault();
|
|
3173
|
+
newValue = Math.min(max, internalMax + step * 10);
|
|
3174
|
+
}
|
|
3175
|
+
if (newValue !== null) {
|
|
3176
|
+
setInternalMax(newValue);
|
|
3177
|
+
debouncedUpdate(internalMin, newValue);
|
|
3178
|
+
}
|
|
3179
|
+
};
|
|
3180
|
+
// Calculate filled track position
|
|
3181
|
+
const minPercent = ((internalMin - min) / (max - min)) * 100;
|
|
3182
|
+
const maxPercent = ((internalMax - min) / (max - min)) * 100;
|
|
3183
|
+
return (React.createElement("div", { className: clsx(rangeSliderTheme.root, className), style: {
|
|
3184
|
+
fontFamily: 'inherit',
|
|
3185
|
+
...style,
|
|
3186
|
+
} },
|
|
3187
|
+
label && (React.createElement("label", { className: rangeSliderTheme.label, style: {
|
|
3188
|
+
display: 'block',
|
|
3189
|
+
marginBottom: theme.spacing.small,
|
|
3190
|
+
fontSize: theme.typography.fontSize.medium,
|
|
3191
|
+
fontWeight: theme.typography.fontWeight?.medium || 500,
|
|
3192
|
+
color: theme.colors.text,
|
|
3193
|
+
} }, label)),
|
|
3194
|
+
React.createElement("div", { className: rangeSliderTheme.slider, style: {
|
|
3195
|
+
position: 'relative',
|
|
3196
|
+
minHeight: '40px',
|
|
3197
|
+
display: 'flex',
|
|
3198
|
+
alignItems: 'center',
|
|
3199
|
+
} },
|
|
3200
|
+
React.createElement("div", { className: rangeSliderTheme.track, style: {
|
|
3201
|
+
position: 'absolute',
|
|
3202
|
+
width: '100%',
|
|
3203
|
+
height: '4px',
|
|
3204
|
+
backgroundColor: theme.colors.border,
|
|
3205
|
+
borderRadius: '2px',
|
|
3206
|
+
} }),
|
|
3207
|
+
React.createElement("div", { className: rangeSliderTheme.trackFilled, style: {
|
|
3208
|
+
position: 'absolute',
|
|
3209
|
+
left: `${minPercent}%`,
|
|
3210
|
+
width: `${maxPercent - minPercent}%`,
|
|
3211
|
+
height: '4px',
|
|
3212
|
+
backgroundColor: theme.colors.primary,
|
|
3213
|
+
borderRadius: '2px',
|
|
3214
|
+
} }),
|
|
3215
|
+
React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMin, onChange: handleMinChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMinKeyDown, tabIndex: 0, "aria-valuenow": internalMin, "aria-valuemin": min, "aria-valuemax": max, className: thumbClass, style: {
|
|
3216
|
+
position: 'absolute',
|
|
3217
|
+
width: '100%',
|
|
3218
|
+
height: '4px',
|
|
3219
|
+
background: 'transparent',
|
|
3220
|
+
WebkitAppearance: 'none',
|
|
3221
|
+
appearance: 'none',
|
|
3222
|
+
cursor: 'pointer',
|
|
3223
|
+
pointerEvents: 'none',
|
|
3224
|
+
}, "aria-label": `Minimum ${label || field}` }),
|
|
3225
|
+
React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMax, onChange: handleMaxChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMaxKeyDown, tabIndex: 0, "aria-valuenow": internalMax, "aria-valuemin": min, "aria-valuemax": max, className: thumbClass, style: {
|
|
3226
|
+
position: 'absolute',
|
|
3227
|
+
width: '100%',
|
|
3228
|
+
height: '4px',
|
|
3229
|
+
background: 'transparent',
|
|
3230
|
+
WebkitAppearance: 'none',
|
|
3231
|
+
appearance: 'none',
|
|
3232
|
+
cursor: 'pointer',
|
|
3233
|
+
pointerEvents: 'none',
|
|
3234
|
+
}, "aria-label": `Maximum ${label || field}` })),
|
|
3235
|
+
showValues && (React.createElement("div", { className: rangeSliderTheme.values, style: {
|
|
3236
|
+
display: 'flex',
|
|
3237
|
+
justifyContent: 'space-between',
|
|
3238
|
+
marginTop: theme.spacing.small,
|
|
3239
|
+
fontSize: theme.typography.fontSize.small,
|
|
3240
|
+
color: theme.colors.textSecondary,
|
|
3241
|
+
} },
|
|
3242
|
+
React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMin)),
|
|
3243
|
+
React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMax)))),
|
|
3244
|
+
React.createElement("style", null, `
|
|
3245
|
+
.${thumbClass}::-webkit-slider-thumb {
|
|
3246
|
+
-webkit-appearance: none;
|
|
3247
|
+
appearance: none;
|
|
3248
|
+
width: 20px;
|
|
3249
|
+
height: 20px;
|
|
3250
|
+
background: ${theme.colors.primary};
|
|
3251
|
+
border-radius: 50%;
|
|
3252
|
+
cursor: pointer;
|
|
3253
|
+
pointer-events: all;
|
|
3254
|
+
box-shadow: ${SHADOWS$1.md};
|
|
3255
|
+
}
|
|
3256
|
+
.${thumbClass}::-moz-range-thumb {
|
|
3257
|
+
width: 20px;
|
|
3258
|
+
height: 20px;
|
|
3259
|
+
background: ${theme.colors.primary};
|
|
3260
|
+
border-radius: 50%;
|
|
3261
|
+
cursor: pointer;
|
|
3262
|
+
pointer-events: all;
|
|
3263
|
+
border: none;
|
|
3264
|
+
box-shadow: ${SHADOWS$1.md};
|
|
3265
|
+
}
|
|
3266
|
+
`)));
|
|
3267
|
+
};
|
|
3268
|
+
|
|
2998
3269
|
/**
|
|
2999
3270
|
* Facets Component
|
|
3000
3271
|
*
|
|
@@ -3044,17 +3315,19 @@ const CheckmarkIcon = ({ size = 16 }) => (React.createElement("svg", { width: si
|
|
|
3044
3315
|
// CSS variable defaults
|
|
3045
3316
|
// ---------------------------------------------------------------------------
|
|
3046
3317
|
const CSS_VAR_DEFAULTS = {
|
|
3047
|
-
'--seekora-facet-bg': '
|
|
3318
|
+
'--seekora-facet-bg': 'transparent',
|
|
3048
3319
|
'--seekora-facet-border': '#dee2e6',
|
|
3049
|
-
'--seekora-facet-active-bg': '
|
|
3320
|
+
'--seekora-facet-active-bg': 'rgba(0, 0, 0, 0.05)',
|
|
3050
3321
|
'--seekora-facet-swatch-size': '32px',
|
|
3051
3322
|
'--seekora-facet-count-bg': '#e9ecef',
|
|
3052
3323
|
'--seekora-facet-count-color': '#495057',
|
|
3324
|
+
'--seekora-primary': '#3b82f6',
|
|
3325
|
+
'--seekora-primary-text': '#ffffff',
|
|
3053
3326
|
};
|
|
3054
3327
|
// ---------------------------------------------------------------------------
|
|
3055
3328
|
// Component
|
|
3056
3329
|
// ---------------------------------------------------------------------------
|
|
3057
|
-
const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, renderFacet, renderFacetItem, maxItems = 10, showMore = true, className, style, theme: customTheme, variant = 'checkbox', searchable = false, showCounts = true, colorMap, defaultCollapsed = false, size = 'medium', }) => {
|
|
3330
|
+
const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, renderFacet, renderFacetItem, maxItems = 10, showMore = true, className, style, theme: customTheme, variant = 'checkbox', searchable = false, showCounts = true, colorMap, defaultCollapsed = false, size = 'medium', facetRanges, }) => {
|
|
3058
3331
|
const { theme } = useSearchContext();
|
|
3059
3332
|
const { results: stateResults, refinements, addRefinement, removeRefinement } = useSearchState();
|
|
3060
3333
|
const facetsTheme = customTheme || {};
|
|
@@ -3104,6 +3377,7 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3104
3377
|
count: count.count,
|
|
3105
3378
|
selected: refinements.some(r => r.field === fieldName && r.value === count.value),
|
|
3106
3379
|
})) : [],
|
|
3380
|
+
stats: facet.stats || undefined,
|
|
3107
3381
|
};
|
|
3108
3382
|
});
|
|
3109
3383
|
log.verbose('Facets: Extracted facets', {
|
|
@@ -3181,7 +3455,7 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3181
3455
|
const sizeScale = React.useMemo(() => {
|
|
3182
3456
|
switch (size) {
|
|
3183
3457
|
case 'small':
|
|
3184
|
-
return { font: theme.typography.fontSize.small, padding: '0.
|
|
3458
|
+
return { font: theme.typography.fontSize.small, padding: '0.5rem', gap: '0.5rem' };
|
|
3185
3459
|
case 'large':
|
|
3186
3460
|
return { font: theme.typography.fontSize.large, padding: '0.75rem', gap: '0.75rem' };
|
|
3187
3461
|
case 'medium':
|
|
@@ -3250,6 +3524,7 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3250
3524
|
? 'var(--seekora-facet-active-bg, ' + theme.colors.hover + ')'
|
|
3251
3525
|
: 'transparent',
|
|
3252
3526
|
transition: 'background-color 0.2s ease',
|
|
3527
|
+
boxSizing: 'border-box',
|
|
3253
3528
|
} },
|
|
3254
3529
|
React.createElement("input", { type: "checkbox", checked: refinements.some(r => r.field === facet.field && r.value === item.value) || item.selected || false, onChange: () => handleFacetToggle(facet.field, item.value, item.selected || false), className: facetsTheme.checkbox, style: {
|
|
3255
3530
|
marginRight: sizeScale.gap,
|
|
@@ -3258,6 +3533,7 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3258
3533
|
React.createElement("span", { className: facetsTheme.facetItemLabel, style: {
|
|
3259
3534
|
flex: 1,
|
|
3260
3535
|
fontSize: sizeScale.font,
|
|
3536
|
+
lineHeight: 1.5,
|
|
3261
3537
|
color: theme.colors.text,
|
|
3262
3538
|
} }, item.value),
|
|
3263
3539
|
renderCountBadge(item.count)));
|
|
@@ -3286,13 +3562,13 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3286
3562
|
borderRadius: '50%',
|
|
3287
3563
|
backgroundColor: color,
|
|
3288
3564
|
border: isChecked
|
|
3289
|
-
? `3px solid ${theme.colors.primary}`
|
|
3565
|
+
? `3px solid var(--seekora-primary, ${theme.colors.primary})`
|
|
3290
3566
|
: `2px solid var(--seekora-facet-border, ${theme.colors.border})`,
|
|
3291
3567
|
display: 'flex',
|
|
3292
3568
|
alignItems: 'center',
|
|
3293
3569
|
justifyContent: 'center',
|
|
3294
3570
|
transition: 'border 0.2s ease, box-shadow 0.2s ease',
|
|
3295
|
-
boxShadow: isChecked ? `0 0 0 2px ${theme.colors.primary}33` : 'none',
|
|
3571
|
+
boxShadow: isChecked ? `0 0 0 2px var(--seekora-primary-alpha, ${theme.colors.primary}33)` : 'none',
|
|
3296
3572
|
position: 'relative',
|
|
3297
3573
|
} }, isChecked && (React.createElement("span", { className: clsx(facetsTheme.colorSwatchInner), style: {
|
|
3298
3574
|
display: 'flex',
|
|
@@ -3518,21 +3794,204 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3518
3794
|
} }, "Show less"))))));
|
|
3519
3795
|
};
|
|
3520
3796
|
// -------------------------------------------------------------------
|
|
3521
|
-
//
|
|
3797
|
+
// Render-type detection for numeric / range facets
|
|
3522
3798
|
// -------------------------------------------------------------------
|
|
3523
|
-
const
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
case 'collapsible':
|
|
3528
|
-
return renderCollapsibleFacet(facet);
|
|
3529
|
-
case 'checkbox':
|
|
3530
|
-
default:
|
|
3531
|
-
return renderCheckboxFacet(facet);
|
|
3799
|
+
const determineFacetRenderType = (fieldName, stats) => {
|
|
3800
|
+
// If explicit range config exists for this field → range buttons
|
|
3801
|
+
if (facetRanges?.some((rc) => rc.field === fieldName)) {
|
|
3802
|
+
return 'range-buttons';
|
|
3532
3803
|
}
|
|
3804
|
+
// If stats with valid min/max → range slider
|
|
3805
|
+
if (stats && typeof stats.min === 'number' && typeof stats.max === 'number' && stats.min !== stats.max) {
|
|
3806
|
+
return 'range-slider';
|
|
3807
|
+
}
|
|
3808
|
+
return 'list';
|
|
3533
3809
|
};
|
|
3534
3810
|
// -------------------------------------------------------------------
|
|
3535
|
-
//
|
|
3811
|
+
// Range button facet renderer
|
|
3812
|
+
// -------------------------------------------------------------------
|
|
3813
|
+
const renderRangeButtonFacet = (facet, _index) => {
|
|
3814
|
+
const rangeConfig = facetRanges?.find((rc) => rc.field === facet.field);
|
|
3815
|
+
if (!rangeConfig)
|
|
3816
|
+
return null;
|
|
3817
|
+
// Build a lookup from item value → count
|
|
3818
|
+
const countMap = new Map();
|
|
3819
|
+
facet.items.forEach((item) => countMap.set(item.value, item.count));
|
|
3820
|
+
// Detect currently active range from refinements
|
|
3821
|
+
const activeMin = refinements.find((r) => r.field === facet.field && r.value.startsWith('>='));
|
|
3822
|
+
const activeMax = refinements.find((r) => r.field === facet.field && r.value.startsWith('<='));
|
|
3823
|
+
const activeFromVal = activeMin ? parseFloat(activeMin.value.slice(2)) : undefined;
|
|
3824
|
+
const activeToVal = activeMax ? parseFloat(activeMax.value.slice(2)) : undefined;
|
|
3825
|
+
const isRangeActive = (range) => {
|
|
3826
|
+
const fromMatch = range.from === undefined
|
|
3827
|
+
? activeFromVal === undefined
|
|
3828
|
+
: activeFromVal === range.from;
|
|
3829
|
+
const toMatch = range.to === undefined
|
|
3830
|
+
? activeToVal === undefined
|
|
3831
|
+
: activeToVal === range.to;
|
|
3832
|
+
return fromMatch && toMatch;
|
|
3833
|
+
};
|
|
3834
|
+
const handleRangeClick = (range) => {
|
|
3835
|
+
// Clear existing range refinements for this field
|
|
3836
|
+
refinements
|
|
3837
|
+
.filter((r) => r.field === facet.field)
|
|
3838
|
+
.forEach((r) => removeRefinement(facet.field, r.value, false));
|
|
3839
|
+
if (isRangeActive(range)) {
|
|
3840
|
+
// Was active → just clear (already removed above), trigger search
|
|
3841
|
+
addRefinement(facet.field, '__noop__', false);
|
|
3842
|
+
removeRefinement(facet.field, '__noop__', true);
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
// Set new range
|
|
3846
|
+
if (range.from !== undefined) {
|
|
3847
|
+
addRefinement(facet.field, `>=${range.from}`, false);
|
|
3848
|
+
}
|
|
3849
|
+
if (range.to !== undefined) {
|
|
3850
|
+
addRefinement(facet.field, `<=${range.to}`, true);
|
|
3851
|
+
}
|
|
3852
|
+
else if (range.from !== undefined) {
|
|
3853
|
+
// Only "from" set — trigger search
|
|
3854
|
+
addRefinement(facet.field, `>=${range.from}`, true);
|
|
3855
|
+
}
|
|
3856
|
+
};
|
|
3857
|
+
const hasActiveRange = activeMin !== undefined || activeMax !== undefined;
|
|
3858
|
+
const handleClear = () => {
|
|
3859
|
+
refinements
|
|
3860
|
+
.filter((r) => r.field === facet.field)
|
|
3861
|
+
.forEach((r) => removeRefinement(facet.field, r.value, false));
|
|
3862
|
+
// Trigger search after clearing
|
|
3863
|
+
addRefinement(facet.field, '__noop__', false);
|
|
3864
|
+
removeRefinement(facet.field, '__noop__', true);
|
|
3865
|
+
};
|
|
3866
|
+
return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
|
|
3867
|
+
marginBottom: theme.spacing.large,
|
|
3868
|
+
padding: theme.spacing.medium,
|
|
3869
|
+
backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
|
|
3870
|
+
border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
|
|
3871
|
+
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
|
|
3872
|
+
} },
|
|
3873
|
+
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
3874
|
+
fontSize: theme.typography.fontSize.large,
|
|
3875
|
+
fontWeight: 'bold',
|
|
3876
|
+
margin: 0,
|
|
3877
|
+
marginBottom: theme.spacing.medium,
|
|
3878
|
+
color: theme.colors.text,
|
|
3879
|
+
} }, facet.label || facet.field),
|
|
3880
|
+
React.createElement("div", { style: {
|
|
3881
|
+
display: 'flex',
|
|
3882
|
+
flexWrap: 'wrap',
|
|
3883
|
+
gap: sizeScale.gap,
|
|
3884
|
+
} }, rangeConfig.ranges.map((range) => {
|
|
3885
|
+
const count = countMap.get(range.label) ?? 0;
|
|
3886
|
+
const active = isRangeActive(range);
|
|
3887
|
+
return (React.createElement("button", { key: range.label, type: "button", className: clsx(facetsTheme.rangeButton, active && facetsTheme.rangeButtonActive), disabled: count === 0 && !active, onClick: () => handleRangeClick(range), style: {
|
|
3888
|
+
display: 'inline-flex',
|
|
3889
|
+
alignItems: 'center',
|
|
3890
|
+
gap: '0.35em',
|
|
3891
|
+
padding: `${sizeScale.padding} 0.75em`,
|
|
3892
|
+
fontSize: sizeScale.font,
|
|
3893
|
+
border: `1px solid ${active ? 'var(--seekora-primary, ' + theme.colors.primary + ')' : 'var(--seekora-facet-border, ' + theme.colors.border + ')'}`,
|
|
3894
|
+
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.full,
|
|
3895
|
+
backgroundColor: active ? 'var(--seekora-primary, ' + theme.colors.primary + ')' : 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
|
|
3896
|
+
color: active ? 'var(--seekora-primary-text, #fff)' : theme.colors.text,
|
|
3897
|
+
cursor: count === 0 && !active ? 'not-allowed' : 'pointer',
|
|
3898
|
+
opacity: count === 0 && !active ? 0.5 : 1,
|
|
3899
|
+
transition: 'all 0.2s ease',
|
|
3900
|
+
} },
|
|
3901
|
+
range.label,
|
|
3902
|
+
showCounts && (React.createElement("span", { className: clsx(facetsTheme.rangeButtonCount), style: {
|
|
3903
|
+
fontSize: theme.typography.fontSize.small,
|
|
3904
|
+
opacity: 0.8,
|
|
3905
|
+
} },
|
|
3906
|
+
"(",
|
|
3907
|
+
count,
|
|
3908
|
+
")"))));
|
|
3909
|
+
})),
|
|
3910
|
+
hasActiveRange && (React.createElement("button", { type: "button", className: clsx(facetsTheme.rangeClear), onClick: handleClear, style: {
|
|
3911
|
+
marginTop: sizeScale.gap,
|
|
3912
|
+
padding: sizeScale.padding,
|
|
3913
|
+
border: 'none',
|
|
3914
|
+
backgroundColor: 'transparent',
|
|
3915
|
+
color: theme.colors.primary,
|
|
3916
|
+
cursor: 'pointer',
|
|
3917
|
+
fontSize: theme.typography.fontSize.small,
|
|
3918
|
+
textDecoration: 'underline',
|
|
3919
|
+
} }, "Clear"))));
|
|
3920
|
+
};
|
|
3921
|
+
// -------------------------------------------------------------------
|
|
3922
|
+
// Range slider facet renderer
|
|
3923
|
+
// -------------------------------------------------------------------
|
|
3924
|
+
const renderRangeSliderFacet = (facet, _index) => {
|
|
3925
|
+
if (!facet.stats)
|
|
3926
|
+
return null;
|
|
3927
|
+
const { min: statsMin, max: statsMax } = facet.stats;
|
|
3928
|
+
// Auto-detect formatting for common field names
|
|
3929
|
+
const fieldLower = facet.field.toLowerCase();
|
|
3930
|
+
const isPriceField = fieldLower.includes('price') || fieldLower.includes('cost') || fieldLower.includes('amount');
|
|
3931
|
+
const formatValue = isPriceField
|
|
3932
|
+
? (v) => `$${v.toFixed(2)}`
|
|
3933
|
+
: (v) => v.toString();
|
|
3934
|
+
// Determine step: use 0.01 for price, 1 for integer ranges, 0.1 otherwise
|
|
3935
|
+
const range = statsMax - statsMin;
|
|
3936
|
+
const step = isPriceField ? 0.01 : range > 10 ? 1 : 0.1;
|
|
3937
|
+
// Check if there's an active range refinement
|
|
3938
|
+
const hasActiveRange = refinements.some((r) => r.field === facet.field && (r.value.startsWith('>=') || r.value.startsWith('<=')));
|
|
3939
|
+
const handleClear = () => {
|
|
3940
|
+
refinements
|
|
3941
|
+
.filter((r) => r.field === facet.field && (r.value.startsWith('>=') || r.value.startsWith('<=')))
|
|
3942
|
+
.forEach((r) => removeRefinement(facet.field, r.value, false));
|
|
3943
|
+
// Trigger search after clearing
|
|
3944
|
+
addRefinement(facet.field, '__noop__', false);
|
|
3945
|
+
removeRefinement(facet.field, '__noop__', true);
|
|
3946
|
+
};
|
|
3947
|
+
return (React.createElement("div", { key: facet.field, className: facetsTheme.facet, style: {
|
|
3948
|
+
marginBottom: theme.spacing.large,
|
|
3949
|
+
padding: theme.spacing.medium,
|
|
3950
|
+
backgroundColor: 'var(--seekora-facet-bg, ' + theme.colors.background + ')',
|
|
3951
|
+
border: `1px solid var(--seekora-facet-border, ${theme.colors.border})`,
|
|
3952
|
+
borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
|
|
3953
|
+
} },
|
|
3954
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: theme.spacing.small } },
|
|
3955
|
+
React.createElement("h3", { className: facetsTheme.facetTitle, style: {
|
|
3956
|
+
fontSize: theme.typography.fontSize.large,
|
|
3957
|
+
fontWeight: 'bold',
|
|
3958
|
+
margin: 0,
|
|
3959
|
+
color: theme.colors.text,
|
|
3960
|
+
} }, facet.label || facet.field),
|
|
3961
|
+
hasActiveRange && (React.createElement("button", { type: "button", className: clsx(facetsTheme.rangeClear), onClick: handleClear, style: {
|
|
3962
|
+
padding: '0.15em 0.5em',
|
|
3963
|
+
border: 'none',
|
|
3964
|
+
backgroundColor: 'transparent',
|
|
3965
|
+
color: theme.colors.primary,
|
|
3966
|
+
cursor: 'pointer',
|
|
3967
|
+
fontSize: theme.typography.fontSize.small,
|
|
3968
|
+
textDecoration: 'underline',
|
|
3969
|
+
} }, "Clear"))),
|
|
3970
|
+
React.createElement(RangeSlider, { field: facet.field, min: statsMin, max: statsMax, step: step, formatValue: formatValue, syncWithState: true })));
|
|
3971
|
+
};
|
|
3972
|
+
// -------------------------------------------------------------------
|
|
3973
|
+
// Default facet renderer dispatcher
|
|
3974
|
+
// -------------------------------------------------------------------
|
|
3975
|
+
const defaultRenderFacet = (facet, index) => {
|
|
3976
|
+
const renderType = determineFacetRenderType(facet.field, facet.stats);
|
|
3977
|
+
if (renderType === 'range-buttons') {
|
|
3978
|
+
return renderRangeButtonFacet(facet);
|
|
3979
|
+
}
|
|
3980
|
+
if (renderType === 'range-slider') {
|
|
3981
|
+
return renderRangeSliderFacet(facet);
|
|
3982
|
+
}
|
|
3983
|
+
switch (variant) {
|
|
3984
|
+
case 'color-swatch':
|
|
3985
|
+
return renderColorSwatchFacet(facet);
|
|
3986
|
+
case 'collapsible':
|
|
3987
|
+
return renderCollapsibleFacet(facet);
|
|
3988
|
+
case 'checkbox':
|
|
3989
|
+
default:
|
|
3990
|
+
return renderCheckboxFacet(facet);
|
|
3991
|
+
}
|
|
3992
|
+
};
|
|
3993
|
+
// -------------------------------------------------------------------
|
|
3994
|
+
// Empty state
|
|
3536
3995
|
// -------------------------------------------------------------------
|
|
3537
3996
|
if (facets.length === 0) {
|
|
3538
3997
|
log.verbose('Facets: No facets to display', {
|
|
@@ -3554,12 +4013,381 @@ const Facets = ({ results: resultsProp, facets: facetsProp, onFacetChange, rende
|
|
|
3554
4013
|
})));
|
|
3555
4014
|
};
|
|
3556
4015
|
|
|
4016
|
+
/**
|
|
4017
|
+
* FacetDropdown Component
|
|
4018
|
+
*
|
|
4019
|
+
* A dropdown component that displays facet values from a specific field
|
|
4020
|
+
* and allows users to filter search results by selecting values.
|
|
4021
|
+
*
|
|
4022
|
+
* Can be used standalone (fetches its own data) or integrated with SearchProvider.
|
|
4023
|
+
*
|
|
4024
|
+
* @cssVariables
|
|
4025
|
+
* Customize the dropdown appearance using CSS variables:
|
|
4026
|
+
*
|
|
4027
|
+
* Button:
|
|
4028
|
+
* - `--facet-dropdown-button-bg`: Button background color
|
|
4029
|
+
* - `--facet-dropdown-text`: Button text color
|
|
4030
|
+
* - `--facet-dropdown-border`: Button and panel border color
|
|
4031
|
+
* - `--facet-dropdown-font-size`: Button font size (default: 0.875rem)
|
|
4032
|
+
* - `--facet-dropdown-font-weight`: Button font weight (default: 500)
|
|
4033
|
+
*
|
|
4034
|
+
* Dropdown Panel:
|
|
4035
|
+
* - `--facet-dropdown-bg`: Panel background color
|
|
4036
|
+
* - `--facet-dropdown-shadow`: Panel box shadow
|
|
4037
|
+
*
|
|
4038
|
+
* Options:
|
|
4039
|
+
* - `--facet-dropdown-option-text`: Option text color
|
|
4040
|
+
* - `--facet-dropdown-option-font-size`: Option font size (default: 0.875rem)
|
|
4041
|
+
* - `--facet-dropdown-option-font-weight-active`: Active option font weight (default: 500)
|
|
4042
|
+
* - `--facet-dropdown-option-active-bg`: Active option background color
|
|
4043
|
+
*
|
|
4044
|
+
* Count Badge:
|
|
4045
|
+
* - `--facet-dropdown-count-text`: Count text color
|
|
4046
|
+
* - `--facet-dropdown-count-font-size`: Count font size (default: 0.75rem)
|
|
4047
|
+
*
|
|
4048
|
+
* Scrollbar:
|
|
4049
|
+
* - `--facet-dropdown-scrollbar-thumb`: Scrollbar thumb color
|
|
4050
|
+
* - `--facet-dropdown-scrollbar-thumb-hover`: Scrollbar thumb hover color
|
|
4051
|
+
*
|
|
4052
|
+
* @example
|
|
4053
|
+
* ```tsx
|
|
4054
|
+
* <FacetDropdown
|
|
4055
|
+
* field="category"
|
|
4056
|
+
* placeholder="All Categories"
|
|
4057
|
+
* applyFilter={true}
|
|
4058
|
+
* showCounts={true}
|
|
4059
|
+
* />
|
|
4060
|
+
* ```
|
|
4061
|
+
*/
|
|
4062
|
+
// Z-index scale for consistent layering
|
|
4063
|
+
// SearchOverlay uses z-100, so dropdown must be higher
|
|
4064
|
+
const Z_INDEX$1 = {
|
|
4065
|
+
dropdown: 150};
|
|
4066
|
+
// ---------------------------------------------------------------------------
|
|
4067
|
+
// Component
|
|
4068
|
+
// ---------------------------------------------------------------------------
|
|
4069
|
+
const FacetDropdown = ({ field, placeholder = 'All Categories', className, theme: customTheme = {}, onChange, value: controlledValue, maxOptions = 10, showCounts = true, options: providedOptions, client: providedClient, applyFilter = true, navigateOnSelect = false, searchPageUrl = '/search', }) => {
|
|
4070
|
+
const { client: contextClient, theme } = useSearchContext();
|
|
4071
|
+
const { addRefinement, removeRefinement, refinements, search } = useSearchState();
|
|
4072
|
+
const client = providedClient || contextClient;
|
|
4073
|
+
const [open, setOpen] = React.useState(false);
|
|
4074
|
+
const [facetOptions, setFacetOptions] = React.useState(providedOptions || []);
|
|
4075
|
+
const [internalValue, setInternalValue] = React.useState(controlledValue || '');
|
|
4076
|
+
const [dropdownPosition, setDropdownPosition] = React.useState(null);
|
|
4077
|
+
const dropdownRef = React.useRef(null);
|
|
4078
|
+
const buttonRef = React.useRef(null);
|
|
4079
|
+
// Determine the current value (controlled or uncontrolled)
|
|
4080
|
+
const currentValue = controlledValue !== undefined ? controlledValue : internalValue;
|
|
4081
|
+
// ---------------------------------------------------------------------------
|
|
4082
|
+
// Fetch facet values
|
|
4083
|
+
// ---------------------------------------------------------------------------
|
|
4084
|
+
const fetchFacetValues = React.useCallback(async () => {
|
|
4085
|
+
if (providedOptions || !client)
|
|
4086
|
+
return;
|
|
4087
|
+
try {
|
|
4088
|
+
log.verbose('FacetDropdown: Fetching facet values', { field });
|
|
4089
|
+
// Perform a search with facet_by parameter to get facet counts
|
|
4090
|
+
const response = await client.search('*', {
|
|
4091
|
+
facet_by: field,
|
|
4092
|
+
max_facet_values: 100,
|
|
4093
|
+
per_page: 0, // We only need facets, not results
|
|
4094
|
+
});
|
|
4095
|
+
log.verbose('FacetDropdown: Search response', { response });
|
|
4096
|
+
// Extract facet counts from the response
|
|
4097
|
+
const facetsData = response?.data?.facets || response?.facets;
|
|
4098
|
+
const facets = Array.isArray(facetsData) ? facetsData : [];
|
|
4099
|
+
const targetFacet = facets.find((f) => f.field_name === field || f.field === field);
|
|
4100
|
+
if (targetFacet && targetFacet.counts) {
|
|
4101
|
+
const options = targetFacet.counts.map((count) => ({
|
|
4102
|
+
value: count.value,
|
|
4103
|
+
count: count.count,
|
|
4104
|
+
label: count.value,
|
|
4105
|
+
}));
|
|
4106
|
+
setFacetOptions(options);
|
|
4107
|
+
log.verbose('FacetDropdown: Facet options loaded', { field, count: options.length });
|
|
4108
|
+
}
|
|
4109
|
+
else {
|
|
4110
|
+
log.verbose('FacetDropdown: No facet data found', { field, facets });
|
|
4111
|
+
setFacetOptions([]);
|
|
4112
|
+
}
|
|
4113
|
+
}
|
|
4114
|
+
catch (error) {
|
|
4115
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
4116
|
+
log.error('FacetDropdown: Error fetching facet values', {
|
|
4117
|
+
field,
|
|
4118
|
+
error: err.message,
|
|
4119
|
+
});
|
|
4120
|
+
setFacetOptions([]);
|
|
4121
|
+
}
|
|
4122
|
+
}, [field, client, providedOptions]);
|
|
4123
|
+
React.useEffect(() => {
|
|
4124
|
+
if (!providedOptions && client) {
|
|
4125
|
+
fetchFacetValues();
|
|
4126
|
+
}
|
|
4127
|
+
}, [fetchFacetValues, providedOptions, client]);
|
|
4128
|
+
// ---------------------------------------------------------------------------
|
|
4129
|
+
// Calculate dropdown position when opened
|
|
4130
|
+
// ---------------------------------------------------------------------------
|
|
4131
|
+
React.useEffect(() => {
|
|
4132
|
+
if (!open || !buttonRef.current)
|
|
4133
|
+
return;
|
|
4134
|
+
const updatePosition = () => {
|
|
4135
|
+
if (!buttonRef.current)
|
|
4136
|
+
return;
|
|
4137
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
4138
|
+
setDropdownPosition({
|
|
4139
|
+
top: rect.bottom + window.scrollY + 4,
|
|
4140
|
+
left: rect.left + window.scrollX,
|
|
4141
|
+
width: rect.width,
|
|
4142
|
+
});
|
|
4143
|
+
};
|
|
4144
|
+
updatePosition();
|
|
4145
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
4146
|
+
window.addEventListener('resize', updatePosition);
|
|
4147
|
+
return () => {
|
|
4148
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
4149
|
+
window.removeEventListener('resize', updatePosition);
|
|
4150
|
+
};
|
|
4151
|
+
}, [open]);
|
|
4152
|
+
// ---------------------------------------------------------------------------
|
|
4153
|
+
// Click outside handler
|
|
4154
|
+
// ---------------------------------------------------------------------------
|
|
4155
|
+
React.useEffect(() => {
|
|
4156
|
+
if (!open)
|
|
4157
|
+
return;
|
|
4158
|
+
const handleClickOutside = (e) => {
|
|
4159
|
+
if (dropdownRef.current &&
|
|
4160
|
+
!dropdownRef.current.contains(e.target) &&
|
|
4161
|
+
buttonRef.current &&
|
|
4162
|
+
!buttonRef.current.contains(e.target)) {
|
|
4163
|
+
setOpen(false);
|
|
4164
|
+
}
|
|
4165
|
+
};
|
|
4166
|
+
const handleEscape = (e) => {
|
|
4167
|
+
if (e.key === 'Escape') {
|
|
4168
|
+
setOpen(false);
|
|
4169
|
+
}
|
|
4170
|
+
};
|
|
4171
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
4172
|
+
document.addEventListener('keydown', handleEscape);
|
|
4173
|
+
return () => {
|
|
4174
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
4175
|
+
document.removeEventListener('keydown', handleEscape);
|
|
4176
|
+
};
|
|
4177
|
+
}, [open]);
|
|
4178
|
+
// ---------------------------------------------------------------------------
|
|
4179
|
+
// Selection handler
|
|
4180
|
+
// ---------------------------------------------------------------------------
|
|
4181
|
+
const handleSelect = React.useCallback((value) => {
|
|
4182
|
+
log.verbose('FacetDropdown: Value selected', { field, value });
|
|
4183
|
+
// Update internal state
|
|
4184
|
+
setInternalValue(value);
|
|
4185
|
+
setOpen(false);
|
|
4186
|
+
// Call onChange callback
|
|
4187
|
+
if (onChange) {
|
|
4188
|
+
onChange(value);
|
|
4189
|
+
}
|
|
4190
|
+
// Apply filter if enabled and we have search state
|
|
4191
|
+
if (applyFilter && addRefinement && removeRefinement) {
|
|
4192
|
+
// Remove any existing refinement for this field
|
|
4193
|
+
const existingRefinement = refinements.find(r => r.field === field);
|
|
4194
|
+
if (existingRefinement) {
|
|
4195
|
+
removeRefinement(field, existingRefinement.value, false);
|
|
4196
|
+
}
|
|
4197
|
+
// Add new refinement if value is not empty
|
|
4198
|
+
if (value) {
|
|
4199
|
+
addRefinement(field, value, true); // true = trigger search
|
|
4200
|
+
}
|
|
4201
|
+
else if (search) {
|
|
4202
|
+
// If clearing the filter, trigger search manually
|
|
4203
|
+
search();
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
// Navigate to search page if enabled
|
|
4207
|
+
if (navigateOnSelect && value && typeof window !== 'undefined') {
|
|
4208
|
+
const url = new URL(window.location.origin + searchPageUrl);
|
|
4209
|
+
url.searchParams.set(field, value);
|
|
4210
|
+
window.location.href = url.toString();
|
|
4211
|
+
}
|
|
4212
|
+
}, [field, onChange, applyFilter, addRefinement, removeRefinement, refinements, search, navigateOnSelect, searchPageUrl]);
|
|
4213
|
+
// ---------------------------------------------------------------------------
|
|
4214
|
+
// Render
|
|
4215
|
+
// ---------------------------------------------------------------------------
|
|
4216
|
+
const displayLabel = currentValue || placeholder;
|
|
4217
|
+
const hasOptions = facetOptions.length > 0;
|
|
4218
|
+
const buttonClass = [
|
|
4219
|
+
'facet-dropdown-button',
|
|
4220
|
+
customTheme.button,
|
|
4221
|
+
className,
|
|
4222
|
+
open && customTheme.buttonOpen,
|
|
4223
|
+
]
|
|
4224
|
+
.filter(Boolean)
|
|
4225
|
+
.join(' ');
|
|
4226
|
+
// Render dropdown panel via portal
|
|
4227
|
+
const renderDropdown = () => {
|
|
4228
|
+
if (!open || !hasOptions || !dropdownPosition || typeof document === 'undefined') {
|
|
4229
|
+
return null;
|
|
4230
|
+
}
|
|
4231
|
+
const dropdown = (React.createElement("div", { ref: dropdownRef, className: customTheme.panel || 'facet-dropdown-panel', role: "listbox", "aria-label": `${field} options`, style: {
|
|
4232
|
+
position: 'absolute',
|
|
4233
|
+
top: `${dropdownPosition.top}px`,
|
|
4234
|
+
left: `${dropdownPosition.left}px`,
|
|
4235
|
+
minWidth: `${dropdownPosition.width}px`,
|
|
4236
|
+
width: 'max-content',
|
|
4237
|
+
maxWidth: 'min(24rem, 90vw)',
|
|
4238
|
+
maxHeight: `calc(100vh - 100px)`,
|
|
4239
|
+
overflowY: 'auto',
|
|
4240
|
+
overflowX: 'hidden',
|
|
4241
|
+
backgroundColor: 'var(--facet-dropdown-bg, var(--background))',
|
|
4242
|
+
border: '1px solid var(--facet-dropdown-border, var(--border-color))',
|
|
4243
|
+
borderRadius: theme?.borderRadius && typeof theme.borderRadius !== 'string'
|
|
4244
|
+
? theme.borderRadius.medium
|
|
4245
|
+
: '0.5rem',
|
|
4246
|
+
boxShadow: 'var(--facet-dropdown-shadow, var(--shadow-lg))',
|
|
4247
|
+
zIndex: Z_INDEX$1.dropdown,
|
|
4248
|
+
padding: '0.25rem',
|
|
4249
|
+
} },
|
|
4250
|
+
React.createElement("button", { type: "button", role: "option", "aria-selected": !currentValue, onClick: (e) => {
|
|
4251
|
+
e.preventDefault();
|
|
4252
|
+
e.stopPropagation();
|
|
4253
|
+
handleSelect('');
|
|
4254
|
+
}, className: [
|
|
4255
|
+
customTheme.option,
|
|
4256
|
+
!currentValue && customTheme.optionActive,
|
|
4257
|
+
]
|
|
4258
|
+
.filter(Boolean)
|
|
4259
|
+
.join(' '), style: {
|
|
4260
|
+
width: '100%',
|
|
4261
|
+
textAlign: 'left',
|
|
4262
|
+
padding: '0.5rem 0.75rem',
|
|
4263
|
+
fontSize: 'var(--facet-dropdown-option-font-size, 0.875rem)',
|
|
4264
|
+
fontWeight: !currentValue ? 'var(--facet-dropdown-option-font-weight-active, 500)' : 'normal',
|
|
4265
|
+
color: 'var(--facet-dropdown-option-text, var(--text-color, currentColor))',
|
|
4266
|
+
backgroundColor: !currentValue ? 'var(--facet-dropdown-option-active-bg, var(--hover-color))' : 'transparent',
|
|
4267
|
+
border: 'none',
|
|
4268
|
+
borderRadius: theme?.borderRadius && typeof theme.borderRadius !== 'string'
|
|
4269
|
+
? theme.borderRadius.small
|
|
4270
|
+
: '0.25rem',
|
|
4271
|
+
cursor: 'pointer',
|
|
4272
|
+
transition: 'background-color 0.15s ease',
|
|
4273
|
+
display: 'flex',
|
|
4274
|
+
alignItems: 'center',
|
|
4275
|
+
justifyContent: 'space-between',
|
|
4276
|
+
} },
|
|
4277
|
+
React.createElement("span", null, placeholder)),
|
|
4278
|
+
facetOptions.map((option) => {
|
|
4279
|
+
const isActive = currentValue === option.value;
|
|
4280
|
+
return (React.createElement("button", { key: option.value, type: "button", role: "option", "aria-selected": isActive, onClick: (e) => {
|
|
4281
|
+
e.preventDefault();
|
|
4282
|
+
e.stopPropagation();
|
|
4283
|
+
handleSelect(option.value);
|
|
4284
|
+
}, className: [
|
|
4285
|
+
customTheme.option,
|
|
4286
|
+
isActive && customTheme.optionActive,
|
|
4287
|
+
]
|
|
4288
|
+
.filter(Boolean)
|
|
4289
|
+
.join(' '), style: {
|
|
4290
|
+
width: '100%',
|
|
4291
|
+
textAlign: 'left',
|
|
4292
|
+
padding: '0.5rem 0.75rem',
|
|
4293
|
+
fontSize: 'var(--facet-dropdown-option-font-size, 0.875rem)',
|
|
4294
|
+
fontWeight: isActive ? 'var(--facet-dropdown-option-font-weight-active, 500)' : 'normal',
|
|
4295
|
+
color: 'var(--facet-dropdown-option-text, var(--text-color, currentColor))',
|
|
4296
|
+
backgroundColor: isActive ? 'var(--facet-dropdown-option-active-bg, var(--hover-color))' : 'transparent',
|
|
4297
|
+
border: 'none',
|
|
4298
|
+
borderRadius: theme?.borderRadius && typeof theme.borderRadius !== 'string'
|
|
4299
|
+
? theme.borderRadius.small
|
|
4300
|
+
: '0.25rem',
|
|
4301
|
+
cursor: 'pointer',
|
|
4302
|
+
transition: 'background-color 0.15s ease',
|
|
4303
|
+
display: 'flex',
|
|
4304
|
+
alignItems: 'center',
|
|
4305
|
+
justifyContent: 'space-between',
|
|
4306
|
+
} },
|
|
4307
|
+
React.createElement("span", { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' } }, option.label || option.value),
|
|
4308
|
+
showCounts && (React.createElement("span", { style: {
|
|
4309
|
+
fontSize: 'var(--facet-dropdown-count-font-size, 0.75rem)',
|
|
4310
|
+
color: 'var(--facet-dropdown-count-text, var(--text-secondary, currentColor))',
|
|
4311
|
+
opacity: 0.7,
|
|
4312
|
+
marginLeft: '0.5rem',
|
|
4313
|
+
flexShrink: 0,
|
|
4314
|
+
} },
|
|
4315
|
+
"(",
|
|
4316
|
+
option.count,
|
|
4317
|
+
")"))));
|
|
4318
|
+
})));
|
|
4319
|
+
return reactDom.createPortal(dropdown, document.body);
|
|
4320
|
+
};
|
|
4321
|
+
return (React.createElement("div", { className: "facet-dropdown-container", style: { position: 'relative' } },
|
|
4322
|
+
React.createElement("style", { dangerouslySetInnerHTML: {
|
|
4323
|
+
__html: `
|
|
4324
|
+
.facet-dropdown-panel {
|
|
4325
|
+
--scrollbar-track: transparent;
|
|
4326
|
+
--scrollbar-thumb: var(--facet-dropdown-scrollbar-thumb, var(--border-color));
|
|
4327
|
+
--scrollbar-thumb-hover: var(--facet-dropdown-scrollbar-thumb-hover, var(--text-secondary));
|
|
4328
|
+
}
|
|
4329
|
+
.facet-dropdown-panel::-webkit-scrollbar {
|
|
4330
|
+
width: 6px;
|
|
4331
|
+
}
|
|
4332
|
+
.facet-dropdown-panel::-webkit-scrollbar-track {
|
|
4333
|
+
background: var(--scrollbar-track);
|
|
4334
|
+
}
|
|
4335
|
+
.facet-dropdown-panel::-webkit-scrollbar-thumb {
|
|
4336
|
+
background: var(--scrollbar-thumb);
|
|
4337
|
+
border-radius: 3px;
|
|
4338
|
+
}
|
|
4339
|
+
.facet-dropdown-panel::-webkit-scrollbar-thumb:hover {
|
|
4340
|
+
background: var(--scrollbar-thumb-hover);
|
|
4341
|
+
}
|
|
4342
|
+
.facet-dropdown-panel {
|
|
4343
|
+
scrollbar-width: thin;
|
|
4344
|
+
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
|
|
4345
|
+
}
|
|
4346
|
+
`
|
|
4347
|
+
} }),
|
|
4348
|
+
React.createElement("button", { ref: buttonRef, type: "button", onClick: (e) => {
|
|
4349
|
+
e.preventDefault();
|
|
4350
|
+
e.stopPropagation();
|
|
4351
|
+
setOpen(prev => !prev);
|
|
4352
|
+
}, className: buttonClass, "aria-label": `Filter by ${field}`, "aria-expanded": open, "aria-haspopup": "listbox", style: {
|
|
4353
|
+
display: 'flex',
|
|
4354
|
+
alignItems: 'center',
|
|
4355
|
+
gap: '0.375rem',
|
|
4356
|
+
padding: '0.625rem 0.75rem',
|
|
4357
|
+
fontSize: 'var(--facet-dropdown-font-size, 0.875rem)',
|
|
4358
|
+
fontWeight: 'var(--facet-dropdown-font-weight, 500)',
|
|
4359
|
+
color: 'var(--facet-dropdown-text, var(--text-color, currentColor))',
|
|
4360
|
+
backgroundColor: 'var(--facet-dropdown-button-bg, var(--background, transparent))',
|
|
4361
|
+
border: '1px solid var(--facet-dropdown-border, var(--border-color))',
|
|
4362
|
+
borderRadius: theme?.borderRadius && typeof theme.borderRadius !== 'string'
|
|
4363
|
+
? theme.borderRadius.medium
|
|
4364
|
+
: '0.5rem',
|
|
4365
|
+
cursor: 'pointer',
|
|
4366
|
+
transition: 'all 0.2s ease',
|
|
4367
|
+
outline: 'none',
|
|
4368
|
+
whiteSpace: 'nowrap',
|
|
4369
|
+
minWidth: '8rem',
|
|
4370
|
+
...(!hasOptions && { opacity: 0.6, cursor: 'not-allowed' }),
|
|
4371
|
+
}, disabled: !hasOptions },
|
|
4372
|
+
React.createElement("span", { style: { flex: 1, textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis' } }, displayLabel),
|
|
4373
|
+
React.createElement("svg", { className: customTheme.caretIcon, width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", style: {
|
|
4374
|
+
transform: open ? 'rotate(180deg)' : 'rotate(0deg)',
|
|
4375
|
+
transition: 'transform 0.2s ease',
|
|
4376
|
+
flexShrink: 0,
|
|
4377
|
+
}, "aria-hidden": "true" },
|
|
4378
|
+
React.createElement("path", { d: "M4 6L8 10L12 6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }))),
|
|
4379
|
+
renderDropdown()));
|
|
4380
|
+
};
|
|
4381
|
+
|
|
3557
4382
|
/**
|
|
3558
4383
|
* CurrentRefinements Component
|
|
3559
4384
|
*
|
|
3560
4385
|
* Displays currently active filters/refinements with ability to clear them.
|
|
3561
4386
|
* Supports StateManager auto-sync, display variants, layout modes, and animations.
|
|
3562
4387
|
*/
|
|
4388
|
+
const TRANSITIONS$7 = {
|
|
4389
|
+
fast: '150ms ease-in-out',
|
|
4390
|
+
normal: '200ms ease-in-out'};
|
|
3563
4391
|
/** Get variant-specific styles */
|
|
3564
4392
|
const getVariantStyles = (variant, themeColors, themeSpacing, themeBorderRadius, fieldColor) => {
|
|
3565
4393
|
const baseBg = fieldColor || `var(--seekora-refinement-bg, ${themeColors.hover})`;
|
|
@@ -3643,10 +4471,59 @@ const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, o
|
|
|
3643
4471
|
const { theme } = useSearchContext();
|
|
3644
4472
|
const { refinements: stateRefinements, removeRefinement, clearRefinements } = useSearchState();
|
|
3645
4473
|
const refinementsTheme = customTheme || {};
|
|
4474
|
+
// Format a numeric value for display (auto-detect price fields)
|
|
4475
|
+
const formatRangeValue = (field, val) => {
|
|
4476
|
+
const f = field.toLowerCase();
|
|
4477
|
+
if (f.includes('price') || f.includes('cost') || f.includes('amount')) {
|
|
4478
|
+
return `$${val.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
4479
|
+
}
|
|
4480
|
+
return val.toLocaleString();
|
|
4481
|
+
};
|
|
4482
|
+
// Create a stable serialized key from stateRefinements to detect actual changes
|
|
4483
|
+
// (needed because state manager mutates the array in place)
|
|
4484
|
+
const stateRefinementsKey = React.useMemo(() => stateRefinements.map(r => `${r.field}:${r.value}`).sort().join('|'), [stateRefinements.map(r => `${r.field}:${r.value}`).sort().join('|')]);
|
|
3646
4485
|
// Use props if provided, otherwise auto-read from StateManager
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
4486
|
+
// Combines >= / <= range refinements into single formatted pills
|
|
4487
|
+
const refinements = React.useMemo(() => {
|
|
4488
|
+
if (refinementsProp !== undefined) {
|
|
4489
|
+
return refinementsProp;
|
|
4490
|
+
}
|
|
4491
|
+
const rangeMap = new Map();
|
|
4492
|
+
const nonRange = [];
|
|
4493
|
+
stateRefinements.forEach(r => {
|
|
4494
|
+
const minMatch = r.value.match(/^>=(\d+(?:\.\d+)?)$/);
|
|
4495
|
+
const maxMatch = r.value.match(/^<=(\d+(?:\.\d+)?)$/);
|
|
4496
|
+
if (minMatch || maxMatch) {
|
|
4497
|
+
if (!rangeMap.has(r.field))
|
|
4498
|
+
rangeMap.set(r.field, {});
|
|
4499
|
+
const entry = rangeMap.get(r.field);
|
|
4500
|
+
if (minMatch)
|
|
4501
|
+
entry.minVal = parseFloat(minMatch[1]);
|
|
4502
|
+
if (maxMatch)
|
|
4503
|
+
entry.maxVal = parseFloat(maxMatch[1]);
|
|
4504
|
+
}
|
|
4505
|
+
else {
|
|
4506
|
+
nonRange.push({ field: r.field, value: r.value });
|
|
4507
|
+
}
|
|
4508
|
+
});
|
|
4509
|
+
rangeMap.forEach((range, field) => {
|
|
4510
|
+
let displayValue;
|
|
4511
|
+
if (range.minVal !== undefined && range.maxVal !== undefined) {
|
|
4512
|
+
displayValue = `${formatRangeValue(field, range.minVal)} – ${formatRangeValue(field, range.maxVal)}`;
|
|
4513
|
+
}
|
|
4514
|
+
else if (range.minVal !== undefined) {
|
|
4515
|
+
displayValue = `≥ ${formatRangeValue(field, range.minVal)}`;
|
|
4516
|
+
}
|
|
4517
|
+
else if (range.maxVal !== undefined) {
|
|
4518
|
+
displayValue = `≤ ${formatRangeValue(field, range.maxVal)}`;
|
|
4519
|
+
}
|
|
4520
|
+
else {
|
|
4521
|
+
return;
|
|
4522
|
+
}
|
|
4523
|
+
nonRange.push({ field, value: '__range__', displayValue });
|
|
4524
|
+
});
|
|
4525
|
+
return nonRange;
|
|
4526
|
+
}, [refinementsProp, stateRefinementsKey]);
|
|
3650
4527
|
// Track items for entry/exit animations
|
|
3651
4528
|
const [visibleItems, setVisibleItems] = React.useState(new Set());
|
|
3652
4529
|
const [exitingItems, setExitingItems] = React.useState(new Set());
|
|
@@ -3670,9 +4547,15 @@ const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, o
|
|
|
3670
4547
|
prevRefinementsRef.current = [...refinements];
|
|
3671
4548
|
}, [refinements]);
|
|
3672
4549
|
const handleClear = (field, value) => {
|
|
3673
|
-
// If synced with StateManager and no prop provided, auto-clear via StateManager
|
|
3674
4550
|
if (refinementsProp === undefined) {
|
|
3675
|
-
|
|
4551
|
+
if (value === '__range__') {
|
|
4552
|
+
// Clear all range refinements for this field
|
|
4553
|
+
const rangeRefs = stateRefinements.filter(r => r.field === field && (/^>=/.test(r.value) || /^<=/.test(r.value)));
|
|
4554
|
+
rangeRefs.forEach((r, i) => removeRefinement(field, r.value, i === rangeRefs.length - 1));
|
|
4555
|
+
}
|
|
4556
|
+
else {
|
|
4557
|
+
removeRefinement(field, value);
|
|
4558
|
+
}
|
|
3676
4559
|
}
|
|
3677
4560
|
if (onRefinementClear) {
|
|
3678
4561
|
onRefinementClear(field, value);
|
|
@@ -3699,7 +4582,7 @@ const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, o
|
|
|
3699
4582
|
margin: layout === 'vertical'
|
|
3700
4583
|
? `0 0 ${theme.spacing.small} 0`
|
|
3701
4584
|
: `0 ${theme.spacing.small} ${theme.spacing.small} 0`,
|
|
3702
|
-
transition:
|
|
4585
|
+
transition: `all ${TRANSITIONS$7.normal}`,
|
|
3703
4586
|
opacity: exitingItems.has(key) ? 0 : 1,
|
|
3704
4587
|
transform: exitingItems.has(key) ? 'scale(0.8)' : 'scale(1)',
|
|
3705
4588
|
animation: isEntering ? 'seekoraChipIn 200ms ease-out' : undefined,
|
|
@@ -3723,7 +4606,7 @@ const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, o
|
|
|
3723
4606
|
alignItems: 'center',
|
|
3724
4607
|
justifyContent: 'center',
|
|
3725
4608
|
borderRadius: '50%',
|
|
3726
|
-
transition:
|
|
4609
|
+
transition: `opacity ${TRANSITIONS$7.fast}`,
|
|
3727
4610
|
opacity: 0.6,
|
|
3728
4611
|
}, "aria-label": `Clear ${refinement.label || refinement.field}: ${refinement.value}`, onMouseEnter: e => (e.currentTarget.style.opacity = '1'), onMouseLeave: e => (e.currentTarget.style.opacity = '0.6') }, renderCloseIcon ? renderCloseIcon() : defaultCloseIcon())));
|
|
3729
4612
|
};
|
|
@@ -3782,7 +4665,7 @@ const CurrentRefinements = ({ refinements: refinementsProp, onRefinementClear, o
|
|
|
3782
4665
|
cursor: 'pointer',
|
|
3783
4666
|
fontSize: theme.typography.fontSize.small,
|
|
3784
4667
|
textDecoration: 'underline',
|
|
3785
|
-
transition:
|
|
4668
|
+
transition: `background-color ${TRANSITIONS$7.fast}`,
|
|
3786
4669
|
} }, "Clear all filters"))));
|
|
3787
4670
|
};
|
|
3788
4671
|
|
|
@@ -3884,6 +4767,8 @@ const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth = '300px
|
|
|
3884
4767
|
display: 'flex',
|
|
3885
4768
|
flexDirection: 'column',
|
|
3886
4769
|
minHeight: '100vh',
|
|
4770
|
+
width: '100%',
|
|
4771
|
+
maxWidth: '100%',
|
|
3887
4772
|
backgroundColor: theme.colors.background,
|
|
3888
4773
|
...style,
|
|
3889
4774
|
} },
|
|
@@ -3895,20 +4780,27 @@ const SearchLayout = ({ sidebar, children, header, footer, sidebarWidth = '300px
|
|
|
3895
4780
|
React.createElement("div", { style: {
|
|
3896
4781
|
display: 'flex',
|
|
3897
4782
|
flex: 1,
|
|
4783
|
+
width: '100%',
|
|
4784
|
+
maxWidth: '100%',
|
|
3898
4785
|
gap: theme.spacing.large,
|
|
3899
4786
|
padding: theme.spacing.medium,
|
|
3900
4787
|
backgroundColor: theme.colors.background,
|
|
3901
4788
|
color: theme.colors.text,
|
|
4789
|
+
overflow: 'hidden',
|
|
3902
4790
|
} },
|
|
3903
4791
|
sidebar && (!isMobile || showSidebarOnMobile) && (React.createElement("aside", { className: layoutTheme.sidebar, style: {
|
|
3904
4792
|
width: sidebarWidth,
|
|
3905
4793
|
minWidth: sidebarWidth,
|
|
4794
|
+
flexShrink: 0,
|
|
3906
4795
|
} }, sidebar)),
|
|
3907
4796
|
React.createElement("main", { className: layoutTheme.main, style: {
|
|
3908
4797
|
flex: 1,
|
|
3909
|
-
minWidth: 0,
|
|
4798
|
+
minWidth: 0,
|
|
4799
|
+
width: '100%',
|
|
4800
|
+
maxWidth: '100%',
|
|
3910
4801
|
backgroundColor: theme.colors.background,
|
|
3911
4802
|
color: theme.colors.text,
|
|
4803
|
+
overflow: 'auto',
|
|
3912
4804
|
} }, children)),
|
|
3913
4805
|
footer && (React.createElement("footer", { className: layoutTheme.footer, style: {
|
|
3914
4806
|
padding: theme.spacing.medium,
|
|
@@ -3950,11 +4842,11 @@ const RangeInput = ({ field, label, min, max, currentMin: currentMinProp, curren
|
|
|
3950
4842
|
const { refinements, addRefinement, removeRefinement } = useSearchState();
|
|
3951
4843
|
const rangeInputTheme = customTheme || {};
|
|
3952
4844
|
// Parse current range from StateManager
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
4845
|
+
// NOTE: computed every render (no useMemo) because the state manager mutates
|
|
4846
|
+
// the refinements array in place — the reference never changes.
|
|
4847
|
+
const stateRange = !syncWithState
|
|
4848
|
+
? { min: undefined, max: undefined }
|
|
4849
|
+
: parseRangeFromRefinements(refinements, field);
|
|
3958
4850
|
const [internalMin, setInternalMin] = React.useState(currentMinProp ?? stateRange.min);
|
|
3959
4851
|
const [internalMax, setInternalMax] = React.useState(currentMaxProp ?? stateRange.max);
|
|
3960
4852
|
const [appliedMin, setAppliedMin] = React.useState(currentMinProp ?? stateRange.min);
|
|
@@ -4717,311 +5609,78 @@ const HierarchicalMenu = ({ attributes, separator = ' > ', limit = 10, showMore
|
|
|
4717
5609
|
const button = parentItem.querySelector(':scope > button');
|
|
4718
5610
|
if (button)
|
|
4719
5611
|
button.focus();
|
|
4720
|
-
else
|
|
4721
|
-
parentItem.focus();
|
|
4722
|
-
}
|
|
4723
|
-
}
|
|
4724
|
-
}
|
|
4725
|
-
break;
|
|
4726
|
-
}
|
|
4727
|
-
case 'Enter': {
|
|
4728
|
-
if (!currentItem)
|
|
4729
|
-
break;
|
|
4730
|
-
e.preventDefault();
|
|
4731
|
-
const button = currentItem.querySelector('button');
|
|
4732
|
-
if (button)
|
|
4733
|
-
button.click();
|
|
4734
|
-
break;
|
|
4735
|
-
}
|
|
4736
|
-
}
|
|
4737
|
-
}, [getVisibleTreeItems]);
|
|
4738
|
-
// Render a level of the hierarchy
|
|
4739
|
-
const renderLevel = (items, level) => {
|
|
4740
|
-
if (!items || items.length === 0)
|
|
4741
|
-
return null;
|
|
4742
|
-
const isExpanded = expanded[level] || false;
|
|
4743
|
-
const displayLimit = isExpanded ? showMoreLimit : limit;
|
|
4744
|
-
const displayItems = items.slice(0, displayLimit);
|
|
4745
|
-
const hasMore = items.length > displayLimit;
|
|
4746
|
-
return (React.createElement("ul", { role: level === 0 ? 'tree' : 'group', className: hierarchicalTheme.list, style: {
|
|
4747
|
-
listStyle: 'none',
|
|
4748
|
-
margin: 0,
|
|
4749
|
-
padding: level > 0 ? `0 0 0 ${theme.spacing.medium}` : 0,
|
|
4750
|
-
} },
|
|
4751
|
-
displayItems.map((item, index) => (React.createElement("li", { key: item.value, role: "treeitem", ...(item.data && item.data.length > 0
|
|
4752
|
-
? { 'aria-expanded': !!item.isRefined }
|
|
4753
|
-
: {}), className: clsx(hierarchicalTheme.item, item.isRefined && hierarchicalTheme.itemSelected, item.data && item.data.length > 0 && hierarchicalTheme.itemParent), style: {
|
|
4754
|
-
padding: `${theme.spacing.small} 0`,
|
|
4755
|
-
} }, renderItem ? (renderItem(item, level)) : (React.createElement(React.Fragment, null,
|
|
4756
|
-
React.createElement("button", { type: "button", onClick: () => handleItemClick(item, level), className: hierarchicalTheme.link, style: {
|
|
4757
|
-
display: 'flex',
|
|
4758
|
-
alignItems: 'center',
|
|
4759
|
-
gap: theme.spacing.small,
|
|
4760
|
-
width: '100%',
|
|
4761
|
-
padding: 0,
|
|
4762
|
-
background: 'none',
|
|
4763
|
-
border: 'none',
|
|
4764
|
-
cursor: 'pointer',
|
|
4765
|
-
textAlign: 'left',
|
|
4766
|
-
fontFamily: 'inherit',
|
|
4767
|
-
fontSize: theme.typography.fontSize.small,
|
|
4768
|
-
color: item.isRefined ? theme.colors.primary : theme.colors.text,
|
|
4769
|
-
fontWeight: item.isRefined ? 600 : 400,
|
|
4770
|
-
} },
|
|
4771
|
-
React.createElement("span", { className: hierarchicalTheme.label, style: { flex: 1 } }, item.label),
|
|
4772
|
-
item.count !== undefined && (React.createElement("span", { className: hierarchicalTheme.count, style: {
|
|
4773
|
-
color: theme.colors.textSecondary,
|
|
4774
|
-
fontSize: theme.typography.fontSize.small,
|
|
4775
|
-
} }, item.count))),
|
|
4776
|
-
item.isRefined && item.data && item.data.length > 0 && (renderLevel(item.data, level + 1))))))),
|
|
4777
|
-
showMore && hasMore && (React.createElement("li", null,
|
|
4778
|
-
React.createElement("button", { type: "button", onClick: () => toggleShowMore(level), className: hierarchicalTheme.showMore, style: {
|
|
4779
|
-
padding: `${theme.spacing.small} 0`,
|
|
4780
|
-
background: 'none',
|
|
4781
|
-
border: 'none',
|
|
4782
|
-
cursor: 'pointer',
|
|
4783
|
-
fontSize: theme.typography.fontSize.small,
|
|
4784
|
-
color: theme.colors.primary,
|
|
4785
|
-
textDecoration: 'underline',
|
|
4786
|
-
} }, isExpanded ? 'Show less' : `Show ${items.length - displayLimit} more`)))));
|
|
4787
|
-
};
|
|
4788
|
-
if (processedItems.length === 0) {
|
|
4789
|
-
return null;
|
|
4790
|
-
}
|
|
4791
|
-
return (React.createElement("div", { ref: containerRef, className: clsx(hierarchicalTheme.root, className), style: style, tabIndex: 0, onKeyDown: handleKeyDown }, renderLevel(processedItems, 0)));
|
|
4792
|
-
};
|
|
4793
|
-
|
|
4794
|
-
/**
|
|
4795
|
-
* RangeSlider Component
|
|
4796
|
-
*
|
|
4797
|
-
* Visual slider for numeric range filtering
|
|
4798
|
-
* Alternative to RangeInput for a more interactive UX
|
|
4799
|
-
*/
|
|
4800
|
-
const RangeSlider = ({ field, label, min, max, step = 1, currentMin: currentMinProp, currentMax: currentMaxProp, onRangeChange, formatValue = (v) => v.toString(), className, style, theme: customTheme, showValues = true, syncWithState = true, debounceMs = 300, }) => {
|
|
4801
|
-
const { theme } = useSearchContext();
|
|
4802
|
-
const { refinements, addRefinement, removeRefinement } = useSearchState();
|
|
4803
|
-
const rangeSliderTheme = customTheme || {};
|
|
4804
|
-
// Parse current range from StateManager
|
|
4805
|
-
const stateRange = React.useMemo(() => {
|
|
4806
|
-
if (!syncWithState)
|
|
4807
|
-
return { min: undefined, max: undefined };
|
|
4808
|
-
let minVal;
|
|
4809
|
-
let maxVal;
|
|
4810
|
-
refinements.forEach(r => {
|
|
4811
|
-
if (r.field === field) {
|
|
4812
|
-
const minMatch = r.value.match(/^>=(\d+(?:\.\d+)?)$/);
|
|
4813
|
-
if (minMatch)
|
|
4814
|
-
minVal = parseFloat(minMatch[1]);
|
|
4815
|
-
const maxMatch = r.value.match(/^<=(\d+(?:\.\d+)?)$/);
|
|
4816
|
-
if (maxMatch)
|
|
4817
|
-
maxVal = parseFloat(maxMatch[1]);
|
|
4818
|
-
}
|
|
4819
|
-
});
|
|
4820
|
-
return { min: minVal, max: maxVal };
|
|
4821
|
-
}, [syncWithState, refinements, field]);
|
|
4822
|
-
const [internalMin, setInternalMin] = React.useState(currentMinProp ?? stateRange.min ?? min);
|
|
4823
|
-
const [internalMax, setInternalMax] = React.useState(currentMaxProp ?? stateRange.max ?? max);
|
|
4824
|
-
const [isDragging, setIsDragging] = React.useState(false);
|
|
4825
|
-
const debounceRef = React.useRef(null);
|
|
4826
|
-
// Sync with StateManager changes
|
|
4827
|
-
React.useEffect(() => {
|
|
4828
|
-
if (syncWithState && !isDragging) {
|
|
4829
|
-
if (stateRange.min !== undefined)
|
|
4830
|
-
setInternalMin(stateRange.min);
|
|
4831
|
-
else
|
|
4832
|
-
setInternalMin(min);
|
|
4833
|
-
if (stateRange.max !== undefined)
|
|
4834
|
-
setInternalMax(stateRange.max);
|
|
4835
|
-
else
|
|
4836
|
-
setInternalMax(max);
|
|
4837
|
-
}
|
|
4838
|
-
}, [syncWithState, stateRange.min, stateRange.max, isDragging, min, max]);
|
|
4839
|
-
// Update StateManager with range refinements
|
|
4840
|
-
const updateStateManager = React.useCallback((minVal, maxVal) => {
|
|
4841
|
-
if (!syncWithState)
|
|
4842
|
-
return;
|
|
4843
|
-
// Remove existing range refinements for this field
|
|
4844
|
-
refinements.forEach(r => {
|
|
4845
|
-
if (r.field === field) {
|
|
4846
|
-
removeRefinement(field, r.value, false);
|
|
4847
|
-
}
|
|
4848
|
-
});
|
|
4849
|
-
// Add new range refinements
|
|
4850
|
-
if (minVal > min) {
|
|
4851
|
-
addRefinement(field, `>=${minVal}`, false);
|
|
4852
|
-
}
|
|
4853
|
-
if (maxVal < max) {
|
|
4854
|
-
addRefinement(field, `<=${maxVal}`, minVal <= min); // Trigger search if only max is set
|
|
4855
|
-
}
|
|
4856
|
-
if (minVal > min && maxVal >= max) {
|
|
4857
|
-
// Trigger search after setting min
|
|
4858
|
-
addRefinement(field, `>=${minVal}`, true);
|
|
4859
|
-
}
|
|
4860
|
-
}, [syncWithState, field, refinements, addRefinement, removeRefinement, min, max]);
|
|
4861
|
-
// Debounced update
|
|
4862
|
-
const debouncedUpdate = React.useCallback((minVal, maxVal) => {
|
|
4863
|
-
if (debounceRef.current) {
|
|
4864
|
-
clearTimeout(debounceRef.current);
|
|
4865
|
-
}
|
|
4866
|
-
debounceRef.current = setTimeout(() => {
|
|
4867
|
-
updateStateManager(minVal, maxVal);
|
|
4868
|
-
if (onRangeChange) {
|
|
4869
|
-
onRangeChange(minVal, maxVal);
|
|
4870
|
-
}
|
|
4871
|
-
}, debounceMs);
|
|
4872
|
-
}, [updateStateManager, onRangeChange, debounceMs]);
|
|
4873
|
-
// Handle min slider change
|
|
4874
|
-
const handleMinChange = (e) => {
|
|
4875
|
-
const value = Math.min(Number(e.target.value), internalMax - step);
|
|
4876
|
-
setInternalMin(value);
|
|
4877
|
-
setIsDragging(true);
|
|
4878
|
-
debouncedUpdate(value, internalMax);
|
|
4879
|
-
};
|
|
4880
|
-
// Handle max slider change
|
|
4881
|
-
const handleMaxChange = (e) => {
|
|
4882
|
-
const value = Math.max(Number(e.target.value), internalMin + step);
|
|
4883
|
-
setInternalMax(value);
|
|
4884
|
-
setIsDragging(true);
|
|
4885
|
-
debouncedUpdate(internalMin, value);
|
|
4886
|
-
};
|
|
4887
|
-
// Handle drag end
|
|
4888
|
-
const handleDragEnd = () => {
|
|
4889
|
-
setIsDragging(false);
|
|
4890
|
-
};
|
|
4891
|
-
// Handle keyboard navigation for enhanced control (Shift+Arrow for 10x step, Home/End)
|
|
4892
|
-
const handleMinKeyDown = (e) => {
|
|
4893
|
-
let newValue = null;
|
|
4894
|
-
if (e.key === 'Home') {
|
|
4895
|
-
e.preventDefault();
|
|
4896
|
-
newValue = min;
|
|
4897
|
-
}
|
|
4898
|
-
else if (e.key === 'End') {
|
|
4899
|
-
e.preventDefault();
|
|
4900
|
-
newValue = internalMax - step;
|
|
4901
|
-
}
|
|
4902
|
-
else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
|
|
4903
|
-
e.preventDefault();
|
|
4904
|
-
newValue = Math.max(min, internalMin - step * 10);
|
|
4905
|
-
}
|
|
4906
|
-
else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
|
|
4907
|
-
e.preventDefault();
|
|
4908
|
-
newValue = Math.min(internalMax - step, internalMin + step * 10);
|
|
4909
|
-
}
|
|
4910
|
-
if (newValue !== null) {
|
|
4911
|
-
setInternalMin(newValue);
|
|
4912
|
-
debouncedUpdate(newValue, internalMax);
|
|
4913
|
-
}
|
|
4914
|
-
};
|
|
4915
|
-
const handleMaxKeyDown = (e) => {
|
|
4916
|
-
let newValue = null;
|
|
4917
|
-
if (e.key === 'Home') {
|
|
4918
|
-
e.preventDefault();
|
|
4919
|
-
newValue = internalMin + step;
|
|
4920
|
-
}
|
|
4921
|
-
else if (e.key === 'End') {
|
|
4922
|
-
e.preventDefault();
|
|
4923
|
-
newValue = max;
|
|
4924
|
-
}
|
|
4925
|
-
else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
|
|
4926
|
-
e.preventDefault();
|
|
4927
|
-
newValue = Math.max(internalMin + step, internalMax - step * 10);
|
|
4928
|
-
}
|
|
4929
|
-
else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
|
|
4930
|
-
e.preventDefault();
|
|
4931
|
-
newValue = Math.min(max, internalMax + step * 10);
|
|
4932
|
-
}
|
|
4933
|
-
if (newValue !== null) {
|
|
4934
|
-
setInternalMax(newValue);
|
|
4935
|
-
debouncedUpdate(internalMin, newValue);
|
|
5612
|
+
else
|
|
5613
|
+
parentItem.focus();
|
|
5614
|
+
}
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
break;
|
|
5618
|
+
}
|
|
5619
|
+
case 'Enter': {
|
|
5620
|
+
if (!currentItem)
|
|
5621
|
+
break;
|
|
5622
|
+
e.preventDefault();
|
|
5623
|
+
const button = currentItem.querySelector('button');
|
|
5624
|
+
if (button)
|
|
5625
|
+
button.click();
|
|
5626
|
+
break;
|
|
5627
|
+
}
|
|
4936
5628
|
}
|
|
4937
|
-
};
|
|
4938
|
-
//
|
|
4939
|
-
const
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
color: theme.colors.text,
|
|
4951
|
-
} }, label)),
|
|
4952
|
-
React.createElement("div", { className: rangeSliderTheme.slider, style: {
|
|
4953
|
-
position: 'relative',
|
|
4954
|
-
height: '40px',
|
|
4955
|
-
display: 'flex',
|
|
4956
|
-
alignItems: 'center',
|
|
4957
|
-
} },
|
|
4958
|
-
React.createElement("div", { className: rangeSliderTheme.track, style: {
|
|
4959
|
-
position: 'absolute',
|
|
4960
|
-
width: '100%',
|
|
4961
|
-
height: '4px',
|
|
4962
|
-
backgroundColor: theme.colors.border,
|
|
4963
|
-
borderRadius: '2px',
|
|
4964
|
-
} }),
|
|
4965
|
-
React.createElement("div", { className: rangeSliderTheme.trackFilled, style: {
|
|
4966
|
-
position: 'absolute',
|
|
4967
|
-
left: `${minPercent}%`,
|
|
4968
|
-
width: `${maxPercent - minPercent}%`,
|
|
4969
|
-
height: '4px',
|
|
4970
|
-
backgroundColor: theme.colors.primary,
|
|
4971
|
-
borderRadius: '2px',
|
|
4972
|
-
} }),
|
|
4973
|
-
React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMin, onChange: handleMinChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMinKeyDown, tabIndex: 0, "aria-valuenow": internalMin, "aria-valuemin": min, "aria-valuemax": max, className: rangeSliderTheme.thumb, style: {
|
|
4974
|
-
position: 'absolute',
|
|
4975
|
-
width: '100%',
|
|
4976
|
-
height: '4px',
|
|
4977
|
-
background: 'transparent',
|
|
4978
|
-
WebkitAppearance: 'none',
|
|
4979
|
-
appearance: 'none',
|
|
4980
|
-
cursor: 'pointer',
|
|
4981
|
-
pointerEvents: 'none',
|
|
4982
|
-
}, "aria-label": `Minimum ${label || field}` }),
|
|
4983
|
-
React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMax, onChange: handleMaxChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMaxKeyDown, tabIndex: 0, "aria-valuenow": internalMax, "aria-valuemin": min, "aria-valuemax": max, className: rangeSliderTheme.thumb, style: {
|
|
4984
|
-
position: 'absolute',
|
|
4985
|
-
width: '100%',
|
|
4986
|
-
height: '4px',
|
|
4987
|
-
background: 'transparent',
|
|
4988
|
-
WebkitAppearance: 'none',
|
|
4989
|
-
appearance: 'none',
|
|
4990
|
-
cursor: 'pointer',
|
|
4991
|
-
pointerEvents: 'none',
|
|
4992
|
-
}, "aria-label": `Maximum ${label || field}` })),
|
|
4993
|
-
showValues && (React.createElement("div", { className: rangeSliderTheme.values, style: {
|
|
4994
|
-
display: 'flex',
|
|
4995
|
-
justifyContent: 'space-between',
|
|
4996
|
-
marginTop: theme.spacing.small,
|
|
4997
|
-
fontSize: theme.typography.fontSize.small,
|
|
4998
|
-
color: theme.colors.textSecondary,
|
|
5629
|
+
}, [getVisibleTreeItems]);
|
|
5630
|
+
// Render a level of the hierarchy
|
|
5631
|
+
const renderLevel = (items, level) => {
|
|
5632
|
+
if (!items || items.length === 0)
|
|
5633
|
+
return null;
|
|
5634
|
+
const isExpanded = expanded[level] || false;
|
|
5635
|
+
const displayLimit = isExpanded ? showMoreLimit : limit;
|
|
5636
|
+
const displayItems = items.slice(0, displayLimit);
|
|
5637
|
+
const hasMore = items.length > displayLimit;
|
|
5638
|
+
return (React.createElement("ul", { role: level === 0 ? 'tree' : 'group', className: hierarchicalTheme.list, style: {
|
|
5639
|
+
listStyle: 'none',
|
|
5640
|
+
margin: 0,
|
|
5641
|
+
padding: level > 0 ? `0 0 0 ${theme.spacing.medium}` : 0,
|
|
4999
5642
|
} },
|
|
5000
|
-
React.createElement("
|
|
5001
|
-
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
5006
|
-
|
|
5007
|
-
|
|
5008
|
-
|
|
5009
|
-
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5643
|
+
displayItems.map((item, index) => (React.createElement("li", { key: item.value, role: "treeitem", ...(item.data && item.data.length > 0
|
|
5644
|
+
? { 'aria-expanded': !!item.isRefined }
|
|
5645
|
+
: {}), className: clsx(hierarchicalTheme.item, item.isRefined && hierarchicalTheme.itemSelected, item.data && item.data.length > 0 && hierarchicalTheme.itemParent), style: {
|
|
5646
|
+
padding: `${theme.spacing.small} 0`,
|
|
5647
|
+
} }, renderItem ? (renderItem(item, level)) : (React.createElement(React.Fragment, null,
|
|
5648
|
+
React.createElement("button", { type: "button", onClick: () => handleItemClick(item, level), className: hierarchicalTheme.link, style: {
|
|
5649
|
+
display: 'flex',
|
|
5650
|
+
alignItems: 'center',
|
|
5651
|
+
gap: theme.spacing.small,
|
|
5652
|
+
width: '100%',
|
|
5653
|
+
padding: 0,
|
|
5654
|
+
background: 'none',
|
|
5655
|
+
border: 'none',
|
|
5656
|
+
cursor: 'pointer',
|
|
5657
|
+
textAlign: 'left',
|
|
5658
|
+
fontFamily: 'inherit',
|
|
5659
|
+
fontSize: theme.typography.fontSize.small,
|
|
5660
|
+
color: item.isRefined ? theme.colors.primary : theme.colors.text,
|
|
5661
|
+
fontWeight: item.isRefined ? 600 : 400,
|
|
5662
|
+
} },
|
|
5663
|
+
React.createElement("span", { className: hierarchicalTheme.label, style: { flex: 1 } }, item.label),
|
|
5664
|
+
item.count !== undefined && (React.createElement("span", { className: hierarchicalTheme.count, style: {
|
|
5665
|
+
color: theme.colors.textSecondary,
|
|
5666
|
+
fontSize: theme.typography.fontSize.small,
|
|
5667
|
+
} }, item.count))),
|
|
5668
|
+
item.isRefined && item.data && item.data.length > 0 && (renderLevel(item.data, level + 1))))))),
|
|
5669
|
+
showMore && hasMore && (React.createElement("li", null,
|
|
5670
|
+
React.createElement("button", { type: "button", onClick: () => toggleShowMore(level), className: hierarchicalTheme.showMore, style: {
|
|
5671
|
+
padding: `${theme.spacing.small} 0`,
|
|
5672
|
+
background: 'none',
|
|
5673
|
+
border: 'none',
|
|
5674
|
+
cursor: 'pointer',
|
|
5675
|
+
fontSize: theme.typography.fontSize.small,
|
|
5676
|
+
color: theme.colors.primary,
|
|
5677
|
+
textDecoration: 'underline',
|
|
5678
|
+
} }, isExpanded ? 'Show less' : `Show ${items.length - displayLimit} more`)))));
|
|
5679
|
+
};
|
|
5680
|
+
if (processedItems.length === 0) {
|
|
5681
|
+
return null;
|
|
5682
|
+
}
|
|
5683
|
+
return (React.createElement("div", { ref: containerRef, className: clsx(hierarchicalTheme.root, className), style: style, tabIndex: 0, onKeyDown: handleKeyDown }, renderLevel(processedItems, 0)));
|
|
5025
5684
|
};
|
|
5026
5685
|
|
|
5027
5686
|
/**
|
|
@@ -6167,13 +6826,21 @@ function useQuerySuggestionsEnhanced(options) {
|
|
|
6167
6826
|
* - Accessibility support
|
|
6168
6827
|
*/
|
|
6169
6828
|
// ============================================================================
|
|
6829
|
+
// Constants
|
|
6830
|
+
// ============================================================================
|
|
6831
|
+
const TRANSITIONS$6 = {
|
|
6832
|
+
fast: '150ms ease-in-out'};
|
|
6833
|
+
const BORDER_RADIUS$9 = {
|
|
6834
|
+
sm: 4,
|
|
6835
|
+
lg: 8};
|
|
6836
|
+
// ============================================================================
|
|
6170
6837
|
// Styles
|
|
6171
6838
|
// ============================================================================
|
|
6172
6839
|
const defaultStyles$1 = {
|
|
6173
6840
|
container: {
|
|
6174
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
6175
|
-
border: '1px solid var(--seekora-border-color,
|
|
6176
|
-
borderRadius:
|
|
6841
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
6842
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
6843
|
+
borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS$9.lg}px)`,
|
|
6177
6844
|
boxShadow: 'var(--seekora-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05))',
|
|
6178
6845
|
maxHeight: '400px',
|
|
6179
6846
|
overflowY: 'auto',
|
|
@@ -6182,7 +6849,7 @@ const defaultStyles$1 = {
|
|
|
6182
6849
|
sectionTitle: {
|
|
6183
6850
|
fontSize: '12px',
|
|
6184
6851
|
fontWeight: 600,
|
|
6185
|
-
color: 'var(--seekora-text-secondary,
|
|
6852
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6186
6853
|
textTransform: 'uppercase',
|
|
6187
6854
|
letterSpacing: '0.05em',
|
|
6188
6855
|
padding: '8px 16px 4px',
|
|
@@ -6193,9 +6860,9 @@ const defaultStyles$1 = {
|
|
|
6193
6860
|
alignItems: 'center',
|
|
6194
6861
|
padding: '10px 16px',
|
|
6195
6862
|
cursor: 'pointer',
|
|
6196
|
-
transition:
|
|
6863
|
+
transition: `background-color ${TRANSITIONS$6.fast}`,
|
|
6197
6864
|
fontSize: '14px',
|
|
6198
|
-
color: 'var(--seekora-text-primary,
|
|
6865
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
6199
6866
|
gap: '12px',
|
|
6200
6867
|
},
|
|
6201
6868
|
suggestionItemActive: {
|
|
@@ -6215,10 +6882,10 @@ const defaultStyles$1 = {
|
|
|
6215
6882
|
},
|
|
6216
6883
|
highlight: {
|
|
6217
6884
|
fontWeight: 600,
|
|
6218
|
-
color: 'var(--seekora-text-primary,
|
|
6885
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
6219
6886
|
backgroundColor: 'var(--seekora-highlight-bg, #fef3c7)',
|
|
6220
6887
|
padding: '0 2px',
|
|
6221
|
-
borderRadius:
|
|
6888
|
+
borderRadius: `${BORDER_RADIUS$9.sm / 2}px`,
|
|
6222
6889
|
},
|
|
6223
6890
|
recentIcon: {
|
|
6224
6891
|
width: '16px',
|
|
@@ -6228,13 +6895,13 @@ const defaultStyles$1 = {
|
|
|
6228
6895
|
},
|
|
6229
6896
|
removeButton: {
|
|
6230
6897
|
padding: '4px',
|
|
6231
|
-
borderRadius:
|
|
6898
|
+
borderRadius: `${BORDER_RADIUS$9.sm}px`,
|
|
6232
6899
|
border: 'none',
|
|
6233
6900
|
background: 'transparent',
|
|
6234
6901
|
cursor: 'pointer',
|
|
6235
6902
|
color: 'var(--seekora-text-secondary, #9ca3af)',
|
|
6236
6903
|
opacity: 0,
|
|
6237
|
-
transition:
|
|
6904
|
+
transition: `opacity ${TRANSITIONS$6.fast}, color ${TRANSITIONS$6.fast}`,
|
|
6238
6905
|
},
|
|
6239
6906
|
removeButtonVisible: {
|
|
6240
6907
|
opacity: 1,
|
|
@@ -6244,7 +6911,7 @@ const defaultStyles$1 = {
|
|
|
6244
6911
|
alignItems: 'center',
|
|
6245
6912
|
justifyContent: 'center',
|
|
6246
6913
|
padding: '24px 16px',
|
|
6247
|
-
color: 'var(--seekora-text-secondary,
|
|
6914
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6248
6915
|
fontSize: '14px',
|
|
6249
6916
|
gap: '8px',
|
|
6250
6917
|
},
|
|
@@ -6254,20 +6921,20 @@ const defaultStyles$1 = {
|
|
|
6254
6921
|
alignItems: 'center',
|
|
6255
6922
|
justifyContent: 'center',
|
|
6256
6923
|
padding: '24px 16px',
|
|
6257
|
-
color: 'var(--seekora-text-secondary,
|
|
6924
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6258
6925
|
fontSize: '14px',
|
|
6259
6926
|
textAlign: 'center',
|
|
6260
6927
|
},
|
|
6261
6928
|
divider: {
|
|
6262
6929
|
height: '1px',
|
|
6263
|
-
backgroundColor: 'var(--seekora-border-color,
|
|
6930
|
+
backgroundColor: 'var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
6264
6931
|
margin: '4px 0',
|
|
6265
6932
|
},
|
|
6266
6933
|
footer: {
|
|
6267
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
6934
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
6268
6935
|
padding: '8px 16px',
|
|
6269
6936
|
fontSize: '12px',
|
|
6270
|
-
color: 'var(--seekora-text-secondary,
|
|
6937
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6271
6938
|
display: 'flex',
|
|
6272
6939
|
alignItems: 'center',
|
|
6273
6940
|
justifyContent: 'space-between',
|
|
@@ -6285,9 +6952,9 @@ const defaultStyles$1 = {
|
|
|
6285
6952
|
minWidth: '20px',
|
|
6286
6953
|
height: '18px',
|
|
6287
6954
|
padding: '0 4px',
|
|
6288
|
-
borderRadius:
|
|
6289
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
6290
|
-
border: '1px solid var(--seekora-border-color,
|
|
6955
|
+
borderRadius: `${BORDER_RADIUS$9.sm - 1}px`,
|
|
6956
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
6957
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
6291
6958
|
fontSize: '10px',
|
|
6292
6959
|
fontWeight: 500,
|
|
6293
6960
|
},
|
|
@@ -6555,6 +7222,16 @@ const QuerySuggestionsDropdown = React.forwardRef(function QuerySuggestionsDropd
|
|
|
6555
7222
|
* - Configurable sections
|
|
6556
7223
|
* - Rich styling options
|
|
6557
7224
|
*/
|
|
7225
|
+
// ============================================================================
|
|
7226
|
+
// Constants
|
|
7227
|
+
// ============================================================================
|
|
7228
|
+
const TRANSITIONS$5 = {
|
|
7229
|
+
fast: '150ms ease-in-out'};
|
|
7230
|
+
const BORDER_RADIUS$8 = {
|
|
7231
|
+
sm: 4,
|
|
7232
|
+
lg: 8,
|
|
7233
|
+
full: 9999,
|
|
7234
|
+
};
|
|
6558
7235
|
// Default section order
|
|
6559
7236
|
const DEFAULT_SECTIONS = [
|
|
6560
7237
|
{ id: 'recent', title: 'Recent Searches', maxItems: 5, enabled: true, order: 1 },
|
|
@@ -6567,16 +7244,16 @@ const DEFAULT_SECTIONS = [
|
|
|
6567
7244
|
// ============================================================================
|
|
6568
7245
|
const styles$2 = {
|
|
6569
7246
|
container: {
|
|
6570
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
6571
|
-
border: '1px solid var(--seekora-border-color,
|
|
6572
|
-
borderRadius:
|
|
7247
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
7248
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7249
|
+
borderRadius: `var(--seekora-border-radius-lg, ${BORDER_RADIUS$8.lg * 1.5}px)`,
|
|
6573
7250
|
boxShadow: 'var(--seekora-shadow-xl, 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04))',
|
|
6574
7251
|
overflow: 'hidden',
|
|
6575
7252
|
},
|
|
6576
7253
|
header: {
|
|
6577
7254
|
padding: '12px 16px',
|
|
6578
|
-
borderBottom: '1px solid var(--seekora-border-color,
|
|
6579
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
7255
|
+
borderBottom: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7256
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
6580
7257
|
},
|
|
6581
7258
|
content: {
|
|
6582
7259
|
overflowY: 'auto',
|
|
@@ -6608,7 +7285,7 @@ const styles$2 = {
|
|
|
6608
7285
|
alignItems: 'flex-start',
|
|
6609
7286
|
padding: '10px 16px',
|
|
6610
7287
|
cursor: 'pointer',
|
|
6611
|
-
transition:
|
|
7288
|
+
transition: `background-color ${TRANSITIONS$5.fast}`,
|
|
6612
7289
|
gap: '12px',
|
|
6613
7290
|
},
|
|
6614
7291
|
itemActive: {
|
|
@@ -6627,7 +7304,7 @@ const styles$2 = {
|
|
|
6627
7304
|
},
|
|
6628
7305
|
itemQuery: {
|
|
6629
7306
|
fontSize: '14px',
|
|
6630
|
-
color: 'var(--seekora-text-primary,
|
|
7307
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
6631
7308
|
fontWeight: 500,
|
|
6632
7309
|
margin: 0,
|
|
6633
7310
|
overflow: 'hidden',
|
|
@@ -6652,11 +7329,11 @@ const styles$2 = {
|
|
|
6652
7329
|
padding: '3px 8px',
|
|
6653
7330
|
fontSize: '11px',
|
|
6654
7331
|
fontWeight: 500,
|
|
6655
|
-
color: 'var(--seekora-text-secondary,
|
|
6656
|
-
backgroundColor: 'var(--seekora-bg-tertiary,
|
|
6657
|
-
borderRadius:
|
|
7332
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
7333
|
+
backgroundColor: 'var(--seekora-bg-tertiary, rgba(255, 255, 255, 0.1))',
|
|
7334
|
+
borderRadius: `${BORDER_RADIUS$8.lg * 1.5}px`,
|
|
6658
7335
|
cursor: 'pointer',
|
|
6659
|
-
transition:
|
|
7336
|
+
transition: `all ${TRANSITIONS$5.fast}`,
|
|
6660
7337
|
},
|
|
6661
7338
|
categoryPillHover: {
|
|
6662
7339
|
backgroundColor: 'var(--seekora-primary-light, #dbeafe)',
|
|
@@ -6678,12 +7355,12 @@ const styles$2 = {
|
|
|
6678
7355
|
padding: '6px 12px',
|
|
6679
7356
|
fontSize: '13px',
|
|
6680
7357
|
fontWeight: 500,
|
|
6681
|
-
color: 'var(--seekora-text-primary,
|
|
6682
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
6683
|
-
border: '1px solid var(--seekora-border-color,
|
|
6684
|
-
borderRadius:
|
|
7358
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
7359
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
7360
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7361
|
+
borderRadius: `${BORDER_RADIUS$8.full}px`,
|
|
6685
7362
|
cursor: 'pointer',
|
|
6686
|
-
transition:
|
|
7363
|
+
transition: `all ${TRANSITIONS$5.fast}`,
|
|
6687
7364
|
},
|
|
6688
7365
|
trendingChipHover: {
|
|
6689
7366
|
borderColor: 'var(--seekora-primary, #3b82f6)',
|
|
@@ -6697,7 +7374,7 @@ const styles$2 = {
|
|
|
6697
7374
|
trendingRank: {
|
|
6698
7375
|
width: '18px',
|
|
6699
7376
|
height: '18px',
|
|
6700
|
-
borderRadius:
|
|
7377
|
+
borderRadius: `${BORDER_RADIUS$8.full}px`,
|
|
6701
7378
|
backgroundColor: 'var(--seekora-primary, #3b82f6)',
|
|
6702
7379
|
color: 'white',
|
|
6703
7380
|
fontSize: '10px',
|
|
@@ -6709,25 +7386,25 @@ const styles$2 = {
|
|
|
6709
7386
|
removeButton: {
|
|
6710
7387
|
padding: '4px',
|
|
6711
7388
|
marginLeft: 'auto',
|
|
6712
|
-
borderRadius:
|
|
7389
|
+
borderRadius: `${BORDER_RADIUS$8.sm}px`,
|
|
6713
7390
|
border: 'none',
|
|
6714
7391
|
background: 'transparent',
|
|
6715
7392
|
cursor: 'pointer',
|
|
6716
7393
|
color: 'var(--seekora-text-tertiary, #9ca3af)',
|
|
6717
7394
|
opacity: 0,
|
|
6718
|
-
transition:
|
|
7395
|
+
transition: `opacity ${TRANSITIONS$5.fast}`,
|
|
6719
7396
|
},
|
|
6720
7397
|
divider: {
|
|
6721
7398
|
height: '1px',
|
|
6722
|
-
backgroundColor: 'var(--seekora-border-color,
|
|
7399
|
+
backgroundColor: 'var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
6723
7400
|
margin: '4px 16px',
|
|
6724
7401
|
},
|
|
6725
7402
|
footer: {
|
|
6726
7403
|
padding: '12px 16px',
|
|
6727
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
6728
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
7404
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7405
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
6729
7406
|
fontSize: '12px',
|
|
6730
|
-
color: 'var(--seekora-text-secondary,
|
|
7407
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6731
7408
|
},
|
|
6732
7409
|
loadingOverlay: {
|
|
6733
7410
|
position: 'absolute',
|
|
@@ -6735,12 +7412,12 @@ const styles$2 = {
|
|
|
6735
7412
|
display: 'flex',
|
|
6736
7413
|
alignItems: 'center',
|
|
6737
7414
|
justifyContent: 'center',
|
|
6738
|
-
backgroundColor: 'rgba(255, 255, 255, 0.
|
|
7415
|
+
backgroundColor: 'rgba(255, 255, 255, 0.1)',
|
|
6739
7416
|
},
|
|
6740
7417
|
emptyState: {
|
|
6741
7418
|
padding: '32px 16px',
|
|
6742
7419
|
textAlign: 'center',
|
|
6743
|
-
color: 'var(--seekora-text-secondary,
|
|
7420
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
6744
7421
|
},
|
|
6745
7422
|
highlight: {
|
|
6746
7423
|
backgroundColor: 'var(--seekora-highlight-bg, #fef9c3)',
|
|
@@ -7035,20 +7712,30 @@ const RichQuerySuggestions = React.forwardRef(function RichQuerySuggestions(prop
|
|
|
7035
7712
|
* - Rich product cards
|
|
7036
7713
|
*/
|
|
7037
7714
|
// ============================================================================
|
|
7715
|
+
// Constants
|
|
7716
|
+
// ============================================================================
|
|
7717
|
+
const TRANSITIONS$4 = {
|
|
7718
|
+
fast: '150ms ease-in-out'};
|
|
7719
|
+
const BORDER_RADIUS$7 = {
|
|
7720
|
+
sm: 4,
|
|
7721
|
+
lg: 8,
|
|
7722
|
+
full: 9999,
|
|
7723
|
+
};
|
|
7724
|
+
// ============================================================================
|
|
7038
7725
|
// Styles
|
|
7039
7726
|
// ============================================================================
|
|
7040
7727
|
const styles$1 = {
|
|
7041
7728
|
container: {
|
|
7042
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
7043
|
-
border: '1px solid var(--seekora-border-color,
|
|
7044
|
-
borderRadius:
|
|
7729
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
7730
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7731
|
+
borderRadius: `var(--seekora-border-radius-lg, ${BORDER_RADIUS$7.lg * 1.5}px)`,
|
|
7045
7732
|
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
|
|
7046
7733
|
overflow: 'hidden',
|
|
7047
7734
|
},
|
|
7048
7735
|
header: {
|
|
7049
7736
|
padding: '12px 20px',
|
|
7050
|
-
borderBottom: '1px solid var(--seekora-border-color,
|
|
7051
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
7737
|
+
borderBottom: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7738
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
7052
7739
|
},
|
|
7053
7740
|
content: {
|
|
7054
7741
|
display: 'flex',
|
|
@@ -7058,13 +7745,13 @@ const styles$1 = {
|
|
|
7058
7745
|
flexDirection: 'column',
|
|
7059
7746
|
},
|
|
7060
7747
|
suggestionsColumn: {
|
|
7061
|
-
borderRight: '1px solid var(--seekora-border-color,
|
|
7748
|
+
borderRight: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7062
7749
|
overflowY: 'auto',
|
|
7063
7750
|
},
|
|
7064
7751
|
productsColumn: {
|
|
7065
7752
|
flex: 1,
|
|
7066
7753
|
overflowY: 'auto',
|
|
7067
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
7754
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
7068
7755
|
},
|
|
7069
7756
|
section: {
|
|
7070
7757
|
padding: '12px 0',
|
|
@@ -7095,7 +7782,7 @@ const styles$1 = {
|
|
|
7095
7782
|
alignItems: 'center',
|
|
7096
7783
|
padding: '10px 20px',
|
|
7097
7784
|
cursor: 'pointer',
|
|
7098
|
-
transition:
|
|
7785
|
+
transition: `background-color ${TRANSITIONS$4.fast}`,
|
|
7099
7786
|
gap: '12px',
|
|
7100
7787
|
},
|
|
7101
7788
|
suggestionItemActive: {
|
|
@@ -7110,7 +7797,7 @@ const styles$1 = {
|
|
|
7110
7797
|
suggestionText: {
|
|
7111
7798
|
flex: 1,
|
|
7112
7799
|
fontSize: '14px',
|
|
7113
|
-
color: 'var(--seekora-text-primary,
|
|
7800
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
7114
7801
|
fontWeight: 500,
|
|
7115
7802
|
overflow: 'hidden',
|
|
7116
7803
|
textOverflow: 'ellipsis',
|
|
@@ -7134,7 +7821,7 @@ const styles$1 = {
|
|
|
7134
7821
|
display: 'flex',
|
|
7135
7822
|
gap: '4px',
|
|
7136
7823
|
padding: '12px 20px',
|
|
7137
|
-
borderBottom: '1px solid var(--seekora-border-color,
|
|
7824
|
+
borderBottom: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7138
7825
|
overflowX: 'auto',
|
|
7139
7826
|
},
|
|
7140
7827
|
tab: {
|
|
@@ -7144,13 +7831,13 @@ const styles$1 = {
|
|
|
7144
7831
|
padding: '8px 16px',
|
|
7145
7832
|
fontSize: '13px',
|
|
7146
7833
|
fontWeight: 500,
|
|
7147
|
-
color: 'var(--seekora-text-secondary,
|
|
7834
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
7148
7835
|
backgroundColor: 'transparent',
|
|
7149
7836
|
border: '1px solid transparent',
|
|
7150
|
-
borderRadius:
|
|
7837
|
+
borderRadius: `${BORDER_RADIUS$7.full}px`,
|
|
7151
7838
|
cursor: 'pointer',
|
|
7152
7839
|
whiteSpace: 'nowrap',
|
|
7153
|
-
transition:
|
|
7840
|
+
transition: `all ${TRANSITIONS$4.fast}`,
|
|
7154
7841
|
},
|
|
7155
7842
|
tabActive: {
|
|
7156
7843
|
color: 'var(--seekora-primary, #3b82f6)',
|
|
@@ -7161,8 +7848,8 @@ const styles$1 = {
|
|
|
7161
7848
|
fontSize: '11px',
|
|
7162
7849
|
fontWeight: 600,
|
|
7163
7850
|
padding: '2px 6px',
|
|
7164
|
-
borderRadius:
|
|
7165
|
-
backgroundColor: 'var(--seekora-bg-tertiary,
|
|
7851
|
+
borderRadius: `${BORDER_RADIUS$7.lg}px`,
|
|
7852
|
+
backgroundColor: 'var(--seekora-bg-tertiary, rgba(255, 255, 255, 0.1))',
|
|
7166
7853
|
},
|
|
7167
7854
|
tabCountActive: {
|
|
7168
7855
|
backgroundColor: 'var(--seekora-primary, #3b82f6)',
|
|
@@ -7177,12 +7864,12 @@ const styles$1 = {
|
|
|
7177
7864
|
productCard: {
|
|
7178
7865
|
display: 'flex',
|
|
7179
7866
|
flexDirection: 'column',
|
|
7180
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
7181
|
-
borderRadius:
|
|
7867
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
7868
|
+
borderRadius: `${BORDER_RADIUS$7.lg}px`,
|
|
7182
7869
|
overflow: 'hidden',
|
|
7183
7870
|
cursor: 'pointer',
|
|
7184
|
-
transition:
|
|
7185
|
-
border: '1px solid var(--seekora-border-color,
|
|
7871
|
+
transition: `transform ${TRANSITIONS$4.fast}, box-shadow ${TRANSITIONS$4.fast}`,
|
|
7872
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7186
7873
|
},
|
|
7187
7874
|
productCardHover: {
|
|
7188
7875
|
transform: 'translateY(-2px)',
|
|
@@ -7200,7 +7887,7 @@ const styles$1 = {
|
|
|
7200
7887
|
productTitle: {
|
|
7201
7888
|
fontSize: '13px',
|
|
7202
7889
|
fontWeight: 500,
|
|
7203
|
-
color: 'var(--seekora-text-primary,
|
|
7890
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
7204
7891
|
margin: 0,
|
|
7205
7892
|
overflow: 'hidden',
|
|
7206
7893
|
textOverflow: 'ellipsis',
|
|
@@ -7228,12 +7915,12 @@ const styles$1 = {
|
|
|
7228
7915
|
padding: '8px 14px',
|
|
7229
7916
|
fontSize: '13px',
|
|
7230
7917
|
fontWeight: 500,
|
|
7231
|
-
color: 'var(--seekora-text-primary,
|
|
7232
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
7233
|
-
border: '1px solid var(--seekora-border-color,
|
|
7234
|
-
borderRadius:
|
|
7918
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
7919
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
7920
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7921
|
+
borderRadius: `${BORDER_RADIUS$7.lg}px`,
|
|
7235
7922
|
cursor: 'pointer',
|
|
7236
|
-
transition:
|
|
7923
|
+
transition: `all ${TRANSITIONS$4.fast}`,
|
|
7237
7924
|
},
|
|
7238
7925
|
brandChipHover: {
|
|
7239
7926
|
borderColor: 'var(--seekora-primary, #3b82f6)',
|
|
@@ -7242,25 +7929,25 @@ const styles$1 = {
|
|
|
7242
7929
|
brandLogo: {
|
|
7243
7930
|
width: '20px',
|
|
7244
7931
|
height: '20px',
|
|
7245
|
-
borderRadius:
|
|
7932
|
+
borderRadius: `${BORDER_RADIUS$7.sm}px`,
|
|
7246
7933
|
objectFit: 'contain',
|
|
7247
7934
|
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
7248
7935
|
},
|
|
7249
7936
|
footer: {
|
|
7250
7937
|
padding: '12px 20px',
|
|
7251
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
7252
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
7938
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
7939
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
7253
7940
|
display: 'flex',
|
|
7254
7941
|
alignItems: 'center',
|
|
7255
7942
|
justifyContent: 'space-between',
|
|
7256
7943
|
fontSize: '12px',
|
|
7257
|
-
color: 'var(--seekora-text-secondary,
|
|
7944
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
7258
7945
|
},
|
|
7259
7946
|
highlight: {
|
|
7260
7947
|
backgroundColor: 'var(--seekora-highlight-bg, #fef9c3)',
|
|
7261
7948
|
fontWeight: 600,
|
|
7262
7949
|
padding: '0 2px',
|
|
7263
|
-
borderRadius:
|
|
7950
|
+
borderRadius: `${BORDER_RADIUS$7.sm / 2}px`,
|
|
7264
7951
|
},
|
|
7265
7952
|
};
|
|
7266
7953
|
// ============================================================================
|
|
@@ -7784,8 +8471,8 @@ const styles = {
|
|
|
7784
8471
|
transition: 'border-color 150ms ease, box-shadow 150ms ease',
|
|
7785
8472
|
},
|
|
7786
8473
|
inputWrapperFocused: {
|
|
7787
|
-
borderColor: 'var(--seekora-primary, #3b82f6)',
|
|
7788
|
-
boxShadow: '0 0 0 3px var(--seekora-primary-light, rgba(59, 130, 246, 0.1))',
|
|
8474
|
+
borderColor: 'var(--seekora-border-focus, var(--seekora-primary, #3b82f6))',
|
|
8475
|
+
boxShadow: '0 0 0 3px var(--seekora-border-focus-alpha, var(--seekora-primary-light, rgba(59, 130, 246, 0.1)))',
|
|
7789
8476
|
},
|
|
7790
8477
|
input: {
|
|
7791
8478
|
flex: 1,
|
|
@@ -7828,7 +8515,7 @@ const styles = {
|
|
|
7828
8515
|
margin: '4px',
|
|
7829
8516
|
border: 'none',
|
|
7830
8517
|
backgroundColor: 'var(--seekora-primary, #3b82f6)',
|
|
7831
|
-
color: 'white',
|
|
8518
|
+
color: 'var(--seekora-primary-text, white)',
|
|
7832
8519
|
borderRadius: 'var(--seekora-border-radius, 6px)',
|
|
7833
8520
|
fontSize: '14px',
|
|
7834
8521
|
fontWeight: 600,
|
|
@@ -8269,6 +8956,13 @@ function SuggestionsProvider({ children, minQueryLength = 1, debounceMs = 200, m
|
|
|
8269
8956
|
* Single input bound to suggestions context: query, setQuery, focus opens dropdown,
|
|
8270
8957
|
* keydown ArrowUp/Down/Enter/Escape delegates to context. Overridable via className/style.
|
|
8271
8958
|
*/
|
|
8959
|
+
const SPACING$3 = {
|
|
8960
|
+
sm: 8,
|
|
8961
|
+
md: 12};
|
|
8962
|
+
const TRANSITIONS$3 = {
|
|
8963
|
+
fast: '150ms ease-in-out'};
|
|
8964
|
+
const BORDER_RADIUS$6 = {
|
|
8965
|
+
md: 6};
|
|
8272
8966
|
const defaultStyles = {
|
|
8273
8967
|
position: 'relative',
|
|
8274
8968
|
width: '100%',
|
|
@@ -8276,22 +8970,23 @@ const defaultStyles = {
|
|
|
8276
8970
|
const inputWrapperStyles = {
|
|
8277
8971
|
display: 'flex',
|
|
8278
8972
|
alignItems: 'center',
|
|
8279
|
-
gap:
|
|
8280
|
-
padding:
|
|
8281
|
-
border: '1px solid var(--seekora-border-color,
|
|
8282
|
-
borderRadius:
|
|
8283
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
8284
|
-
transition:
|
|
8973
|
+
gap: `${SPACING$3.sm}px`,
|
|
8974
|
+
padding: `${SPACING$3.sm}px ${SPACING$3.md}px`,
|
|
8975
|
+
border: '1px solid var(--seekora-border-color, rgba(0,0,0,0.1))',
|
|
8976
|
+
borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS$6.md}px)`,
|
|
8977
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
8978
|
+
transition: `border-color ${TRANSITIONS$3.fast}, box-shadow ${TRANSITIONS$3.fast}`,
|
|
8979
|
+
boxSizing: 'border-box',
|
|
8285
8980
|
};
|
|
8286
8981
|
const inputStyles = {
|
|
8287
8982
|
flex: 1,
|
|
8288
8983
|
minWidth: 0,
|
|
8289
|
-
padding:
|
|
8984
|
+
padding: `${SPACING$3.sm}px 0`,
|
|
8290
8985
|
border: 'none',
|
|
8291
8986
|
outline: 'none',
|
|
8292
8987
|
backgroundColor: 'transparent',
|
|
8293
8988
|
fontSize: 'inherit',
|
|
8294
|
-
color: 'var(--seekora-text-primary,
|
|
8989
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
8295
8990
|
fontFamily: 'inherit',
|
|
8296
8991
|
};
|
|
8297
8992
|
function SearchInput({ placeholder = 'Search...', autoFocus = false, showClearButton = true, closeOnBlur = true, leftIcon, className, style, inputClassName, inputStyle, ariaLabel = 'Search', }) {
|
|
@@ -8340,7 +9035,7 @@ function SearchInput({ placeholder = 'Search...', autoFocus = false, showClearBu
|
|
|
8340
9035
|
leftIcon ? (React.createElement("span", { className: "seekora-suggestions-input-left-icon", style: { display: 'flex', flexShrink: 0, color: 'var(--seekora-text-secondary, #6b7280)' } }, leftIcon)) : null,
|
|
8341
9036
|
React.createElement("input", { ref: inputRef, type: "text", value: query, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, placeholder: placeholder, autoFocus: autoFocus, autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false, "aria-label": ariaLabel, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-autocomplete": "list", role: "combobox", className: clsx('seekora-suggestions-input', inputClassName), style: { ...inputStyles, ...inputStyle } }),
|
|
8342
9037
|
showClearButton && query ? (React.createElement("button", { type: "button", onClick: handleClear, className: "seekora-suggestions-input-clear", "aria-label": "Clear search", style: {
|
|
8343
|
-
padding:
|
|
9038
|
+
padding: 8,
|
|
8344
9039
|
border: 'none',
|
|
8345
9040
|
background: 'transparent',
|
|
8346
9041
|
cursor: 'pointer',
|
|
@@ -8362,7 +9057,12 @@ function ClearIcon() {
|
|
|
8362
9057
|
* Shows when isOpen; handles click-outside and Escape to close. Children = any composition
|
|
8363
9058
|
* of SuggestionList, ProductGrid, etc. Position and z-index configurable.
|
|
8364
9059
|
*/
|
|
8365
|
-
|
|
9060
|
+
const BORDER_RADIUS$5 = {
|
|
9061
|
+
md: 6};
|
|
9062
|
+
// Z-index scale for consistent layering
|
|
9063
|
+
const Z_INDEX = {
|
|
9064
|
+
dropdown: 100};
|
|
9065
|
+
function DropdownPanel({ children, position = 'absolute', top = '100%', left = 0, right, width = '100%', maxHeight = '80vh', zIndex = Z_INDEX.dropdown, className, style, closeOnClickOutside = true, closeOnEscape = true, }) {
|
|
8366
9066
|
const { isOpen, close } = useSuggestionsContext();
|
|
8367
9067
|
const panelRef = React.useRef(null);
|
|
8368
9068
|
React.useEffect(() => {
|
|
@@ -8401,7 +9101,7 @@ function DropdownPanel({ children, position = 'absolute', top = '100%', left = 0
|
|
|
8401
9101
|
overflow: 'auto',
|
|
8402
9102
|
backgroundColor: 'var(--seekora-bg-surface, #fff)',
|
|
8403
9103
|
border: '1px solid var(--seekora-border-color, #e5e7eb)',
|
|
8404
|
-
borderRadius:
|
|
9104
|
+
borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS$5.md}px)`,
|
|
8405
9105
|
boxShadow: 'var(--seekora-shadow-lg, 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05))',
|
|
8406
9106
|
marginTop: 4,
|
|
8407
9107
|
};
|
|
@@ -8492,6 +9192,9 @@ const defaultItemStyle = {
|
|
|
8492
9192
|
backgroundColor: 'transparent',
|
|
8493
9193
|
color: 'var(--seekora-text-primary, #111827)',
|
|
8494
9194
|
transition: 'background-color 120ms ease',
|
|
9195
|
+
overflow: 'hidden',
|
|
9196
|
+
textOverflow: 'ellipsis',
|
|
9197
|
+
whiteSpace: 'nowrap',
|
|
8495
9198
|
};
|
|
8496
9199
|
function SuggestionItem({ suggestion, index, isActive, onSelect, className, style, enableHighlightMarkup = true, highlightMarkupOptions, renderHighlight, }) {
|
|
8497
9200
|
const displayText = suggestion.highlightedQuery ?? suggestion.query;
|
|
@@ -8676,8 +9379,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8676
9379
|
backgroundRepeat: 'no-repeat',
|
|
8677
9380
|
border: '2px solid var(--seekora-border-color, #e5e7eb)',
|
|
8678
9381
|
borderRadius: 8,
|
|
8679
|
-
boxShadow: '0 8px 24px rgba(0,0,0,0.2)',
|
|
8680
|
-
backgroundColor: '#fff',
|
|
9382
|
+
boxShadow: 'var(--seekora-zoom-panel-shadow, 0 8px 24px rgba(0,0,0,0.2))',
|
|
9383
|
+
backgroundColor: 'var(--seekora-zoom-panel-bg, #fff)',
|
|
8681
9384
|
pointerEvents: 'none',
|
|
8682
9385
|
zIndex: 9998,
|
|
8683
9386
|
};
|
|
@@ -8692,9 +9395,9 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8692
9395
|
height: lensSize,
|
|
8693
9396
|
left: cursorPos.x - lensSize / 2,
|
|
8694
9397
|
top: cursorPos.y - lensSize / 2,
|
|
8695
|
-
border: '2px solid rgba(255,255,255,0.8)',
|
|
9398
|
+
border: 'var(--seekora-lens-border, 2px solid rgba(255,255,255,0.8))',
|
|
8696
9399
|
borderRadius: '50%',
|
|
8697
|
-
boxShadow: '0 0 0 1px rgba(0,0,0,0.3), inset 0 0 0 1px rgba(0,0,0,0.3)',
|
|
9400
|
+
boxShadow: 'var(--seekora-lens-shadow, 0 0 0 1px rgba(0,0,0,0.3), inset 0 0 0 1px rgba(0,0,0,0.3))',
|
|
8698
9401
|
pointerEvents: 'none',
|
|
8699
9402
|
overflow: 'hidden',
|
|
8700
9403
|
zIndex: 100,
|
|
@@ -8724,8 +9427,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8724
9427
|
width: 32,
|
|
8725
9428
|
height: 32,
|
|
8726
9429
|
borderRadius: '50%',
|
|
8727
|
-
backgroundColor: 'rgba(0,0,0,0.6)',
|
|
8728
|
-
color: '#fff',
|
|
9430
|
+
backgroundColor: 'var(--seekora-zoom-indicator-bg, rgba(0,0,0,0.6))',
|
|
9431
|
+
color: 'var(--seekora-zoom-indicator-text, #fff)',
|
|
8729
9432
|
display: 'flex',
|
|
8730
9433
|
alignItems: 'center',
|
|
8731
9434
|
justifyContent: 'center',
|
|
@@ -8742,8 +9445,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8742
9445
|
top: cursorPos.y - 75,
|
|
8743
9446
|
width: 150,
|
|
8744
9447
|
height: 150,
|
|
8745
|
-
border: '2px solid rgba(0,0,0,0.3)',
|
|
8746
|
-
backgroundColor: 'rgba(255,255,255,0.1)',
|
|
9448
|
+
border: 'var(--seekora-hover-area-border, 2px solid rgba(0,0,0,0.3))',
|
|
9449
|
+
backgroundColor: 'var(--seekora-hover-area-bg, rgba(255,255,255,0.1))',
|
|
8747
9450
|
pointerEvents: 'none',
|
|
8748
9451
|
zIndex: 50,
|
|
8749
9452
|
} })),
|
|
@@ -8754,7 +9457,7 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8754
9457
|
left: 0,
|
|
8755
9458
|
right: 0,
|
|
8756
9459
|
bottom: 0,
|
|
8757
|
-
backgroundColor: 'rgba(0,0,0,0.95)',
|
|
9460
|
+
backgroundColor: 'var(--seekora-lightbox-bg, rgba(0,0,0,0.95))',
|
|
8758
9461
|
zIndex: 9999,
|
|
8759
9462
|
display: 'flex',
|
|
8760
9463
|
alignItems: 'center',
|
|
@@ -8770,8 +9473,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8770
9473
|
height: 44,
|
|
8771
9474
|
borderRadius: '50%',
|
|
8772
9475
|
border: 'none',
|
|
8773
|
-
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
8774
|
-
color: '#fff',
|
|
9476
|
+
backgroundColor: 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))',
|
|
9477
|
+
color: 'var(--seekora-lightbox-btn-text, #fff)',
|
|
8775
9478
|
fontSize: '1.5rem',
|
|
8776
9479
|
cursor: 'pointer',
|
|
8777
9480
|
display: 'flex',
|
|
@@ -8783,9 +9486,9 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8783
9486
|
e.stopPropagation();
|
|
8784
9487
|
closeLightbox();
|
|
8785
9488
|
}, onMouseEnter: (e) => {
|
|
8786
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.3)';
|
|
9489
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg-hover, rgba(255,255,255,0.3))';
|
|
8787
9490
|
}, onMouseLeave: (e) => {
|
|
8788
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.2)';
|
|
9491
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))';
|
|
8789
9492
|
} }, "\u2715"),
|
|
8790
9493
|
hasMultipleImages && (React.createElement(React.Fragment, null,
|
|
8791
9494
|
React.createElement("button", { type: "button", "aria-label": "Previous image", style: {
|
|
@@ -8797,8 +9500,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8797
9500
|
height: 56,
|
|
8798
9501
|
borderRadius: '50%',
|
|
8799
9502
|
border: 'none',
|
|
8800
|
-
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
8801
|
-
color: '#fff',
|
|
9503
|
+
backgroundColor: 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))',
|
|
9504
|
+
color: 'var(--seekora-lightbox-btn-text, #fff)',
|
|
8802
9505
|
fontSize: '2rem',
|
|
8803
9506
|
fontWeight: 'bold',
|
|
8804
9507
|
cursor: 'pointer',
|
|
@@ -8811,9 +9514,9 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8811
9514
|
e.stopPropagation();
|
|
8812
9515
|
goToPrev();
|
|
8813
9516
|
}, onMouseEnter: (e) => {
|
|
8814
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.3)';
|
|
9517
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg-hover, rgba(255,255,255,0.3))';
|
|
8815
9518
|
}, onMouseLeave: (e) => {
|
|
8816
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.2)';
|
|
9519
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))';
|
|
8817
9520
|
} }, "\u2039"),
|
|
8818
9521
|
React.createElement("button", { type: "button", "aria-label": "Next image", style: {
|
|
8819
9522
|
position: 'absolute',
|
|
@@ -8824,8 +9527,8 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8824
9527
|
height: 56,
|
|
8825
9528
|
borderRadius: '50%',
|
|
8826
9529
|
border: 'none',
|
|
8827
|
-
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
8828
|
-
color: '#fff',
|
|
9530
|
+
backgroundColor: 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))',
|
|
9531
|
+
color: 'var(--seekora-lightbox-btn-text, #fff)',
|
|
8829
9532
|
fontSize: '2rem',
|
|
8830
9533
|
fontWeight: 'bold',
|
|
8831
9534
|
cursor: 'pointer',
|
|
@@ -8838,9 +9541,9 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8838
9541
|
e.stopPropagation();
|
|
8839
9542
|
goToNext();
|
|
8840
9543
|
}, onMouseEnter: (e) => {
|
|
8841
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.3)';
|
|
9544
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg-hover, rgba(255,255,255,0.3))';
|
|
8842
9545
|
}, onMouseLeave: (e) => {
|
|
8843
|
-
e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.2)';
|
|
9546
|
+
e.currentTarget.style.backgroundColor = 'var(--seekora-lightbox-btn-bg, rgba(255,255,255,0.2))';
|
|
8844
9547
|
} }, "\u203A"))),
|
|
8845
9548
|
React.createElement("img", { src: allImages[lightboxIndex], alt: alt, style: {
|
|
8846
9549
|
maxWidth: '90%',
|
|
@@ -8866,7 +9569,7 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8866
9569
|
width: 60,
|
|
8867
9570
|
height: 60,
|
|
8868
9571
|
padding: 0,
|
|
8869
|
-
border: i === lightboxIndex ? '3px solid #fff' : '2px solid rgba(255,255,255,0.3)',
|
|
9572
|
+
border: i === lightboxIndex ? 'var(--seekora-lightbox-thumb-border-active, 3px solid #fff)' : 'var(--seekora-lightbox-thumb-border, 2px solid rgba(255,255,255,0.3))',
|
|
8870
9573
|
borderRadius: 4,
|
|
8871
9574
|
overflow: 'hidden',
|
|
8872
9575
|
cursor: 'pointer',
|
|
@@ -8882,10 +9585,10 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8882
9585
|
} },
|
|
8883
9586
|
React.createElement("img", { src: img, alt: "", style: { width: '100%', height: '100%', objectFit: 'cover' } }))))),
|
|
8884
9587
|
React.createElement("div", { style: {
|
|
8885
|
-
color: 'rgba(255,255,255,0.9)',
|
|
9588
|
+
color: 'var(--seekora-lightbox-counter-text, rgba(255,255,255,0.9))',
|
|
8886
9589
|
fontSize: '0.875rem',
|
|
8887
9590
|
textAlign: 'center',
|
|
8888
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
9591
|
+
backgroundColor: 'var(--seekora-lightbox-counter-bg, rgba(0,0,0,0.5))',
|
|
8889
9592
|
padding: '4px 12px',
|
|
8890
9593
|
borderRadius: 12,
|
|
8891
9594
|
} },
|
|
@@ -8897,10 +9600,10 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8897
9600
|
top: 20,
|
|
8898
9601
|
left: '50%',
|
|
8899
9602
|
transform: 'translateX(-50%)',
|
|
8900
|
-
color: 'rgba(255,255,255,0.7)',
|
|
9603
|
+
color: 'var(--seekora-lightbox-instructions-text, rgba(255,255,255,0.7))',
|
|
8901
9604
|
fontSize: '0.875rem',
|
|
8902
9605
|
textAlign: 'center',
|
|
8903
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
9606
|
+
backgroundColor: 'var(--seekora-lightbox-instructions-bg, rgba(0,0,0,0.5))',
|
|
8904
9607
|
padding: '8px 16px',
|
|
8905
9608
|
borderRadius: 12,
|
|
8906
9609
|
} }, hasMultipleImages ? 'Use arrow keys or click thumbnails to navigate • ESC to close' : 'Click outside or press ESC to close')))));
|
|
@@ -8914,10 +9617,13 @@ function ImageZoom({ src, alt = '', mode = 'both', zoomLevel = 2.5, className, s
|
|
|
8914
9617
|
*/
|
|
8915
9618
|
const imgBaseStyle = {
|
|
8916
9619
|
width: '100%',
|
|
9620
|
+
height: 'auto',
|
|
8917
9621
|
aspectRatio: '1',
|
|
8918
9622
|
objectFit: 'cover',
|
|
8919
9623
|
borderRadius: 4,
|
|
8920
9624
|
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
9625
|
+
display: 'block',
|
|
9626
|
+
overflow: 'hidden',
|
|
8921
9627
|
};
|
|
8922
9628
|
function ImageDisplay({ images, variant = 'single', alt = '', className, style, carouselAutoplay = false, carouselIntervalMs = 4000, enableZoom = false, zoomMode = 'both', zoomLevel = 2.5, showDots = true, }) {
|
|
8923
9629
|
const [index, setIndex] = React.useState(0);
|
|
@@ -8960,8 +9666,8 @@ function ImageDisplay({ images, variant = 'single', alt = '', className, style,
|
|
|
8960
9666
|
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-carousel', className), style: { position: 'relative', ...style } },
|
|
8961
9667
|
mainImage,
|
|
8962
9668
|
safeImages.length > 1 && (React.createElement(React.Fragment, null,
|
|
8963
|
-
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(), onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'rgba(255,255,255,1)'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.9)'; } }, "\u2039"),
|
|
8964
|
-
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(), onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'rgba(255,255,255,1)'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.9)'; } }, "\u203A"),
|
|
9669
|
+
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"),
|
|
9670
|
+
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"),
|
|
8965
9671
|
showDots && (React.createElement("div", { className: "seekora-img-carousel-dots", style: {
|
|
8966
9672
|
position: 'absolute',
|
|
8967
9673
|
bottom: 8,
|
|
@@ -8970,16 +9676,16 @@ function ImageDisplay({ images, variant = 'single', alt = '', className, style,
|
|
|
8970
9676
|
display: 'flex',
|
|
8971
9677
|
gap: 6,
|
|
8972
9678
|
padding: '6px 12px',
|
|
8973
|
-
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
9679
|
+
backgroundColor: 'var(--seekora-carousel-dots-bg, rgba(0,0,0,0.5))',
|
|
8974
9680
|
borderRadius: 12,
|
|
8975
9681
|
zIndex: 10,
|
|
8976
|
-
} }, 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(); setIndex(i); }, style: {
|
|
9682
|
+
} }, 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: {
|
|
8977
9683
|
width: 8,
|
|
8978
9684
|
height: 8,
|
|
8979
9685
|
borderRadius: '50%',
|
|
8980
9686
|
border: 'none',
|
|
8981
9687
|
padding: 0,
|
|
8982
|
-
backgroundColor: i === index ? '#fff' : 'rgba(255,255,255,0.5)',
|
|
9688
|
+
backgroundColor: i === index ? 'var(--seekora-carousel-dot-active, #fff)' : 'var(--seekora-carousel-dot, rgba(255,255,255,0.5))',
|
|
8983
9689
|
cursor: 'pointer',
|
|
8984
9690
|
transition: 'all 150ms ease',
|
|
8985
9691
|
} })))))))));
|
|
@@ -8989,7 +9695,7 @@ function ImageDisplay({ images, variant = 'single', alt = '', className, style,
|
|
|
8989
9695
|
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" }));
|
|
8990
9696
|
return (React.createElement("div", { className: clsx('seekora-img-display', 'seekora-img-thumbstrip', className), style: { display: 'flex', flexDirection: 'column', gap: 8, ...style } },
|
|
8991
9697
|
mainImage,
|
|
8992
|
-
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: (e) => { e.stopPropagation(); e.preventDefault(); setIndex(i); }, onClick: (e) => e.stopPropagation() },
|
|
9698
|
+
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: (e) => { e.stopPropagation(); e.preventDefault(); setIndex(i); }, onClick: (e) => { e.stopPropagation(); e.preventDefault(); } },
|
|
8993
9699
|
React.createElement("img", { src: src, alt: "", style: { width: '100%', height: '100%', objectFit: 'cover' } })))))));
|
|
8994
9700
|
}
|
|
8995
9701
|
return React.createElement("img", { src: current, alt: alt, className: clsx('seekora-img-display', className), style: { ...imgBaseStyle, ...style }, loading: "lazy" });
|
|
@@ -9004,8 +9710,8 @@ function arrowStyle(left) {
|
|
|
9004
9710
|
height: 32,
|
|
9005
9711
|
borderRadius: '50%',
|
|
9006
9712
|
border: 'none',
|
|
9007
|
-
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
9008
|
-
color: '#111',
|
|
9713
|
+
backgroundColor: 'var(--seekora-carousel-btn-bg, rgba(255, 255, 255, 0.9))',
|
|
9714
|
+
color: 'var(--seekora-carousel-btn-text, #111)',
|
|
9009
9715
|
fontSize: '1.25rem',
|
|
9010
9716
|
fontWeight: 'bold',
|
|
9011
9717
|
cursor: 'pointer',
|
|
@@ -9024,6 +9730,14 @@ function arrowStyle(left) {
|
|
|
9024
9730
|
* Renders a set of action buttons for product cards. Can be positioned absolutely
|
|
9025
9731
|
* over the image (on hover) or inline below the card content.
|
|
9026
9732
|
*/
|
|
9733
|
+
const SPACING$2 = {
|
|
9734
|
+
sm: 8};
|
|
9735
|
+
const TRANSITIONS$2 = {
|
|
9736
|
+
fast: '150ms ease-in-out'};
|
|
9737
|
+
const BORDER_RADIUS$4 = {
|
|
9738
|
+
md: 6};
|
|
9739
|
+
const SHADOWS = {
|
|
9740
|
+
md: '0 2px 4px rgba(0,0,0,0.1)'};
|
|
9027
9741
|
const DEFAULT_ICONS = {
|
|
9028
9742
|
addToCart: '🛒',
|
|
9029
9743
|
wishlist: '♡',
|
|
@@ -9039,8 +9753,8 @@ const DEFAULT_LABELS = {
|
|
|
9039
9753
|
compare: 'Compare',
|
|
9040
9754
|
};
|
|
9041
9755
|
const BUTTON_SIZES = {
|
|
9042
|
-
small: { width:
|
|
9043
|
-
medium: { width:
|
|
9756
|
+
small: { width: 44, height: 44, fontSize: '0.75rem', iconSize: '1rem' },
|
|
9757
|
+
medium: { width: 44, height: 44, fontSize: '0.875rem', iconSize: '1.25rem' },
|
|
9044
9758
|
large: { width: 44, height: 44, fontSize: '1rem', iconSize: '1.5rem' },
|
|
9045
9759
|
};
|
|
9046
9760
|
function ActionButtons({ buttons, layout = 'horizontal', position = 'inline', showLabels = false, size = 'medium', className, style, }) {
|
|
@@ -9049,11 +9763,11 @@ function ActionButtons({ buttons, layout = 'horizontal', position = 'inline', sh
|
|
|
9049
9763
|
const containerStyle = {
|
|
9050
9764
|
display: 'flex',
|
|
9051
9765
|
flexDirection: layout === 'vertical' ? 'column' : 'row',
|
|
9052
|
-
gap:
|
|
9766
|
+
gap: SPACING$2.sm,
|
|
9053
9767
|
...(isOverlay ? {
|
|
9054
9768
|
position: 'absolute',
|
|
9055
|
-
...(position === 'top-right' ? { top:
|
|
9056
|
-
...(position === 'bottom-center' ? { bottom:
|
|
9769
|
+
...(position === 'top-right' ? { top: SPACING$2.sm, right: SPACING$2.sm } : {}),
|
|
9770
|
+
...(position === 'bottom-center' ? { bottom: SPACING$2.sm, left: '50%', transform: 'translateX(-50%)' } : {}),
|
|
9057
9771
|
} : {}),
|
|
9058
9772
|
...style,
|
|
9059
9773
|
};
|
|
@@ -9068,12 +9782,12 @@ function ActionButtons({ buttons, layout = 'horizontal', position = 'inline', sh
|
|
|
9068
9782
|
fontSize: sizeConfig.fontSize,
|
|
9069
9783
|
fontWeight: 500,
|
|
9070
9784
|
border: 'none',
|
|
9071
|
-
borderRadius:
|
|
9072
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
9073
|
-
color: 'var(--seekora-text,
|
|
9785
|
+
borderRadius: BORDER_RADIUS$4.md,
|
|
9786
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
9787
|
+
color: 'var(--seekora-text, inherit)',
|
|
9074
9788
|
cursor: 'pointer',
|
|
9075
|
-
transition:
|
|
9076
|
-
boxShadow:
|
|
9789
|
+
transition: `all ${TRANSITIONS$2.fast}`,
|
|
9790
|
+
boxShadow: SHADOWS.md,
|
|
9077
9791
|
};
|
|
9078
9792
|
const handleClick = (btn, e) => {
|
|
9079
9793
|
e.stopPropagation();
|
|
@@ -9102,6 +9816,11 @@ function ActionButtons({ buttons, layout = 'horizontal', position = 'inline', sh
|
|
|
9102
9816
|
* optional description, image, url. Overridable via className/style. Use for
|
|
9103
9817
|
* search results, section blocks, or any list; for e-commerce products use ProductCard.
|
|
9104
9818
|
*/
|
|
9819
|
+
const TRANSITIONS$1 = {
|
|
9820
|
+
fast: '150ms ease-in-out'};
|
|
9821
|
+
const BORDER_RADIUS$3 = {
|
|
9822
|
+
sm: 4,
|
|
9823
|
+
md: 6};
|
|
9105
9824
|
const cardStyle$1 = {
|
|
9106
9825
|
display: 'flex',
|
|
9107
9826
|
flexDirection: 'column',
|
|
@@ -9109,19 +9828,21 @@ const cardStyle$1 = {
|
|
|
9109
9828
|
padding: 8,
|
|
9110
9829
|
cursor: 'pointer',
|
|
9111
9830
|
border: 'none',
|
|
9112
|
-
borderRadius:
|
|
9831
|
+
borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS$3.md}px)`,
|
|
9113
9832
|
backgroundColor: 'transparent',
|
|
9114
9833
|
textAlign: 'left',
|
|
9115
9834
|
fontSize: 'inherit',
|
|
9116
9835
|
fontFamily: 'inherit',
|
|
9117
|
-
transition:
|
|
9836
|
+
transition: `background-color ${TRANSITIONS$1.fast}`,
|
|
9118
9837
|
};
|
|
9119
9838
|
const imgStyle$1 = {
|
|
9120
9839
|
width: '100%',
|
|
9121
|
-
aspectRatio: '1',
|
|
9840
|
+
aspectRatio: 'var(--seekora-card-aspect-ratio, 1)',
|
|
9122
9841
|
objectFit: 'cover',
|
|
9123
|
-
borderRadius:
|
|
9842
|
+
borderRadius: BORDER_RADIUS$3.sm,
|
|
9124
9843
|
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
9844
|
+
display: 'block',
|
|
9845
|
+
overflow: 'hidden',
|
|
9125
9846
|
};
|
|
9126
9847
|
function ItemCard({ item, position, onSelect, className, style, asLink = true, imageVariant = 'single', layout = 'vertical', actionButtons, actionButtonsPosition = 'overlay-top-right', showActionLabels = false, }) {
|
|
9127
9848
|
const images = item.images?.length ? item.images : item.image ?? item.imageUrl ? [String(item.image ?? item.imageUrl)] : [];
|
|
@@ -9129,12 +9850,12 @@ function ItemCard({ item, position, onSelect, className, style, asLink = true, i
|
|
|
9129
9850
|
const description = item.description ?? item.secondaryText;
|
|
9130
9851
|
const href = item.url;
|
|
9131
9852
|
const isHorizontal = layout === 'horizontal';
|
|
9132
|
-
const imageBlock = images.length > 0 ? (React.createElement("div", { style: { position: 'relative', ...(isHorizontal ? {
|
|
9853
|
+
const imageBlock = images.length > 0 ? (React.createElement("div", { style: { position: 'relative', overflow: 'hidden', borderRadius: 4, ...(isHorizontal ? { minWidth: 80, flexBasis: '20%', maxWidth: 120, flexShrink: 0 } : {}) } },
|
|
9133
9854
|
React.createElement(ImageDisplay, { images: images, variant: imageVariant, alt: String(title), className: "seekora-item-card-image" }),
|
|
9134
|
-
actionButtons && actionButtons.length > 0 && actionButtonsPosition?.startsWith('overlay') && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" })))) : (React.createElement("div", { className: "seekora-item-card-placeholder", style: { ...imgStyle$1, ...(isHorizontal ? {
|
|
9855
|
+
actionButtons && actionButtons.length > 0 && actionButtonsPosition?.startsWith('overlay') && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" })))) : (React.createElement("div", { className: "seekora-item-card-placeholder", style: { ...imgStyle$1, ...(isHorizontal ? { minWidth: 80, flexBasis: '20%', maxWidth: 120, height: 80, flexShrink: 0 } : {}) }, "aria-hidden": true }));
|
|
9135
9856
|
const textBlock = (React.createElement("div", { style: isHorizontal ? { display: 'flex', flexDirection: 'column', gap: 4, flex: 1, minWidth: 0 } : undefined },
|
|
9136
|
-
React.createElement("span", { className: "seekora-item-card-title", style: { fontSize: '0.875rem', fontWeight: 500 } }, String(title)),
|
|
9137
|
-
description ? (React.createElement("span", { className: "seekora-item-card-description", style: { fontSize: '0.8125rem', color: 'var(--seekora-text-secondary, #6b7280)', lineHeight: 1.3 } }, String(description))) : null,
|
|
9857
|
+
React.createElement("span", { className: "seekora-item-card-title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, String(title)),
|
|
9858
|
+
description ? (React.createElement("span", { className: "seekora-item-card-description", style: { fontSize: '0.8125rem', color: 'var(--seekora-text-secondary, #6b7280)', lineHeight: 1.3, display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical', overflow: 'hidden' } }, String(description))) : null,
|
|
9138
9859
|
actionButtons && actionButtons.length > 0 && actionButtonsPosition === 'inline' && (React.createElement(ActionButtons, { buttons: actionButtons, position: "inline", showLabels: showActionLabels, size: "small", layout: "horizontal" }))));
|
|
9139
9860
|
const content = isHorizontal ? (React.createElement("div", { style: { display: 'flex', gap: 12, alignItems: 'flex-start' } },
|
|
9140
9861
|
imageBlock,
|
|
@@ -9165,11 +9886,12 @@ function ItemCard({ item, position, onSelect, className, style, asLink = true, i
|
|
|
9165
9886
|
* or custom renderItem. Use for search hits, section blocks, docs, articles; for
|
|
9166
9887
|
* product-only lists use ProductGrid.
|
|
9167
9888
|
*/
|
|
9889
|
+
const SPACING$1 = {
|
|
9890
|
+
md: 12};
|
|
9168
9891
|
const defaultGridStyle = {
|
|
9169
9892
|
display: 'grid',
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
padding: 12,
|
|
9893
|
+
gap: SPACING$1.md,
|
|
9894
|
+
padding: SPACING$1.md,
|
|
9173
9895
|
};
|
|
9174
9896
|
function toGenericItem(item, getItemId, getItemTitle, getItemImage, getItemDescription, getItemUrl) {
|
|
9175
9897
|
return {
|
|
@@ -9766,19 +10488,24 @@ function PriceDisplay({ price, comparePrice, priceRange, currency = '$', currenc
|
|
|
9766
10488
|
/**
|
|
9767
10489
|
* BadgeList – renders product badges (sale, new, sold out, custom)
|
|
9768
10490
|
*/
|
|
10491
|
+
const SPACING = {
|
|
10492
|
+
xs: 4,
|
|
10493
|
+
sm: 8};
|
|
10494
|
+
const BORDER_RADIUS$2 = {
|
|
10495
|
+
sm: 4};
|
|
9769
10496
|
const positionStyles = {
|
|
9770
|
-
'top-left': { position: 'absolute', top:
|
|
9771
|
-
'top-right': { position: 'absolute', top:
|
|
9772
|
-
'bottom-left': { position: 'absolute', bottom:
|
|
9773
|
-
'bottom-right': { position: 'absolute', bottom:
|
|
10497
|
+
'top-left': { position: 'absolute', top: SPACING.sm, left: SPACING.sm },
|
|
10498
|
+
'top-right': { position: 'absolute', top: SPACING.sm, right: SPACING.sm },
|
|
10499
|
+
'bottom-left': { position: 'absolute', bottom: SPACING.sm, left: SPACING.sm },
|
|
10500
|
+
'bottom-right': { position: 'absolute', bottom: SPACING.sm, right: SPACING.sm },
|
|
9774
10501
|
inline: {},
|
|
9775
10502
|
};
|
|
9776
10503
|
const typeColors = {
|
|
9777
|
-
sale: { bg: '#ef4444', text: '#fff' },
|
|
9778
|
-
new: { bg: '#3b82f6', text: '#fff' },
|
|
9779
|
-
soldOut: { bg: '#6b7280', text: '#fff' },
|
|
9780
|
-
limited: { bg: '#f59e0b', text: '#fff' },
|
|
9781
|
-
custom: { bg: '#111827', text: '#fff' },
|
|
10504
|
+
sale: { bg: 'var(--seekora-badge-sale-bg, #ef4444)', text: 'var(--seekora-badge-sale-text, #fff)' },
|
|
10505
|
+
new: { bg: 'var(--seekora-badge-new-bg, #3b82f6)', text: 'var(--seekora-badge-new-text, #fff)' },
|
|
10506
|
+
soldOut: { bg: 'var(--seekora-badge-soldout-bg, #6b7280)', text: 'var(--seekora-badge-soldout-text, #fff)' },
|
|
10507
|
+
limited: { bg: 'var(--seekora-badge-limited-bg, #f59e0b)', text: 'var(--seekora-badge-limited-text, #fff)' },
|
|
10508
|
+
custom: { bg: 'var(--seekora-badge-custom-bg, #111827)', text: 'var(--seekora-badge-custom-text, #fff)' },
|
|
9782
10509
|
};
|
|
9783
10510
|
function BadgeList({ badges, maxBadges, position = 'top-left', className, style, }) {
|
|
9784
10511
|
if (!badges || badges.length === 0)
|
|
@@ -9787,8 +10514,8 @@ function BadgeList({ badges, maxBadges, position = 'top-left', className, style,
|
|
|
9787
10514
|
return (React.createElement("div", { className: clsx('seekora-badge-list', className), style: {
|
|
9788
10515
|
display: 'flex',
|
|
9789
10516
|
flexWrap: 'wrap',
|
|
9790
|
-
gap:
|
|
9791
|
-
zIndex:
|
|
10517
|
+
gap: SPACING.xs,
|
|
10518
|
+
zIndex: 2,
|
|
9792
10519
|
...positionStyles[position],
|
|
9793
10520
|
...style,
|
|
9794
10521
|
} }, visible.map((badge, i) => {
|
|
@@ -9796,10 +10523,10 @@ function BadgeList({ badges, maxBadges, position = 'top-left', className, style,
|
|
|
9796
10523
|
return (React.createElement("span", { key: `${badge.text}-${i}`, className: clsx('seekora-badge', badge.type && `seekora-badge--${badge.type === 'soldOut' ? 'sold-out' : badge.type}`), style: {
|
|
9797
10524
|
display: 'inline-block',
|
|
9798
10525
|
padding: '2px 8px',
|
|
9799
|
-
borderRadius:
|
|
10526
|
+
borderRadius: BORDER_RADIUS$2.sm,
|
|
9800
10527
|
fontSize: '0.6875rem',
|
|
9801
10528
|
fontWeight: 600,
|
|
9802
|
-
lineHeight: 1.
|
|
10529
|
+
lineHeight: 1.2,
|
|
9803
10530
|
backgroundColor: badge.color ?? colors.bg,
|
|
9804
10531
|
color: badge.textColor ?? colors.text,
|
|
9805
10532
|
whiteSpace: 'nowrap',
|
|
@@ -10029,7 +10756,7 @@ function VariantSwatches({ options, visibleOptions, maxValues = 5, colorMap, sel
|
|
|
10029
10756
|
outlineOffset: 2,
|
|
10030
10757
|
cursor: onSwatchClick && isAvailable ? 'pointer' : 'not-allowed',
|
|
10031
10758
|
flexShrink: 0,
|
|
10032
|
-
boxShadow: isSelected ? '0 0 0 1px #fff' : 'none',
|
|
10759
|
+
boxShadow: isSelected ? 'var(--seekora-swatch-ring, 0 0 0 1px #fff)' : 'none',
|
|
10033
10760
|
opacity: isAvailable ? 1 : 0.3,
|
|
10034
10761
|
position: 'relative',
|
|
10035
10762
|
}, onMouseEnter: () => isAvailable && onSwatchHover?.(option.name, value), onMouseDown: (e) => {
|
|
@@ -10046,7 +10773,7 @@ function VariantSwatches({ options, visibleOptions, maxValues = 5, colorMap, sel
|
|
|
10046
10773
|
left: '-2px',
|
|
10047
10774
|
right: '-2px',
|
|
10048
10775
|
height: 1,
|
|
10049
|
-
backgroundColor: '#ef4444',
|
|
10776
|
+
backgroundColor: 'var(--seekora-unavailable-line, #ef4444)',
|
|
10050
10777
|
transform: 'translateY(-50%) rotate(-45deg)',
|
|
10051
10778
|
} }))));
|
|
10052
10779
|
}
|
|
@@ -10062,7 +10789,7 @@ function VariantSwatches({ options, visibleOptions, maxValues = 5, colorMap, sel
|
|
|
10062
10789
|
? 'var(--seekora-primary, #111827)'
|
|
10063
10790
|
: 'transparent',
|
|
10064
10791
|
color: isSelected
|
|
10065
|
-
? '#fff'
|
|
10792
|
+
? 'var(--seekora-primary-text, #fff)'
|
|
10066
10793
|
: 'var(--seekora-text-secondary, #6b7280)',
|
|
10067
10794
|
cursor: onSwatchClick && isAvailable ? 'pointer' : 'not-allowed',
|
|
10068
10795
|
whiteSpace: 'nowrap',
|
|
@@ -10098,17 +10825,21 @@ function VariantSwatches({ options, visibleOptions, maxValues = 5, colorMap, sel
|
|
|
10098
10825
|
* Not exported from the package. Each layout renders the same product data
|
|
10099
10826
|
* with different visual emphasis.
|
|
10100
10827
|
*/
|
|
10828
|
+
const BORDER_RADIUS$1 = {
|
|
10829
|
+
sm: 4};
|
|
10101
10830
|
const imgPlaceholderStyle = {
|
|
10102
10831
|
width: '100%',
|
|
10103
10832
|
aspectRatio: '1',
|
|
10104
10833
|
objectFit: 'cover',
|
|
10105
|
-
borderRadius:
|
|
10834
|
+
borderRadius: BORDER_RADIUS$1.sm,
|
|
10106
10835
|
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
10107
10836
|
};
|
|
10108
10837
|
function ImageBlock({ images, title, imageVariant, aspectRatio, enableZoom, zoomMode, zoomLevel }) {
|
|
10109
|
-
const ar = aspectRatio
|
|
10838
|
+
const ar = aspectRatio
|
|
10839
|
+
? (aspectRatio.includes(':') ? aspectRatio.replace(':', '/') : aspectRatio)
|
|
10840
|
+
: '1';
|
|
10110
10841
|
if (images.length > 0) {
|
|
10111
|
-
return (React.createElement("div", { className: "seekora-product-card__image", style: { position: 'relative', overflow: 'hidden', borderRadius:
|
|
10842
|
+
return (React.createElement("div", { className: "seekora-product-card__image", style: { position: 'relative', overflow: 'hidden', borderRadius: BORDER_RADIUS$1.sm } },
|
|
10112
10843
|
React.createElement(ImageDisplay, { images: images, variant: images.length > 1 ? imageVariant : 'single', alt: title, className: "seekora-suggestions-product-card-image", style: { aspectRatio: ar }, enableZoom: enableZoom, zoomMode: zoomMode, zoomLevel: zoomLevel })));
|
|
10113
10844
|
}
|
|
10114
10845
|
return React.createElement("div", { className: "seekora-product-card__image seekora-suggestions-product-card-placeholder", style: { ...imgPlaceholderStyle, aspectRatio: ar }, "aria-hidden": true });
|
|
@@ -10117,7 +10848,7 @@ function ImageBlock({ images, title, imageVariant, aspectRatio, enableZoom, zoom
|
|
|
10117
10848
|
function MinimalLayout({ images, title, price, product, imageVariant, displayConfig, enableImageZoom, imageZoomMode, imageZoomLevel }) {
|
|
10118
10849
|
return (React.createElement(React.Fragment, null,
|
|
10119
10850
|
React.createElement(ImageBlock, { images: images, title: title, imageVariant: imageVariant, aspectRatio: displayConfig.imageAspectRatio, enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel }),
|
|
10120
|
-
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
10851
|
+
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis' } }, title),
|
|
10121
10852
|
price != null && !Number.isNaN(price) && (React.createElement("span", { className: "seekora-product-card__price seekora-suggestions-product-card-price", style: { fontSize: '0.875rem', color: 'var(--seekora-text-secondary, #6b7280)' } },
|
|
10122
10853
|
product.currency ?? '$',
|
|
10123
10854
|
price.toFixed(2)))));
|
|
@@ -10125,31 +10856,35 @@ function MinimalLayout({ images, title, price, product, imageVariant, displayCon
|
|
|
10125
10856
|
/** standard: image, badges, brand, title, price + compare price, color swatches */
|
|
10126
10857
|
function StandardLayout({ images, title, price, comparePrice, brand, badges, options, variants, product, imageVariant, displayConfig, onVariantHover, onVariantClick, selectedVariants, actionButtons, actionButtonsPosition, showActionLabels, enableImageZoom, imageZoomMode, imageZoomLevel, }) {
|
|
10127
10858
|
const cfg = displayConfig;
|
|
10859
|
+
// Normalize position: 'overlay-*' positions render over image, everything else renders inline
|
|
10860
|
+
const isOverlayPosition = actionButtonsPosition?.startsWith('overlay');
|
|
10128
10861
|
return (React.createElement(React.Fragment, null,
|
|
10129
10862
|
React.createElement("div", { style: { position: 'relative' } },
|
|
10130
10863
|
React.createElement(ImageBlock, { images: images, title: title, imageVariant: imageVariant, aspectRatio: cfg.imageAspectRatio, enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel }),
|
|
10131
10864
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left", maxBadges: 2 })),
|
|
10132
|
-
actionButtons && actionButtons.length > 0 &&
|
|
10865
|
+
actionButtons && actionButtons.length > 0 && isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
10133
10866
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: 4 } },
|
|
10134
10867
|
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: '0.75rem', color: 'var(--seekora-text-secondary, #6b7280)', textTransform: 'uppercase', letterSpacing: '0.02em' } }, brand)),
|
|
10135
|
-
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
10868
|
+
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis' } }, title),
|
|
10136
10869
|
React.createElement("div", { className: "seekora-product-card__price" },
|
|
10137
10870
|
React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: '0.875rem' } })),
|
|
10138
10871
|
cfg.showVariants !== false && options.length > 0 && (React.createElement(VariantSwatches, { options: options, visibleOptions: cfg.variantOptionsToShow, maxValues: cfg.maxVariantValues, selectedValues: selectedVariants, variants: variants, onSwatchHover: onVariantHover, onSwatchClick: onVariantClick })),
|
|
10139
|
-
actionButtons && actionButtons.length > 0 &&
|
|
10872
|
+
actionButtons && actionButtons.length > 0 && !isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: "inline", showLabels: showActionLabels, size: "small", layout: "horizontal" })))));
|
|
10140
10873
|
}
|
|
10141
10874
|
/** detailed: image, badges, brand, title, price + compare + discount, rating, all swatches, stock */
|
|
10142
10875
|
function DetailedLayout({ images, title, price, comparePrice, brand, badges, priceRange, options, variants, product, imageVariant, displayConfig, onVariantHover, onVariantClick, selectedVariants, actionButtons, actionButtonsPosition, showActionLabels, enableImageZoom, imageZoomMode, imageZoomLevel, }) {
|
|
10143
10876
|
const cfg = displayConfig;
|
|
10144
10877
|
const available = product.available;
|
|
10878
|
+
// Normalize position: 'overlay-*' positions render over image, everything else renders inline
|
|
10879
|
+
const isOverlayPosition = actionButtonsPosition?.startsWith('overlay');
|
|
10145
10880
|
return (React.createElement(React.Fragment, null,
|
|
10146
10881
|
React.createElement("div", { style: { position: 'relative' } },
|
|
10147
10882
|
React.createElement(ImageBlock, { images: images, title: title, imageVariant: imageVariant, aspectRatio: cfg.imageAspectRatio, enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel }),
|
|
10148
10883
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left" })),
|
|
10149
|
-
actionButtons && actionButtons.length > 0 &&
|
|
10884
|
+
actionButtons && actionButtons.length > 0 && isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
10150
10885
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: 4 } },
|
|
10151
10886
|
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: '0.75rem', color: 'var(--seekora-text-secondary, #6b7280)', textTransform: 'uppercase', letterSpacing: '0.02em' } }, brand)),
|
|
10152
|
-
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
10887
|
+
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis' } }, title),
|
|
10153
10888
|
cfg.showRating !== false && product.rating != null && (React.createElement(RatingDisplay, { rating: product.rating, reviewCount: product.reviewCount, variant: "compact", size: "small", showNumeric: false, showReviewCount: true, className: "seekora-product-card__rating" })),
|
|
10154
10889
|
React.createElement("div", { className: "seekora-product-card__price" }, cfg.showPriceRange && priceRange ? (React.createElement(PriceDisplay, { priceRange: priceRange, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, style: { fontSize: '0.875rem' } })) : (React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: '0.875rem' } }))),
|
|
10155
10890
|
cfg.showVariants !== false && options.length > 0 && (React.createElement(VariantSwatches, { options: options, visibleOptions: cfg.variantOptionsToShow, maxValues: cfg.maxVariantValues, selectedValues: selectedVariants, variants: variants, onSwatchHover: onVariantHover, onSwatchClick: onVariantClick })),
|
|
@@ -10157,7 +10892,7 @@ function DetailedLayout({ images, title, price, comparePrice, brand, badges, pri
|
|
|
10157
10892
|
fontSize: '0.75rem',
|
|
10158
10893
|
color: available ? 'var(--seekora-success, #22c55e)' : 'var(--seekora-error, #ef4444)',
|
|
10159
10894
|
} }, available ? 'In Stock' : 'Out of Stock')),
|
|
10160
|
-
actionButtons && actionButtons.length > 0 &&
|
|
10895
|
+
actionButtons && actionButtons.length > 0 && !isOverlayPosition && (React.createElement(ActionButtons, { buttons: actionButtons, position: "inline", showLabels: showActionLabels, size: "small", layout: "horizontal" })))));
|
|
10161
10896
|
}
|
|
10162
10897
|
/** compact: smaller image, 1-line title, price */
|
|
10163
10898
|
function CompactLayout({ images, title, price, product, imageVariant, displayConfig, enableImageZoom, imageZoomMode, imageZoomLevel }) {
|
|
@@ -10178,13 +10913,13 @@ function CompactLayout({ images, title, price, product, imageVariant, displayCon
|
|
|
10178
10913
|
function HorizontalLayout({ images, title, price, comparePrice, brand, badges, options, variants, product, imageVariant, displayConfig, onVariantHover, onVariantClick, selectedVariants, actionButtons, actionButtonsPosition, showActionLabels, enableImageZoom, imageZoomMode, imageZoomLevel, }) {
|
|
10179
10914
|
const cfg = displayConfig;
|
|
10180
10915
|
return (React.createElement("div", { style: { display: 'flex', gap: 12, alignItems: 'flex-start' } },
|
|
10181
|
-
React.createElement("div", { style: { position: 'relative',
|
|
10916
|
+
React.createElement("div", { style: { position: 'relative', minWidth: 80, flexBasis: '25%', maxWidth: 120, flexShrink: 0 } },
|
|
10182
10917
|
React.createElement(ImageBlock, { images: images, title: title, imageVariant: imageVariant, aspectRatio: "1:1", enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel }),
|
|
10183
10918
|
cfg.showBadges !== false && badges.length > 0 && (React.createElement(BadgeList, { badges: badges, position: "top-left", maxBadges: 1 })),
|
|
10184
10919
|
actionButtons && actionButtons.length > 0 && actionButtonsPosition?.startsWith('overlay') && (React.createElement(ActionButtons, { buttons: actionButtons, position: actionButtonsPosition === 'overlay-top-right' ? 'top-right' : 'bottom-center', showLabels: showActionLabels, size: "small" }))),
|
|
10185
10920
|
React.createElement("div", { className: "seekora-product-card__body", style: { display: 'flex', flexDirection: 'column', gap: 4, flex: 1, minWidth: 0 } },
|
|
10186
10921
|
cfg.showBrand !== false && brand && (React.createElement("span", { className: "seekora-product-card__brand", style: { fontSize: '0.75rem', color: 'var(--seekora-text-secondary, #6b7280)', textTransform: 'uppercase' } }, brand)),
|
|
10187
|
-
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
10922
|
+
React.createElement("span", { className: "seekora-product-card__title", style: { fontSize: '0.875rem', fontWeight: 500, lineHeight: 1.4, overflow: 'hidden', textOverflow: 'ellipsis' } }, title),
|
|
10188
10923
|
React.createElement("div", { className: "seekora-product-card__price" },
|
|
10189
10924
|
React.createElement(PriceDisplay, { price: price ?? undefined, comparePrice: comparePrice ?? undefined, currency: cfg.currency ?? product.currency, currencyPosition: cfg.currencyPosition, priceDecimals: cfg.priceDecimals, showDiscount: cfg.showDiscount, style: { fontSize: '0.875rem' } })),
|
|
10190
10925
|
cfg.showVariants !== false && options.length > 0 && (React.createElement(VariantSwatches, { options: options, visibleOptions: cfg.variantOptionsToShow, maxValues: cfg.maxVariantValues ?? 3, selectedValues: selectedVariants, variants: variants, onSwatchHover: onVariantHover, onSwatchClick: onVariantClick })),
|
|
@@ -10197,6 +10932,11 @@ function HorizontalLayout({ images, title, price, comparePrice, brand, badges, o
|
|
|
10197
10932
|
* Without displayConfig: renders the original minimal layout (image, title, price).
|
|
10198
10933
|
* With displayConfig: renders layout variants (minimal, standard, detailed, compact, horizontal).
|
|
10199
10934
|
*/
|
|
10935
|
+
const TRANSITIONS = {
|
|
10936
|
+
fast: '150ms ease-in-out'};
|
|
10937
|
+
const BORDER_RADIUS = {
|
|
10938
|
+
sm: 4,
|
|
10939
|
+
md: 6};
|
|
10200
10940
|
const cardStyle = {
|
|
10201
10941
|
display: 'flex',
|
|
10202
10942
|
flexDirection: 'column',
|
|
@@ -10204,19 +10944,19 @@ const cardStyle = {
|
|
|
10204
10944
|
padding: 8,
|
|
10205
10945
|
cursor: 'pointer',
|
|
10206
10946
|
border: 'none',
|
|
10207
|
-
borderRadius:
|
|
10947
|
+
borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS.md}px)`,
|
|
10208
10948
|
backgroundColor: 'transparent',
|
|
10209
10949
|
textAlign: 'left',
|
|
10210
|
-
transition:
|
|
10950
|
+
transition: `background-color ${TRANSITIONS.fast}`,
|
|
10211
10951
|
};
|
|
10212
10952
|
const imgStyle = {
|
|
10213
10953
|
width: '100%',
|
|
10214
10954
|
aspectRatio: '1',
|
|
10215
10955
|
objectFit: 'cover',
|
|
10216
|
-
borderRadius:
|
|
10956
|
+
borderRadius: BORDER_RADIUS.sm,
|
|
10217
10957
|
backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
|
|
10218
10958
|
};
|
|
10219
|
-
function ProductCard({ product, position, section, tabId, onSelect, className, style, imageVariant = 'single', displayConfig, onVariantHover, onVariantClick, selectedVariants, asLink, actionButtons, actionButtonsPosition = '
|
|
10959
|
+
function ProductCard({ product, position, section, tabId, onSelect, className, style, imageVariant = 'single', displayConfig, onVariantHover, onVariantClick, selectedVariants, asLink, actionButtons, actionButtonsPosition = 'inline', showActionLabels = false, enableImageZoom = false, imageZoomMode = 'both', imageZoomLevel = 2.5, }) {
|
|
10220
10960
|
// Find selected variant if selections are provided
|
|
10221
10961
|
const selectedVariant = React.useMemo(() => {
|
|
10222
10962
|
if (!selectedVariants || !product.options || !product.variants)
|
|
@@ -10261,9 +11001,11 @@ function ProductCard({ product, position, section, tabId, onSelect, className, s
|
|
|
10261
11001
|
const price = effectivePrice;
|
|
10262
11002
|
// If no displayConfig, render original minimal layout (backwards compat)
|
|
10263
11003
|
if (!displayConfig) {
|
|
10264
|
-
return (React.createElement("
|
|
10265
|
-
e.
|
|
10266
|
-
|
|
11004
|
+
return (React.createElement("div", { role: "button", tabIndex: 0, className: clsx('seekora-suggestions-product-card', className), style: { ...cardStyle, ...style }, onClick: () => onSelect(), onKeyDown: (e) => {
|
|
11005
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
11006
|
+
e.preventDefault();
|
|
11007
|
+
onSelect();
|
|
11008
|
+
}
|
|
10267
11009
|
}, "data-position": position, "data-section": section, "data-tab-id": tabId },
|
|
10268
11010
|
images.length > 0 ? (React.createElement(ImageDisplay, { images: images, variant: imageVariant, alt: title, className: "seekora-suggestions-product-card-image", enableZoom: enableImageZoom, zoomMode: imageZoomMode, zoomLevel: imageZoomLevel })) : (React.createElement("div", { className: "seekora-suggestions-product-card-placeholder", style: imgStyle, "aria-hidden": true })),
|
|
10269
11011
|
React.createElement("span", { className: "seekora-suggestions-product-card-title", style: { fontSize: '0.875rem', fontWeight: 500 } }, title),
|
|
@@ -10333,9 +11075,11 @@ function ProductCard({ product, position, section, tabId, onSelect, className, s
|
|
|
10333
11075
|
}, "data-position": position, "data-section": section, "data-tab-id": tabId },
|
|
10334
11076
|
React.createElement(LayoutComponent, { ...layoutProps })));
|
|
10335
11077
|
}
|
|
10336
|
-
return (React.createElement("
|
|
10337
|
-
e.
|
|
10338
|
-
|
|
11078
|
+
return (React.createElement("div", { role: "button", tabIndex: 0, className: rootClassName, style: rootStyle, onClick: () => onSelect(), onKeyDown: (e) => {
|
|
11079
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
11080
|
+
e.preventDefault();
|
|
11081
|
+
onSelect();
|
|
11082
|
+
}
|
|
10339
11083
|
}, "data-position": position, "data-section": section, "data-tab-id": tabId },
|
|
10340
11084
|
React.createElement(LayoutComponent, { ...layoutProps })));
|
|
10341
11085
|
}
|
|
@@ -10611,10 +11355,10 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
10611
11355
|
fontSize: '0.875rem',
|
|
10612
11356
|
fontWeight: 600,
|
|
10613
11357
|
marginBottom: 8,
|
|
10614
|
-
color: 'var(--seekora-text-primary,
|
|
11358
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
10615
11359
|
} },
|
|
10616
11360
|
option.name,
|
|
10617
|
-
selected && (React.createElement("span", { style: { fontWeight: 400, marginLeft: 6, color: 'var(--seekora-text-secondary,
|
|
11361
|
+
selected && (React.createElement("span", { style: { fontWeight: 400, marginLeft: 6, color: 'var(--seekora-text-secondary, inherit)' } }, selected))),
|
|
10618
11362
|
mode === 'dropdown' ? (React.createElement("select", { className: "seekora-variant-dropdown", value: selected ?? '', onChange: (e) => {
|
|
10619
11363
|
e.stopPropagation();
|
|
10620
11364
|
onSelectionChange(option.name, e.target.value);
|
|
@@ -10622,9 +11366,9 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
10622
11366
|
padding: '8px 12px',
|
|
10623
11367
|
fontSize: '0.875rem',
|
|
10624
11368
|
borderRadius: 6,
|
|
10625
|
-
border: '1px solid var(--seekora-border-color,
|
|
10626
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
10627
|
-
color: 'var(--seekora-text-primary,
|
|
11369
|
+
border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
11370
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
11371
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
10628
11372
|
cursor: 'pointer',
|
|
10629
11373
|
minWidth: 120,
|
|
10630
11374
|
} },
|
|
@@ -10658,7 +11402,7 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
10658
11402
|
backgroundColor: color,
|
|
10659
11403
|
border: isActive
|
|
10660
11404
|
? '2px solid var(--seekora-primary, #111827)'
|
|
10661
|
-
: '1px solid var(--seekora-border-color,
|
|
11405
|
+
: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
10662
11406
|
outline: isActive ? '2px solid var(--seekora-primary, #111827)' : 'none',
|
|
10663
11407
|
outlineOffset: 2,
|
|
10664
11408
|
cursor: available ? 'pointer' : 'not-allowed',
|
|
@@ -10679,13 +11423,13 @@ function VariantSelector({ options, variants, selections, onSelectionChange, opt
|
|
|
10679
11423
|
borderRadius: 6,
|
|
10680
11424
|
border: isActive
|
|
10681
11425
|
? '2px solid var(--seekora-primary, #111827)'
|
|
10682
|
-
: '1px solid var(--seekora-border-color,
|
|
11426
|
+
: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
10683
11427
|
backgroundColor: isActive
|
|
10684
11428
|
? 'var(--seekora-primary, #111827)'
|
|
10685
|
-
: 'var(--seekora-bg-surface,
|
|
11429
|
+
: 'var(--seekora-bg-surface, transparent)',
|
|
10686
11430
|
color: isActive
|
|
10687
|
-
? '
|
|
10688
|
-
: 'var(--seekora-text-primary,
|
|
11431
|
+
? 'transparent'
|
|
11432
|
+
: 'var(--seekora-text-primary, inherit)',
|
|
10689
11433
|
cursor: available ? 'pointer' : 'not-allowed',
|
|
10690
11434
|
opacity: available ? 1 : 0.5,
|
|
10691
11435
|
textDecoration: !available ? 'line-through' : 'none',
|
|
@@ -10904,7 +11648,7 @@ function extractTotal(response) {
|
|
|
10904
11648
|
return Number(data.data.total_results);
|
|
10905
11649
|
return 0;
|
|
10906
11650
|
}
|
|
10907
|
-
function SectionSearchProvider({ children, query, refinements = [], maxItems = 12, sortBy, enabled = true, sectionId, }) {
|
|
11651
|
+
function SectionSearchProvider({ children, query, refinements = [], maxItems = 12, sortBy, enabled = true, sectionId, searchOptions, }) {
|
|
10908
11652
|
const { client } = useSearchContext();
|
|
10909
11653
|
const [items, setItems] = React.useState([]);
|
|
10910
11654
|
const [loading, setLoading] = React.useState(true);
|
|
@@ -10922,6 +11666,7 @@ function SectionSearchProvider({ children, query, refinements = [], maxItems = 1
|
|
|
10922
11666
|
setLoading(true);
|
|
10923
11667
|
setError(null);
|
|
10924
11668
|
const options = {
|
|
11669
|
+
...searchOptions,
|
|
10925
11670
|
per_page: maxItems,
|
|
10926
11671
|
page: 1,
|
|
10927
11672
|
};
|
|
@@ -10949,7 +11694,7 @@ function SectionSearchProvider({ children, query, refinements = [], maxItems = 1
|
|
|
10949
11694
|
return () => {
|
|
10950
11695
|
cancelled = true;
|
|
10951
11696
|
};
|
|
10952
|
-
}, [client, enabled, query, maxItems, sortBy, refinements]);
|
|
11697
|
+
}, [client, enabled, query, maxItems, sortBy, refinements, searchOptions]);
|
|
10953
11698
|
const trackClick = React.useCallback((item, position) => {
|
|
10954
11699
|
if (!client?.trackEvent)
|
|
10955
11700
|
return;
|
|
@@ -11014,9 +11759,9 @@ function SectionItemGrid({ columns = 4, maxItems = 12, className, style, showLoa
|
|
|
11014
11759
|
* Uses ImageDisplay with configurable variant (carousel, thumbStrip, etc.).
|
|
11015
11760
|
* For use on individual product page.
|
|
11016
11761
|
*/
|
|
11017
|
-
function ProductGallery({ images, variant = 'thumbStrip', alt = 'Product', className, style, carouselAutoplay, carouselIntervalMs, }) {
|
|
11762
|
+
function ProductGallery({ images, variant = 'thumbStrip', alt = 'Product', className, style, carouselAutoplay, carouselIntervalMs, enableZoom, zoomMode, zoomLevel, }) {
|
|
11018
11763
|
return (React.createElement("div", { className: clsx('seekora-product-gallery', className), style: style },
|
|
11019
|
-
React.createElement(ImageDisplay, { images: images, variant: variant, alt: alt, carouselAutoplay: carouselAutoplay, carouselIntervalMs: carouselIntervalMs })));
|
|
11764
|
+
React.createElement(ImageDisplay, { images: images, variant: variant, alt: alt, carouselAutoplay: carouselAutoplay, carouselIntervalMs: carouselIntervalMs, enableZoom: enableZoom, zoomMode: zoomMode, zoomLevel: zoomLevel })));
|
|
11020
11765
|
}
|
|
11021
11766
|
|
|
11022
11767
|
/**
|
|
@@ -13320,8 +14065,8 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13320
14065
|
right: 0,
|
|
13321
14066
|
bottom: isMobile ? 0 : 'auto',
|
|
13322
14067
|
marginTop: isMobile ? 0 : '8px',
|
|
13323
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
13324
|
-
color: 'var(--seekora-text-primary,
|
|
14068
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
14069
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13325
14070
|
borderRadius: isMobile ? 0 : '16px',
|
|
13326
14071
|
boxShadow: isMobile ? 'none' : '0 4px 30px rgba(0, 0, 0, 0.12)',
|
|
13327
14072
|
overflow: 'hidden',
|
|
@@ -13339,14 +14084,14 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13339
14084
|
overflowY: 'auto',
|
|
13340
14085
|
},
|
|
13341
14086
|
leftPanel: {
|
|
13342
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
13343
|
-
borderRight: isMobile ? 'none' : '1px solid var(--seekora-border-color,
|
|
13344
|
-
borderBottom: isMobile ? '1px solid var(--seekora-border-color,
|
|
14087
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
14088
|
+
borderRight: isMobile ? 'none' : '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
14089
|
+
borderBottom: isMobile ? '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))' : 'none',
|
|
13345
14090
|
display: 'flex',
|
|
13346
14091
|
flexDirection: 'column',
|
|
13347
14092
|
},
|
|
13348
14093
|
rightPanel: {
|
|
13349
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
14094
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
13350
14095
|
padding: isMobile ? '16px' : '24px',
|
|
13351
14096
|
display: 'flex',
|
|
13352
14097
|
flexDirection: 'column',
|
|
@@ -13361,7 +14106,7 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13361
14106
|
display: 'flex',
|
|
13362
14107
|
alignItems: 'center',
|
|
13363
14108
|
justifyContent: 'space-between',
|
|
13364
|
-
borderBottom: '1px solid var(--seekora-border-color,
|
|
14109
|
+
borderBottom: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
13365
14110
|
},
|
|
13366
14111
|
sectionTitle: {
|
|
13367
14112
|
fontSize: '11px',
|
|
@@ -13372,7 +14117,7 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13372
14117
|
},
|
|
13373
14118
|
viewAllLink: {
|
|
13374
14119
|
fontSize: '12px',
|
|
13375
|
-
color: 'var(--seekora-text-primary,
|
|
14120
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13376
14121
|
textDecoration: 'underline',
|
|
13377
14122
|
cursor: 'pointer',
|
|
13378
14123
|
},
|
|
@@ -13386,11 +14131,11 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13386
14131
|
minHeight: '48px',
|
|
13387
14132
|
margin: '4px 8px',
|
|
13388
14133
|
borderRadius: '10px',
|
|
13389
|
-
color: 'var(--seekora-text-primary,
|
|
14134
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13390
14135
|
},
|
|
13391
14136
|
suggestionItemActive: {
|
|
13392
|
-
backgroundColor: 'var(--seekora-bg-hover,
|
|
13393
|
-
color: 'var(--seekora-text-primary,
|
|
14137
|
+
backgroundColor: 'var(--seekora-bg-hover, rgba(255, 255, 255, 0.1))',
|
|
14138
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13394
14139
|
},
|
|
13395
14140
|
suggestionIcon: {
|
|
13396
14141
|
display: 'flex',
|
|
@@ -13405,12 +14150,12 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13405
14150
|
},
|
|
13406
14151
|
suggestionQuery: {
|
|
13407
14152
|
fontSize: '14px',
|
|
13408
|
-
color: 'var(--seekora-text-primary,
|
|
14153
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13409
14154
|
fontWeight: 400,
|
|
13410
14155
|
},
|
|
13411
14156
|
suggestionMeta: {
|
|
13412
14157
|
fontSize: '12px',
|
|
13413
|
-
color: 'var(--seekora-text-secondary,
|
|
14158
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13414
14159
|
marginTop: '2px',
|
|
13415
14160
|
},
|
|
13416
14161
|
suggestionArrow: {
|
|
@@ -13428,29 +14173,29 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13428
14173
|
display: 'grid',
|
|
13429
14174
|
gridTemplateColumns: 'repeat(2, 1fr)',
|
|
13430
14175
|
gap: '1px',
|
|
13431
|
-
backgroundColor: 'var(--seekora-border-color,
|
|
13432
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
14176
|
+
backgroundColor: 'var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
14177
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
13433
14178
|
},
|
|
13434
14179
|
collectionItem: {
|
|
13435
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
13436
|
-
color: 'var(--seekora-text-primary,
|
|
14180
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
14181
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13437
14182
|
padding: '16px 20px',
|
|
13438
14183
|
cursor: 'pointer',
|
|
13439
14184
|
transition: 'background-color 150ms',
|
|
13440
14185
|
},
|
|
13441
14186
|
collectionItemHover: {
|
|
13442
|
-
backgroundColor: 'var(--seekora-bg-hover,
|
|
13443
|
-
color: 'var(--seekora-text-primary,
|
|
14187
|
+
backgroundColor: 'var(--seekora-bg-hover, rgba(255, 255, 255, 0.1))',
|
|
14188
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13444
14189
|
},
|
|
13445
14190
|
collectionName: {
|
|
13446
14191
|
fontSize: '13px',
|
|
13447
14192
|
fontWeight: 500,
|
|
13448
|
-
color: 'var(--seekora-text-primary,
|
|
14193
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13449
14194
|
marginBottom: '4px',
|
|
13450
14195
|
},
|
|
13451
14196
|
collectionCount: {
|
|
13452
14197
|
fontSize: '11px',
|
|
13453
|
-
color: 'var(--seekora-text-secondary,
|
|
14198
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13454
14199
|
},
|
|
13455
14200
|
heroProduct: {
|
|
13456
14201
|
marginBottom: '24px',
|
|
@@ -13466,13 +14211,13 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13466
14211
|
heroTitle: {
|
|
13467
14212
|
fontSize: '16px',
|
|
13468
14213
|
fontWeight: 500,
|
|
13469
|
-
color: 'var(--seekora-text-primary,
|
|
14214
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13470
14215
|
marginBottom: '8px',
|
|
13471
14216
|
lineHeight: 1.3,
|
|
13472
14217
|
},
|
|
13473
14218
|
heroBrand: {
|
|
13474
14219
|
fontSize: '12px',
|
|
13475
|
-
color: 'var(--seekora-text-secondary,
|
|
14220
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13476
14221
|
marginBottom: '12px',
|
|
13477
14222
|
textTransform: 'uppercase',
|
|
13478
14223
|
letterSpacing: '0.05em',
|
|
@@ -13486,7 +14231,7 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13486
14231
|
heroPrice: {
|
|
13487
14232
|
fontSize: '18px',
|
|
13488
14233
|
fontWeight: 500,
|
|
13489
|
-
color: 'var(--seekora-text-primary,
|
|
14234
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13490
14235
|
},
|
|
13491
14236
|
heroComparePrice: {
|
|
13492
14237
|
fontSize: '14px',
|
|
@@ -13504,8 +14249,8 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13504
14249
|
heroButton: {
|
|
13505
14250
|
width: '100%',
|
|
13506
14251
|
padding: '14px 20px',
|
|
13507
|
-
backgroundColor: 'var(--seekora-text-primary,
|
|
13508
|
-
color: 'var(--seekora-bg-surface,
|
|
14252
|
+
backgroundColor: 'var(--seekora-text-primary, inherit)',
|
|
14253
|
+
color: 'var(--seekora-bg-surface, transparent)',
|
|
13509
14254
|
border: 'none',
|
|
13510
14255
|
borderRadius: '2px',
|
|
13511
14256
|
fontSize: '13px',
|
|
@@ -13516,8 +14261,8 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13516
14261
|
transition: 'background-color 150ms',
|
|
13517
14262
|
},
|
|
13518
14263
|
heroButtonHover: {
|
|
13519
|
-
backgroundColor: 'var(--seekora-text-secondary,
|
|
13520
|
-
color: 'var(--seekora-bg-surface,
|
|
14264
|
+
backgroundColor: 'var(--seekora-text-secondary, inherit)',
|
|
14265
|
+
color: 'var(--seekora-bg-surface, transparent)',
|
|
13521
14266
|
},
|
|
13522
14267
|
productsScroll: {
|
|
13523
14268
|
flex: 1,
|
|
@@ -13545,7 +14290,7 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13545
14290
|
},
|
|
13546
14291
|
productTitle: {
|
|
13547
14292
|
fontSize: '12px',
|
|
13548
|
-
color: 'var(--seekora-text-primary,
|
|
14293
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13549
14294
|
marginBottom: '4px',
|
|
13550
14295
|
whiteSpace: 'nowrap',
|
|
13551
14296
|
overflow: 'hidden',
|
|
@@ -13554,20 +14299,20 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13554
14299
|
productPrice: {
|
|
13555
14300
|
fontSize: '12px',
|
|
13556
14301
|
fontWeight: 500,
|
|
13557
|
-
color: 'var(--seekora-text-primary,
|
|
14302
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13558
14303
|
},
|
|
13559
14304
|
footer: {
|
|
13560
14305
|
padding: '12px 20px',
|
|
13561
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
13562
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
14306
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
14307
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
13563
14308
|
display: 'flex',
|
|
13564
14309
|
alignItems: 'center',
|
|
13565
14310
|
justifyContent: 'space-between',
|
|
13566
14311
|
fontSize: '11px',
|
|
13567
|
-
color: 'var(--seekora-text-secondary,
|
|
14312
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13568
14313
|
},
|
|
13569
14314
|
footerLink: {
|
|
13570
|
-
color: 'var(--seekora-text-primary,
|
|
14315
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13571
14316
|
textDecoration: 'underline',
|
|
13572
14317
|
cursor: 'pointer',
|
|
13573
14318
|
},
|
|
@@ -13576,13 +14321,13 @@ const createStyles$3 = (isMobile = false) => ({
|
|
|
13576
14321
|
alignItems: 'center',
|
|
13577
14322
|
justifyContent: 'center',
|
|
13578
14323
|
padding: '60px',
|
|
13579
|
-
color: 'var(--seekora-text-secondary,
|
|
14324
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13580
14325
|
},
|
|
13581
14326
|
spinner: {
|
|
13582
14327
|
width: '24px',
|
|
13583
14328
|
height: '24px',
|
|
13584
|
-
border: '2px solid var(--seekora-border-color,
|
|
13585
|
-
borderTopColor: 'var(--seekora-text-primary,
|
|
14329
|
+
border: '2px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
14330
|
+
borderTopColor: 'var(--seekora-text-primary, inherit)',
|
|
13586
14331
|
borderRadius: '50%',
|
|
13587
14332
|
animation: 'seekora-spin 0.8s linear infinite',
|
|
13588
14333
|
},
|
|
@@ -13773,7 +14518,7 @@ const createStyles$2 = () => ({
|
|
|
13773
14518
|
left: 0,
|
|
13774
14519
|
right: 0,
|
|
13775
14520
|
bottom: 0,
|
|
13776
|
-
backgroundColor: 'var(--seekora-bg-surface,
|
|
14521
|
+
backgroundColor: 'var(--seekora-bg-surface, transparent)',
|
|
13777
14522
|
borderRadius: '16px 16px 0 0',
|
|
13778
14523
|
boxShadow: '0 -4px 20px rgba(0, 0, 0, 0.15)',
|
|
13779
14524
|
fontFamily: 'var(--seekora-font-family, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif)',
|
|
@@ -13797,17 +14542,17 @@ const createStyles$2 = () => ({
|
|
|
13797
14542
|
dragBar: {
|
|
13798
14543
|
width: '36px',
|
|
13799
14544
|
height: '5px',
|
|
13800
|
-
backgroundColor: 'var(--seekora-border-color,
|
|
14545
|
+
backgroundColor: 'var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
13801
14546
|
borderRadius: '3px',
|
|
13802
14547
|
},
|
|
13803
14548
|
header: {
|
|
13804
14549
|
padding: '0 16px 16px',
|
|
13805
|
-
borderBottom: '1px solid var(--seekora-border-color,
|
|
14550
|
+
borderBottom: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
13806
14551
|
},
|
|
13807
14552
|
searchContainer: {
|
|
13808
14553
|
display: 'flex',
|
|
13809
14554
|
alignItems: 'center',
|
|
13810
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
14555
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
13811
14556
|
borderRadius: '12px',
|
|
13812
14557
|
padding: '12px 16px',
|
|
13813
14558
|
gap: '12px',
|
|
@@ -13823,7 +14568,7 @@ const createStyles$2 = () => ({
|
|
|
13823
14568
|
border: 'none',
|
|
13824
14569
|
background: 'transparent',
|
|
13825
14570
|
fontSize: '17px',
|
|
13826
|
-
color: 'var(--seekora-text-primary,
|
|
14571
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13827
14572
|
outline: 'none',
|
|
13828
14573
|
},
|
|
13829
14574
|
cancelBtn: {
|
|
@@ -13871,11 +14616,11 @@ const createStyles$2 = () => ({
|
|
|
13871
14616
|
cursor: 'pointer',
|
|
13872
14617
|
transition: 'background-color 100ms',
|
|
13873
14618
|
minHeight: '56px', // Touch-friendly
|
|
13874
|
-
color: 'var(--seekora-text-primary,
|
|
14619
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13875
14620
|
},
|
|
13876
14621
|
itemActive: {
|
|
13877
|
-
backgroundColor: 'var(--seekora-bg-hover,
|
|
13878
|
-
color: 'var(--seekora-text-primary,
|
|
14622
|
+
backgroundColor: 'var(--seekora-bg-hover, rgba(255, 255, 255, 0.1))',
|
|
14623
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13879
14624
|
},
|
|
13880
14625
|
itemIcon: {
|
|
13881
14626
|
width: '24px',
|
|
@@ -13897,14 +14642,14 @@ const createStyles$2 = () => ({
|
|
|
13897
14642
|
},
|
|
13898
14643
|
itemTitle: {
|
|
13899
14644
|
fontSize: '17px',
|
|
13900
|
-
color: 'var(--seekora-text-primary,
|
|
14645
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13901
14646
|
whiteSpace: 'nowrap',
|
|
13902
14647
|
overflow: 'hidden',
|
|
13903
14648
|
textOverflow: 'ellipsis',
|
|
13904
14649
|
},
|
|
13905
14650
|
itemSubtitle: {
|
|
13906
14651
|
fontSize: '15px',
|
|
13907
|
-
color: 'var(--seekora-text-secondary,
|
|
14652
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13908
14653
|
marginTop: '2px',
|
|
13909
14654
|
whiteSpace: 'nowrap',
|
|
13910
14655
|
overflow: 'hidden',
|
|
@@ -13937,7 +14682,7 @@ const createStyles$2 = () => ({
|
|
|
13937
14682
|
},
|
|
13938
14683
|
productTitle: {
|
|
13939
14684
|
fontSize: '15px',
|
|
13940
|
-
color: 'var(--seekora-text-primary,
|
|
14685
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13941
14686
|
marginBottom: '4px',
|
|
13942
14687
|
whiteSpace: 'nowrap',
|
|
13943
14688
|
overflow: 'hidden',
|
|
@@ -13946,19 +14691,19 @@ const createStyles$2 = () => ({
|
|
|
13946
14691
|
productPrice: {
|
|
13947
14692
|
fontSize: '15px',
|
|
13948
14693
|
fontWeight: 600,
|
|
13949
|
-
color: 'var(--seekora-text-primary,
|
|
14694
|
+
color: 'var(--seekora-text-primary, inherit)',
|
|
13950
14695
|
},
|
|
13951
14696
|
footer: {
|
|
13952
14697
|
padding: '12px 16px',
|
|
13953
14698
|
paddingBottom: 'calc(12px + env(safe-area-inset-bottom, 0px))',
|
|
13954
|
-
borderTop: '1px solid var(--seekora-border-color,
|
|
13955
|
-
backgroundColor: 'var(--seekora-bg-secondary,
|
|
14699
|
+
borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
14700
|
+
backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
|
|
13956
14701
|
},
|
|
13957
14702
|
footerBtn: {
|
|
13958
14703
|
width: '100%',
|
|
13959
14704
|
padding: '16px',
|
|
13960
14705
|
backgroundColor: 'var(--seekora-primary, #007aff)',
|
|
13961
|
-
color: 'var(--seekora-text-inverse,
|
|
14706
|
+
color: 'var(--seekora-text-inverse, transparent)',
|
|
13962
14707
|
border: 'none',
|
|
13963
14708
|
borderRadius: '12px',
|
|
13964
14709
|
fontSize: '17px',
|
|
@@ -13970,12 +14715,12 @@ const createStyles$2 = () => ({
|
|
|
13970
14715
|
alignItems: 'center',
|
|
13971
14716
|
justifyContent: 'center',
|
|
13972
14717
|
padding: '60px',
|
|
13973
|
-
color: 'var(--seekora-text-secondary,
|
|
14718
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13974
14719
|
},
|
|
13975
14720
|
spinner: {
|
|
13976
14721
|
width: '28px',
|
|
13977
14722
|
height: '28px',
|
|
13978
|
-
border: '3px solid var(--seekora-border-color,
|
|
14723
|
+
border: '3px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
|
|
13979
14724
|
borderTopColor: 'var(--seekora-primary, #007aff)',
|
|
13980
14725
|
borderRadius: '50%',
|
|
13981
14726
|
animation: 'seekora-spin 0.8s linear infinite',
|
|
@@ -13983,7 +14728,7 @@ const createStyles$2 = () => ({
|
|
|
13983
14728
|
empty: {
|
|
13984
14729
|
padding: '60px 20px',
|
|
13985
14730
|
textAlign: 'center',
|
|
13986
|
-
color: 'var(--seekora-text-secondary,
|
|
14731
|
+
color: 'var(--seekora-text-secondary, inherit)',
|
|
13987
14732
|
fontSize: '17px',
|
|
13988
14733
|
},
|
|
13989
14734
|
emptyIcon: {
|
|
@@ -17448,6 +18193,7 @@ exports.CurrentRefinements = CurrentRefinements;
|
|
|
17448
18193
|
exports.DocSearch = DocSearch;
|
|
17449
18194
|
exports.DocSearchButton = DocSearchButton;
|
|
17450
18195
|
exports.DropdownPanel = DropdownPanel;
|
|
18196
|
+
exports.FacetDropdown = FacetDropdown;
|
|
17451
18197
|
exports.Facets = Facets;
|
|
17452
18198
|
exports.FederatedDropdown = FederatedDropdown;
|
|
17453
18199
|
exports.Fingerprint = Fingerprint;
|