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