@seekora-ai/ui-sdk-react 0.2.12 → 0.2.14

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 (102) hide show
  1. package/dist/components/CurrentRefinements.d.ts +22 -2
  2. package/dist/components/CurrentRefinements.d.ts.map +1 -1
  3. package/dist/components/CurrentRefinements.js +199 -47
  4. package/dist/components/Facets.d.ts +30 -1
  5. package/dist/components/Facets.d.ts.map +1 -1
  6. package/dist/components/Facets.js +418 -46
  7. package/dist/components/HierarchicalMenu.d.ts.map +1 -1
  8. package/dist/components/HierarchicalMenu.js +112 -4
  9. package/dist/components/InfiniteHits.d.ts +2 -0
  10. package/dist/components/InfiniteHits.d.ts.map +1 -1
  11. package/dist/components/InfiniteHits.js +6 -3
  12. package/dist/components/Pagination.d.ts +47 -1
  13. package/dist/components/Pagination.d.ts.map +1 -1
  14. package/dist/components/Pagination.js +166 -28
  15. package/dist/components/QuerySuggestions.d.ts +2 -0
  16. package/dist/components/QuerySuggestions.d.ts.map +1 -1
  17. package/dist/components/QuerySuggestions.js +4 -3
  18. package/dist/components/QuerySuggestionsDropdown.d.ts +1 -1
  19. package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -1
  20. package/dist/components/QuerySuggestionsDropdown.js +4 -4
  21. package/dist/components/RangeSlider.d.ts.map +1 -1
  22. package/dist/components/RangeSlider.js +49 -2
  23. package/dist/components/Recommendations.d.ts +6 -0
  24. package/dist/components/Recommendations.d.ts.map +1 -1
  25. package/dist/components/Recommendations.js +12 -6
  26. package/dist/components/RichQuerySuggestions.d.ts +11 -0
  27. package/dist/components/RichQuerySuggestions.d.ts.map +1 -1
  28. package/dist/components/RichQuerySuggestions.js +2 -3
  29. package/dist/components/SearchBar.d.ts +18 -0
  30. package/dist/components/SearchBar.d.ts.map +1 -1
  31. package/dist/components/SearchBar.js +134 -24
  32. package/dist/components/SearchProvider.d.ts +8 -1
  33. package/dist/components/SearchProvider.d.ts.map +1 -1
  34. package/dist/components/SearchProvider.js +16 -4
  35. package/dist/components/SearchResults.d.ts +12 -0
  36. package/dist/components/SearchResults.d.ts.map +1 -1
  37. package/dist/components/SearchResults.js +11 -5
  38. package/dist/components/SortBy.d.ts +44 -4
  39. package/dist/components/SortBy.d.ts.map +1 -1
  40. package/dist/components/SortBy.js +154 -29
  41. package/dist/components/Stats.d.ts +14 -0
  42. package/dist/components/Stats.d.ts.map +1 -1
  43. package/dist/components/Stats.js +172 -23
  44. package/dist/components/section-primitives/SectionItemGrid.d.ts +3 -1
  45. package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -1
  46. package/dist/components/section-primitives/SectionItemGrid.js +3 -2
  47. package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -1
  48. package/dist/components/suggestions/AmazonDropdown.js +4 -6
  49. package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -1
  50. package/dist/components/suggestions/GoogleDropdown.js +4 -8
  51. package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -1
  52. package/dist/components/suggestions/MinimalDropdown.js +4 -6
  53. package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -1
  54. package/dist/components/suggestions/MobileSheetDropdown.js +4 -6
  55. package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -1
  56. package/dist/components/suggestions/PinterestDropdown.js +4 -8
  57. package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -1
  58. package/dist/components/suggestions/ShopifyDropdown.js +4 -6
  59. package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -1
  60. package/dist/components/suggestions/SpotlightDropdown.js +4 -6
  61. package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -1
  62. package/dist/components/suggestions/SuggestionSearchBar.js +1 -0
  63. package/dist/components/suggestions/types.d.ts +2 -0
  64. package/dist/components/suggestions/types.d.ts.map +1 -1
  65. package/dist/components/suggestions/utils.d.ts +10 -1
  66. package/dist/components/suggestions/utils.d.ts.map +1 -1
  67. package/dist/components/suggestions/utils.js +36 -0
  68. package/dist/components/suggestions-primitives/SuggestionList.d.ts +8 -1
  69. package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -1
  70. package/dist/components/suggestions-primitives/SuggestionList.js +7 -4
  71. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.d.ts.map +1 -1
  72. package/dist/components/suggestions-primitives/SuggestionsDropdownComposition.js +0 -2
  73. package/dist/components/suggestions-primitives/highlightMarkup.d.ts +16 -4
  74. package/dist/components/suggestions-primitives/highlightMarkup.d.ts.map +1 -1
  75. package/dist/components/suggestions-primitives/highlightMarkup.js +42 -4
  76. package/dist/docsearch/components/Results.d.ts +3 -1
  77. package/dist/docsearch/components/Results.d.ts.map +1 -1
  78. package/dist/docsearch/components/Results.js +6 -2
  79. package/dist/hooks/useClickTracking.d.ts +36 -0
  80. package/dist/hooks/useClickTracking.d.ts.map +1 -0
  81. package/dist/hooks/useClickTracking.js +96 -0
  82. package/dist/hooks/useExperiment.d.ts +25 -0
  83. package/dist/hooks/useExperiment.d.ts.map +1 -0
  84. package/dist/hooks/useExperiment.js +146 -0
  85. package/dist/hooks/useKeyboardNavigation.d.ts +51 -0
  86. package/dist/hooks/useKeyboardNavigation.d.ts.map +1 -0
  87. package/dist/hooks/useKeyboardNavigation.js +113 -0
  88. package/dist/hooks/useQuerySuggestions.d.ts.map +1 -1
  89. package/dist/hooks/useQuerySuggestions.js +19 -3
  90. package/dist/hooks/useQuerySuggestionsEnhanced.d.ts.map +1 -1
  91. package/dist/hooks/useQuerySuggestionsEnhanced.js +25 -7
  92. package/dist/hooks/useSuggestionsAnalytics.d.ts.map +1 -1
  93. package/dist/hooks/useSuggestionsAnalytics.js +6 -1
  94. package/dist/index.d.ts +4 -1
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.umd.js +1 -1
  97. package/dist/src/index.d.ts +249 -19
  98. package/dist/src/index.esm.js +1659 -305
  99. package/dist/src/index.esm.js.map +1 -1
  100. package/dist/src/index.js +1658 -304
  101. package/dist/src/index.js.map +1 -1
  102. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../src/components/RangeSlider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAKjF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,8DAA8D;IAC9D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CA4QlD,CAAC"}
1
+ {"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../src/components/RangeSlider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA4D,MAAM,OAAO,CAAC;AAKjF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,8DAA8D;IAC9D,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAqUlD,CAAC"}
@@ -103,6 +103,53 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
103
103
  const handleDragEnd = () => {
104
104
  setIsDragging(false);
105
105
  };
106
+ // Handle keyboard navigation for enhanced control (Shift+Arrow for 10x step, Home/End)
107
+ const handleMinKeyDown = (e) => {
108
+ let newValue = null;
109
+ if (e.key === 'Home') {
110
+ e.preventDefault();
111
+ newValue = min;
112
+ }
113
+ else if (e.key === 'End') {
114
+ e.preventDefault();
115
+ newValue = internalMax - step;
116
+ }
117
+ else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
118
+ e.preventDefault();
119
+ newValue = Math.max(min, internalMin - step * 10);
120
+ }
121
+ else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
122
+ e.preventDefault();
123
+ newValue = Math.min(internalMax - step, internalMin + step * 10);
124
+ }
125
+ if (newValue !== null) {
126
+ setInternalMin(newValue);
127
+ debouncedUpdate(newValue, internalMax);
128
+ }
129
+ };
130
+ const handleMaxKeyDown = (e) => {
131
+ let newValue = null;
132
+ if (e.key === 'Home') {
133
+ e.preventDefault();
134
+ newValue = internalMin + step;
135
+ }
136
+ else if (e.key === 'End') {
137
+ e.preventDefault();
138
+ newValue = max;
139
+ }
140
+ else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
141
+ e.preventDefault();
142
+ newValue = Math.max(internalMin + step, internalMax - step * 10);
143
+ }
144
+ else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
145
+ e.preventDefault();
146
+ newValue = Math.min(max, internalMax + step * 10);
147
+ }
148
+ if (newValue !== null) {
149
+ setInternalMax(newValue);
150
+ debouncedUpdate(internalMin, newValue);
151
+ }
152
+ };
106
153
  // Calculate filled track position
107
154
  const minPercent = ((internalMin - min) / (max - min)) * 100;
108
155
  const maxPercent = ((internalMax - min) / (max - min)) * 100;
@@ -138,7 +185,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
138
185
  backgroundColor: theme.colors.primary,
139
186
  borderRadius: '2px',
140
187
  } }),
141
- React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMin, onChange: handleMinChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, className: rangeSliderTheme.thumb, style: {
188
+ 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: {
142
189
  position: 'absolute',
143
190
  width: '100%',
144
191
  height: '4px',
@@ -148,7 +195,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
148
195
  cursor: 'pointer',
149
196
  pointerEvents: 'none',
150
197
  }, "aria-label": `Minimum ${label || field}` }),
151
- React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMax, onChange: handleMaxChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, className: rangeSliderTheme.thumb, style: {
198
+ 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: {
152
199
  position: 'absolute',
153
200
  width: '100%',
154
201
  height: '4px',
@@ -51,6 +51,8 @@ export interface RelatedProductsProps extends BaseRecommendationProps {
51
51
  items?: RecommendationItem[];
52
52
  /** Loading state */
53
53
  loading?: boolean;
54
+ /** Show loading state when fetching and no previous items (default false: show previous results until new render) */
55
+ showLoadingState?: boolean;
54
56
  }
55
57
  export declare const RelatedProducts: React.FC<RelatedProductsProps>;
56
58
  export interface TrendingItemsProps extends BaseRecommendationProps {
@@ -58,6 +60,8 @@ export interface TrendingItemsProps extends BaseRecommendationProps {
58
60
  items?: RecommendationItem[];
59
61
  /** Loading state */
60
62
  loading?: boolean;
63
+ /** Show loading state when fetching and no previous items (default false: show previous results until new render) */
64
+ showLoadingState?: boolean;
61
65
  /** Facet name for trending (if using facet data) */
62
66
  facetName?: string;
63
67
  }
@@ -69,6 +73,8 @@ export interface FrequentlyBoughtTogetherProps extends BaseRecommendationProps {
69
73
  items?: RecommendationItem[];
70
74
  /** Loading state */
71
75
  loading?: boolean;
76
+ /** Show loading state when fetching and no previous items (default false: show previous results until new render) */
77
+ showLoadingState?: boolean;
72
78
  /** Show "Add all to cart" button */
73
79
  showAddAllButton?: boolean;
74
80
  /** Callback when "Add all" is clicked */
@@ -1 +1 @@
1
- {"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../src/components/Recommendations.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Recommendations.d.ts","sourceRoot":"","sources":["../../src/components/Recommendations.tsx"],"names":[],"mappings":"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"}
@@ -10,36 +10,40 @@
10
10
  import React, { useEffect, useState, useMemo } from 'react';
11
11
  import { useSearchContext } from './SearchProvider';
12
12
  import { clsx } from 'clsx';
13
- export const RelatedProducts = ({ productId, items: itemsProp, loading: loadingProp = false, title = 'Related Products', maxItems = 6, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
13
+ export const RelatedProducts = ({ productId, items: itemsProp, loading: loadingProp = false, showLoadingState = false, title = 'Related Products', maxItems = 6, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
14
14
  const { theme } = useSearchContext();
15
15
  const recommendationTheme = customTheme || {};
16
16
  // If items are provided, use them directly
17
17
  const items = itemsProp?.slice(0, maxItems) || [];
18
18
  const loading = loadingProp;
19
- if (loading) {
19
+ if (loading && items.length === 0 && showLoadingState) {
20
20
  return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
21
21
  React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading related products...")));
22
22
  }
23
+ if (loading && items.length === 0)
24
+ return null;
23
25
  if (items.length === 0) {
24
26
  return null;
25
27
  }
26
28
  return (React.createElement(RecommendationSection, { title: title, items: items, renderItem: renderItem, onItemClick: onItemClick, className: className, style: style, theme: customTheme, layout: layout, currencySymbol: currencySymbol }));
27
29
  };
28
- export const TrendingItems = ({ items: itemsProp, loading: loadingProp = false, title = 'Trending Now', maxItems = 8, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
30
+ export const TrendingItems = ({ items: itemsProp, loading: loadingProp = false, showLoadingState = false, title = 'Trending Now', maxItems = 8, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', }) => {
29
31
  const { theme } = useSearchContext();
30
32
  const recommendationTheme = customTheme || {};
31
33
  const items = itemsProp?.slice(0, maxItems) || [];
32
34
  const loading = loadingProp;
33
- if (loading) {
35
+ if (loading && items.length === 0 && showLoadingState) {
34
36
  return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
35
37
  React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading trending items...")));
36
38
  }
39
+ if (loading && items.length === 0)
40
+ return null;
37
41
  if (items.length === 0) {
38
42
  return null;
39
43
  }
40
44
  return (React.createElement(RecommendationSection, { title: title, items: items, renderItem: renderItem, onItemClick: onItemClick, className: className, style: style, theme: customTheme, layout: layout, currencySymbol: currencySymbol }));
41
45
  };
42
- export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading: loadingProp = false, title = 'Frequently Bought Together', maxItems = 4, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', showAddAllButton = true, onAddAll, }) => {
46
+ export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading: loadingProp = false, showLoadingState = false, title = 'Frequently Bought Together', maxItems = 4, renderItem, onItemClick, className, style, theme: customTheme, layout = 'horizontal', currencySymbol = '$', showAddAllButton = true, onAddAll, }) => {
43
47
  const { theme } = useSearchContext();
44
48
  const recommendationTheme = customTheme || {};
45
49
  const items = itemsProp?.slice(0, maxItems) || [];
@@ -52,10 +56,12 @@ export const FrequentlyBoughtTogether = ({ productId, items: itemsProp, loading:
52
56
  return sum + price;
53
57
  }, 0);
54
58
  }, [items]);
55
- if (loading) {
59
+ if (loading && items.length === 0 && showLoadingState) {
56
60
  return (React.createElement("div", { className: clsx(recommendationTheme.root, className), style: style },
57
61
  React.createElement("div", { className: recommendationTheme.loading, style: getLoadingStyle(theme) }, "Loading recommendations...")));
58
62
  }
63
+ if (loading && items.length === 0)
64
+ return null;
59
65
  if (items.length === 0) {
60
66
  return null;
61
67
  }
@@ -57,6 +57,10 @@ export interface RichQuerySuggestionsProps extends QuerySuggestionsEventHandlers
57
57
  header?: React.ReactNode;
58
58
  /** Custom footer content */
59
59
  footer?: React.ReactNode;
60
+ /** Show loading overlay when fetching (default false: show previous results until new results render) */
61
+ showLoadingOverlay?: boolean;
62
+ /** Custom render for loading overlay (only when showLoadingOverlay is true) */
63
+ renderLoading?: () => React.ReactNode;
60
64
  /** Dropdown width */
61
65
  width?: string | number;
62
66
  /** Dropdown max height */
@@ -67,6 +71,13 @@ export interface RichQuerySuggestionsProps extends QuerySuggestionsEventHandlers
67
71
  ariaLabel?: string;
68
72
  /** Analytics tags */
69
73
  analyticsTags?: string[];
74
+ /** Highlight options for query suggestions (passed to highlight rendering) */
75
+ highlightOptions?: {
76
+ highlightColor?: string;
77
+ highlightTextColor?: string;
78
+ highlightFontWeight?: string | number;
79
+ highlightStyle?: 'background' | 'underline' | 'bold' | 'color-only';
80
+ };
70
81
  }
71
82
  export interface RichQuerySuggestionsRef {
72
83
  getActiveIndex: () => number;
@@ -1 +1 @@
1
- {"version":3,"file":"RichQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/RichQuerySuggestions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,cAAc,EAGd,kBAAkB,EAClB,0BAA0B,EAC1B,6BAA6B,EAE7B,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,yBAA0B,SAAQ,6BAA6B;IAC9E,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACnC,sCAAsC;IACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,2BAA2B;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,sEAAsE;IACtE,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,wCAAwC;IACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,2BAA2B;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yBAAyB;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,wBAAwB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IACtF,sCAAsC;IACtC,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,KAAK,CAAC,SAAS,CAAC;IACnE,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,KAAK,CAAC,SAAS,CAAC;IAC3D,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,cAAc,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,MAAM,CAAC;CAC7B;AAqPD,eAAO,MAAM,oBAAoB,2GAschC,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"RichQuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/RichQuerySuggestions.tsx"],"names":[],"mappings":"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"}
@@ -233,7 +233,7 @@ const CloseIcon = () => (React.createElement("svg", { viewBox: "0 0 20 20", fill
233
233
  // Component
234
234
  // ============================================================================
235
235
  export const RichQuerySuggestions = forwardRef(function RichQuerySuggestions(props, ref) {
236
- const { query, isOpen = true, sections = DEFAULT_SECTIONS, maxSuggestionsPerSection = 8, minQueryLength = 0, debounceMs = 200, includeDropdownRecommendations = true, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, maxCategories = 3, showCounts = true, showCategoryCounts = true, showSectionHeaders = true, classNames = {}, style, renderSuggestion, renderCategory, renderTrendingItem, renderRecentItem, header, footer, width = '100%', maxHeight = '480px', zIndex = 1000, ariaLabel = 'Search suggestions', analyticsTags, onSuggestionSelect, onCategoryClick, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, } = props;
236
+ const { query, isOpen = true, sections = DEFAULT_SECTIONS, maxSuggestionsPerSection = 8, minQueryLength = 0, debounceMs = 200, includeDropdownRecommendations = true, includeDropdownProductList = true, includeFilteredTabs = true, includeCategories = true, maxCategories = 3, showCounts = true, showCategoryCounts = true, showSectionHeaders = true, classNames = {}, style, renderSuggestion, renderCategory, renderTrendingItem, renderRecentItem, header, footer, width = '100%', maxHeight = '480px', zIndex = 1000, ariaLabel = 'Search suggestions', analyticsTags, onSuggestionSelect, onCategoryClick, onRecentSearchClick, onRecentSearchRemove, onViewAllClick, onOpen, onClose, showLoadingOverlay = false, renderLoading, } = props;
237
237
  const { client } = useSearchContext();
238
238
  const containerRef = useRef(null);
239
239
  const [activeIndex, setActiveIndex] = useState(-1);
@@ -452,8 +452,7 @@ export const RichQuerySuggestions = forwardRef(function RichQuerySuggestions(pro
452
452
  } },
453
453
  header && React.createElement("div", { style: styles.header }, header),
454
454
  React.createElement("div", { style: { ...styles.content, maxHeight } },
455
- loading && (React.createElement("div", { style: styles.loadingOverlay },
456
- React.createElement("span", null, "Loading..."))),
455
+ loading && showLoadingOverlay && (React.createElement("div", { style: styles.loadingOverlay }, renderLoading ? renderLoading() : React.createElement("span", null, "Loading..."))),
457
456
  enabledSections.map((section, index) => {
458
457
  let content = null;
459
458
  switch (section.id) {
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import React from 'react';
7
7
  import type { SearchOptions } from '@seekora-ai/search-sdk';
8
+ export type SearchBarSize = 'small' | 'medium' | 'large';
8
9
  export interface SearchBarTheme {
9
10
  container?: string;
10
11
  input?: string;
@@ -14,6 +15,9 @@ export interface SearchBarTheme {
14
15
  suggestionItemHover?: string;
15
16
  suggestionItemActive?: string;
16
17
  loadingIndicator?: string;
18
+ searchIcon?: string;
19
+ clearButton?: string;
20
+ submitButton?: string;
17
21
  }
18
22
  export interface SearchBarProps {
19
23
  placeholder?: string;
@@ -33,8 +37,22 @@ export interface SearchBarProps {
33
37
  className?: string;
34
38
  style?: React.CSSProperties;
35
39
  theme?: SearchBarTheme;
40
+ /** Show loading state when fetching and no previous suggestions (default false: show previous results until new render) */
41
+ showLoadingState?: boolean;
36
42
  renderSuggestion?: (suggestion: string, index: number) => React.ReactNode;
37
43
  renderLoading?: () => React.ReactNode;
44
+ /** Custom render for the search icon. If not provided, a default magnifying glass SVG is rendered. */
45
+ renderSearchIcon?: () => React.ReactNode;
46
+ /** Whether to show a clear button when the query is non-empty (default: true) */
47
+ showClearButton?: boolean;
48
+ /** Custom render for the clear icon */
49
+ renderClearIcon?: () => React.ReactNode;
50
+ /** Whether to show a submit button to the right of the input (default: false) */
51
+ showSubmitButton?: boolean;
52
+ /** Custom render for the submit button */
53
+ renderSubmitButton?: () => React.ReactNode;
54
+ /** Size variant controlling padding and font size (default: 'medium') */
55
+ size?: SearchBarSize;
38
56
  }
39
57
  export declare const SearchBar: React.FC<SearchBarProps>;
40
58
  //# sourceMappingURL=SearchBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../src/components/SearchBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1E,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;CACvC;AAED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAuT9C,CAAC"}
1
+ {"version":3,"file":"SearchBar.d.ts","sourceRoot":"","sources":["../../src/components/SearchBar.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAMxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAC;IACjD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,kBAAkB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,GAAG,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,aAAa,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,2HAA2H;IAC3H,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1E,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC,sGAAsG;IACtG,gBAAgB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACzC,iFAAiF;IACjF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,eAAe,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACxC,iFAAiF;IACjF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC3C,yEAAyE;IACzE,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAgED,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CA0b9C,CAAC"}
@@ -9,7 +9,42 @@ import { useSearchState } from '../hooks/useSearchState';
9
9
  import { useQuerySuggestions } from '../hooks/useQuerySuggestions';
10
10
  import { log } from '@seekora-ai/ui-sdk-core';
11
11
  import { clsx } from 'clsx';
12
- export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, renderSuggestion, renderLoading, }) => {
12
+ const SIZE_CONFIG = {
13
+ small: {
14
+ padding: '0.375rem 0.5rem',
15
+ fontSize: '0.875rem',
16
+ iconSize: 14,
17
+ iconPaddingLeft: '1.75rem',
18
+ iconPaddingRight: '1.75rem',
19
+ iconLeft: '0.5rem',
20
+ iconRight: '0.5rem',
21
+ },
22
+ medium: {
23
+ padding: '0.625rem 1rem',
24
+ fontSize: '1rem',
25
+ iconSize: 18,
26
+ iconPaddingLeft: '2.25rem',
27
+ iconPaddingRight: '2.25rem',
28
+ iconLeft: '0.625rem',
29
+ iconRight: '0.625rem',
30
+ },
31
+ large: {
32
+ padding: '0.875rem 1.25rem',
33
+ fontSize: '1.25rem',
34
+ iconSize: 22,
35
+ iconPaddingLeft: '2.75rem',
36
+ iconPaddingRight: '2.75rem',
37
+ iconLeft: '0.75rem',
38
+ iconRight: '0.75rem',
39
+ },
40
+ };
41
+ const DefaultSearchIcon = ({ size = 18 }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
42
+ React.createElement("circle", { cx: "11", cy: "11", r: "8" }),
43
+ React.createElement("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })));
44
+ const DefaultClearIcon = ({ size = 14 }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
45
+ React.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
46
+ React.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })));
47
+ export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, showLoadingState = false, renderSuggestion, renderLoading, renderSearchIcon, showClearButton = true, renderClearIcon, showSubmitButton = false, renderSubmitButton, size = 'medium', }) => {
13
48
  const { client, theme, enableAnalytics, autoTrackSearch } = useSearchContext();
14
49
  const { query, setQuery, search: triggerSearch, results, loading: searchLoading, error: searchError } = useSearchState();
15
50
  const [isFocused, setIsFocused] = useState(false);
@@ -142,40 +177,115 @@ export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, d
142
177
  const defaultRenderLoading = () => (React.createElement("div", { style: { padding: theme.spacing.medium, textAlign: 'center' } }, "Loading suggestions..."));
143
178
  const searchBarTheme = customTheme || {};
144
179
  const isLoading = suggestionsLoading || searchLoading;
145
- // Only show suggestions list if:
146
- // 1. Input is focused
147
- // 2. Suggestions are enabled
148
- // 3. Query is long enough
149
- // 4. AND (we have suggestions to show OR we're currently loading suggestions)
180
+ // Show list when we have suggestions (including previous while loading) or when loading and showLoadingState
150
181
  const hasSuggestions = displayedSuggestions.length > 0;
151
- const showSuggestionsList = isFocused && showSuggestions && query.length >= minQueryLength && (hasSuggestions || isLoading);
182
+ const showSuggestionsList = isFocused && showSuggestions && query.length >= minQueryLength && (hasSuggestions || (isLoading && showLoadingState));
152
183
  // Get processing time from results
153
184
  const res = results;
154
185
  const processingTime = res?.processingTimeMS
155
186
  || res?.data?.processingTimeMS
156
187
  || res?.data?.data?.processingTimeMS;
188
+ // Size-based configuration
189
+ const sizeConfig = SIZE_CONFIG[size];
190
+ // Determine whether the search icon is shown (always unless renderSearchIcon returns null explicitly — but
191
+ // we always show it; there is no prop to hide the search icon, only to customise it)
192
+ const hasSearchIcon = true;
193
+ const hasClearBtn = showClearButton && query.length > 0;
194
+ // Compute input padding accounting for icons
195
+ const inputPaddingLeft = hasSearchIcon ? sizeConfig.iconPaddingLeft : sizeConfig.padding.split(' ')[1] || sizeConfig.padding;
196
+ const inputPaddingRight = hasClearBtn ? sizeConfig.iconPaddingRight : sizeConfig.padding.split(' ')[1] || sizeConfig.padding;
197
+ const borderRadius = typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium;
198
+ const focusBorderColor = isFocused ? theme.colors.focus : theme.colors.border;
199
+ const focusRingShadow = isFocused
200
+ ? `0 0 0 3px ${theme.colors.focus}33`
201
+ : undefined;
202
+ const handleClear = useCallback(() => {
203
+ setQuery('', false);
204
+ setSelectedIndex(-1);
205
+ inputRef.current?.focus();
206
+ }, [setQuery]);
207
+ const handleSubmit = useCallback(() => {
208
+ const currentValue = inputRef.current?.value || query;
209
+ handleSearch(currentValue);
210
+ }, [query, handleSearch]);
157
211
  return (React.createElement("div", { ref: containerRef, className: clsx(searchBarTheme.container, className), style: {
158
212
  position: 'relative',
159
213
  display: 'flex',
160
214
  alignItems: 'center',
215
+ // CSS custom properties for external styling
216
+ '--seekora-searchbar-bg': theme.colors.background,
217
+ '--seekora-searchbar-border': theme.colors.border,
218
+ '--seekora-searchbar-focus-border': theme.colors.focus,
219
+ '--seekora-searchbar-radius': borderRadius,
220
+ '--seekora-searchbar-icon-color': theme.colors.textSecondary,
161
221
  ...style,
162
222
  } },
163
- 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: {
164
- flex: 1,
165
- padding: theme.spacing.medium,
166
- fontSize: theme.typography.fontSize.medium,
223
+ React.createElement("div", { style: { position: 'relative', flex: 1, display: 'flex', alignItems: 'center' } },
224
+ hasSearchIcon && (React.createElement("span", { className: searchBarTheme.searchIcon, "aria-hidden": "true", style: {
225
+ position: 'absolute',
226
+ left: sizeConfig.iconLeft,
227
+ top: '50%',
228
+ transform: 'translateY(-50%)',
229
+ display: 'flex',
230
+ alignItems: 'center',
231
+ justifyContent: 'center',
232
+ pointerEvents: 'none',
233
+ color: 'var(--seekora-searchbar-icon-color)',
234
+ zIndex: 1,
235
+ } }, renderSearchIcon ? renderSearchIcon() : React.createElement(DefaultSearchIcon, { size: sizeConfig.iconSize }))),
236
+ 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: {
237
+ width: '100%',
238
+ paddingTop: sizeConfig.padding.split(' ')[0],
239
+ paddingBottom: sizeConfig.padding.split(' ')[0],
240
+ paddingLeft: inputPaddingLeft,
241
+ paddingRight: inputPaddingRight,
242
+ fontSize: sizeConfig.fontSize,
243
+ fontFamily: theme.typography.fontFamily,
244
+ backgroundColor: 'var(--seekora-searchbar-bg)',
245
+ color: theme.colors.text,
246
+ borderWidth: '1px',
247
+ borderStyle: 'solid',
248
+ borderColor: focusBorderColor,
249
+ borderRadius: 'var(--seekora-searchbar-radius)',
250
+ outline: 'none',
251
+ boxShadow: focusRingShadow,
252
+ transition: theme.transitions?.fast || '150ms ease-in-out',
253
+ boxSizing: 'border-box',
254
+ } }),
255
+ hasClearBtn && (React.createElement("button", { type: "button", onClick: handleClear, className: searchBarTheme.clearButton, "aria-label": "Clear search", style: {
256
+ position: 'absolute',
257
+ right: sizeConfig.iconRight,
258
+ top: '50%',
259
+ transform: 'translateY(-50%)',
260
+ display: 'flex',
261
+ alignItems: 'center',
262
+ justifyContent: 'center',
263
+ background: 'none',
264
+ border: 'none',
265
+ cursor: 'pointer',
266
+ padding: '2px',
267
+ borderRadius: '50%',
268
+ color: 'var(--seekora-searchbar-icon-color)',
269
+ transition: theme.transitions?.fast || '150ms ease-in-out',
270
+ zIndex: 1,
271
+ }, onMouseDown: (e) => {
272
+ // Prevent input blur so the clear action doesn't race with blur handler
273
+ e.preventDefault();
274
+ } }, renderClearIcon ? renderClearIcon() : React.createElement(DefaultClearIcon, { size: sizeConfig.iconSize - 4 })))),
275
+ showSubmitButton && (renderSubmitButton ? (React.createElement("div", { onClick: handleSubmit, style: { marginLeft: theme.spacing.small, cursor: 'pointer' } }, renderSubmitButton())) : (React.createElement("button", { type: "button", onClick: handleSubmit, className: searchBarTheme.submitButton, style: {
276
+ marginLeft: theme.spacing.small,
277
+ padding: sizeConfig.padding,
278
+ fontSize: sizeConfig.fontSize,
167
279
  fontFamily: theme.typography.fontFamily,
168
- backgroundColor: theme.colors.background,
169
- color: theme.colors.text,
170
- borderWidth: '1px',
171
- borderStyle: 'solid',
172
- borderColor: isFocused ? theme.colors.focus : theme.colors.border,
173
- borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
174
- outline: 'none',
175
- ...(isFocused && {
176
- boxShadow: theme.shadows.small,
177
- }),
178
- } }),
280
+ fontWeight: theme.typography.fontWeight?.medium ?? 500,
281
+ backgroundColor: theme.colors.primary,
282
+ color: '#ffffff',
283
+ border: 'none',
284
+ borderRadius: 'var(--seekora-searchbar-radius)',
285
+ cursor: 'pointer',
286
+ whiteSpace: 'nowrap',
287
+ transition: theme.transitions?.fast || '150ms ease-in-out',
288
+ } }, "Search"))),
179
289
  processingTime !== undefined && (React.createElement("span", { style: {
180
290
  marginLeft: theme.spacing.small,
181
291
  fontSize: theme.typography.fontSize.small,
@@ -199,8 +309,8 @@ export const SearchBar = ({ placeholder = 'Search...', showSuggestions = true, d
199
309
  overflowY: 'auto',
200
310
  zIndex: 1000,
201
311
  } },
202
- isLoading && (renderLoading ? renderLoading() : defaultRenderLoading()),
203
- !isLoading && displayedSuggestions.length > 0 && (React.createElement(React.Fragment, null, displayedSuggestions.map((suggestion, index) => {
312
+ isLoading && displayedSuggestions.length === 0 && showLoadingState && (renderLoading ? renderLoading() : defaultRenderLoading()),
313
+ displayedSuggestions.length > 0 && (React.createElement(React.Fragment, null, displayedSuggestions.map((suggestion, index) => {
204
314
  const isSelected = index === selectedIndex;
205
315
  const renderFn = renderSuggestion || defaultRenderSuggestion;
206
316
  return (React.createElement("div", { key: index, className: clsx(searchBarTheme.suggestionItem, isSelected && searchBarTheme.suggestionItemActive), onClick: () => handleSuggestionSelect(suggestion.query), onMouseEnter: () => setSelectedIndex(index), style: {
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * SearchProvider Component
3
3
  *
4
- * Provides Seekora client and context to child components
4
+ * Provides Seekora client and context to child components.
5
+ * Supports A/B testing via abTestId/abVariant props.
5
6
  */
6
7
  import React, { ReactNode } from 'react';
7
8
  import type { SeekoraClient } from '@seekora-ai/search-sdk';
@@ -21,6 +22,12 @@ export interface SearchProviderProps {
21
22
  autoTrackSearch?: boolean;
22
23
  stateManager?: SearchStateManagerConfig;
23
24
  children: ReactNode;
25
+ /** A/B test experiment ID to include in all analytics events */
26
+ abTestId?: string;
27
+ /** A/B test variant to include in all analytics events */
28
+ abVariant?: string;
29
+ /** Auto-fetch experiment assignments on mount (default: false) */
30
+ experiments?: boolean;
24
31
  }
25
32
  export declare const SearchProvider: React.FC<SearchProviderProps>;
26
33
  export declare const useSearchContext: () => SearchContextValue;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchProvider.d.ts","sourceRoot":"","sources":["../../src/components/SearchProvider.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,EAA6B,SAAS,EAAW,MAAM,OAAO,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAO,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI1D,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAID,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAqCxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,kBAQnC,CAAC"}
1
+ {"version":3,"file":"SearchProvider.d.ts","sourceRoot":"","sources":["../../src/components/SearchProvider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,EAA6B,SAAS,EAAsB,MAAM,OAAO,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAO,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI1D,UAAU,kBAAkB;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAID,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,wBAAwB,CAAC;IACxC,QAAQ,EAAE,SAAS,CAAC;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAoDxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,kBAQnC,CAAC"}
@@ -1,14 +1,15 @@
1
1
  /**
2
2
  * SearchProvider Component
3
3
  *
4
- * Provides Seekora client and context to child components
4
+ * Provides Seekora client and context to child components.
5
+ * Supports A/B testing via abTestId/abVariant props.
5
6
  */
6
- import React, { createContext, useContext, useMemo } from 'react';
7
+ import React, { createContext, useContext, useMemo, useEffect } from 'react';
7
8
  import { log, SearchStateManager } from '@seekora-ai/ui-sdk-core';
8
9
  import { defaultTheme } from '../themes/default';
9
10
  import { createTheme } from '../themes/createTheme';
10
11
  const SearchContext = createContext(null);
11
- export const SearchProvider = ({ client, theme: themeConfig, enableAnalytics = true, autoTrackSearch = true, stateManager: stateManagerConfig, children, }) => {
12
+ export const SearchProvider = ({ client, theme: themeConfig, enableAnalytics = true, autoTrackSearch = true, stateManager: stateManagerConfig, children, abTestId, abVariant, experiments: _experiments, }) => {
12
13
  const theme = useMemo(() => {
13
14
  return themeConfig ? createTheme(themeConfig) : defaultTheme;
14
15
  }, [themeConfig]);
@@ -21,8 +22,19 @@ export const SearchProvider = ({ client, theme: themeConfig, enableAnalytics = t
21
22
  itemsPerPage: 10,
22
23
  defaultSearchOptions: { widget_mode: true },
23
24
  ...stateManagerConfig,
25
+ abTestId,
26
+ abVariant,
24
27
  });
25
- }, [client, stateManagerConfig]);
28
+ }, [client, stateManagerConfig, abTestId, abVariant]);
29
+ // Update A/B test fields on state manager and SDK client when props change
30
+ useEffect(() => {
31
+ if (abTestId !== undefined || abVariant !== undefined) {
32
+ stateManager.setAbTest(abTestId, abVariant);
33
+ if (typeof client.setAbTest === 'function') {
34
+ client.setAbTest(abTestId, abVariant);
35
+ }
36
+ }
37
+ }, [stateManager, client, abTestId, abVariant]);
26
38
  const value = useMemo(() => ({
27
39
  client,
28
40
  theme,
@@ -21,6 +21,10 @@ export interface SearchResultsTheme {
21
21
  loadingState?: string;
22
22
  errorState?: string;
23
23
  pagination?: string;
24
+ /** Custom min-height class override */
25
+ minHeight?: string;
26
+ /** Custom min-width class override */
27
+ minWidth?: string;
24
28
  }
25
29
  export interface SearchResultsProps {
26
30
  results?: SearchResponse | null;
@@ -29,6 +33,8 @@ export interface SearchResultsProps {
29
33
  onResultClick?: (result: ResultItem, index: number) => void;
30
34
  renderResult?: (result: ResultItem, index: number, isActive?: boolean) => React.ReactNode;
31
35
  renderEmpty?: () => React.ReactNode;
36
+ /** Show loading state when fetching and no previous results (default false: show previous results until new render) */
37
+ showLoadingState?: boolean;
32
38
  renderLoading?: () => React.ReactNode;
33
39
  renderError?: (error: Error) => React.ReactNode;
34
40
  className?: string;
@@ -46,6 +52,12 @@ export interface SearchResultsProps {
46
52
  enableKeyboardNavigation?: boolean;
47
53
  /** Auto-focus the results container */
48
54
  autoFocus?: boolean;
55
+ /** Minimum height to prevent container collapse when empty (default: '400px') */
56
+ minHeight?: string;
57
+ /** Minimum width to prevent container shrinking (default: '100%') */
58
+ minWidth?: string;
59
+ /** Opacity applied to results while loading new results (default: 0.7, set to 1 to disable) */
60
+ loadingOpacity?: number;
49
61
  }
50
62
  export declare const SearchResults: React.FC<SearchResultsProps>;
51
63
  //# sourceMappingURL=SearchResults.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/components/SearchResults.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1F,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC;IAC1C,+DAA+D;IAC/D,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAoBD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAmmBtD,CAAC"}
1
+ {"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/components/SearchResults.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEnF,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1F,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,uHAAuH;IACvH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,mEAAmE;IACnE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,gFAAgF;IAChF,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE,CAAC;IAC1C,+DAA+D;IAC/D,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAoBD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA6mBtD,CAAC"}