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

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 (143) 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 +94 -0
  4. package/dist/components/FacetDropdown.d.ts.map +1 -0
  5. package/dist/components/FacetDropdown.js +396 -0
  6. package/dist/components/Facets.d.ts +30 -0
  7. package/dist/components/Facets.d.ts.map +1 -1
  8. package/dist/components/Facets.js +215 -7
  9. package/dist/components/FederatedDropdown.d.ts.map +1 -1
  10. package/dist/components/FederatedDropdown.js +45 -31
  11. package/dist/components/InfiniteHits.d.ts +0 -7
  12. package/dist/components/InfiniteHits.d.ts.map +1 -1
  13. package/dist/components/InfiniteHits.js +2 -13
  14. package/dist/components/Pagination.d.ts.map +1 -1
  15. package/dist/components/Pagination.js +27 -9
  16. package/dist/components/QuerySuggestions.d.ts +0 -4
  17. package/dist/components/QuerySuggestions.d.ts.map +1 -1
  18. package/dist/components/QuerySuggestions.js +1 -17
  19. package/dist/components/QuerySuggestionsDropdown.d.ts +0 -4
  20. package/dist/components/QuerySuggestionsDropdown.d.ts.map +1 -1
  21. package/dist/components/QuerySuggestionsDropdown.js +32 -33
  22. package/dist/components/RangeInput.d.ts.map +1 -1
  23. package/dist/components/RangeInput.js +6 -6
  24. package/dist/components/RangeSlider.d.ts.map +1 -1
  25. package/dist/components/RangeSlider.js +54 -32
  26. package/dist/components/Recommendations.d.ts +0 -7
  27. package/dist/components/Recommendations.d.ts.map +1 -1
  28. package/dist/components/Recommendations.js +3 -23
  29. package/dist/components/RichQuerySuggestions.d.ts +0 -4
  30. package/dist/components/RichQuerySuggestions.d.ts.map +1 -1
  31. package/dist/components/RichQuerySuggestions.js +40 -35
  32. package/dist/components/SearchBar.d.ts +0 -4
  33. package/dist/components/SearchBar.d.ts.map +1 -1
  34. package/dist/components/SearchBar.js +17 -11
  35. package/dist/components/SearchBarWithSuggestions.js +4 -4
  36. package/dist/components/SearchLayout.d.ts.map +1 -1
  37. package/dist/components/SearchLayout.js +22 -17
  38. package/dist/components/SearchProvider.d.ts.map +1 -1
  39. package/dist/components/SearchProvider.js +1 -3
  40. package/dist/components/SearchResults.d.ts +0 -6
  41. package/dist/components/SearchResults.d.ts.map +1 -1
  42. package/dist/components/SearchResults.js +38 -39
  43. package/dist/components/primitives/ActionButtons.d.ts.map +1 -1
  44. package/dist/components/primitives/ActionButtons.js +34 -10
  45. package/dist/components/primitives/BadgeList.d.ts.map +1 -1
  46. package/dist/components/primitives/BadgeList.js +33 -13
  47. package/dist/components/primitives/ImageDisplay.d.ts.map +1 -1
  48. package/dist/components/primitives/ImageDisplay.js +32 -19
  49. package/dist/components/primitives/ImageZoom.d.ts.map +1 -1
  50. package/dist/components/primitives/ImageZoom.js +85 -30
  51. package/dist/components/primitives/VariantSelector.js +10 -10
  52. package/dist/components/primitives/VariantSwatches.d.ts.map +1 -1
  53. package/dist/components/primitives/VariantSwatches.js +28 -13
  54. package/dist/components/product-page/ProductGallery.d.ts +8 -1
  55. package/dist/components/product-page/ProductGallery.d.ts.map +1 -1
  56. package/dist/components/product-page/ProductGallery.js +2 -2
  57. package/dist/components/section-primitives/SectionItemGrid.d.ts +1 -3
  58. package/dist/components/section-primitives/SectionItemGrid.d.ts.map +1 -1
  59. package/dist/components/section-primitives/SectionItemGrid.js +1 -4
  60. package/dist/components/section-primitives/SectionSearchProvider.d.ts +3 -1
  61. package/dist/components/section-primitives/SectionSearchProvider.d.ts.map +1 -1
  62. package/dist/components/section-primitives/SectionSearchProvider.js +3 -2
  63. package/dist/components/section-primitives/index.d.ts +0 -1
  64. package/dist/components/section-primitives/index.d.ts.map +1 -1
  65. package/dist/components/section-primitives/index.js +0 -1
  66. package/dist/components/suggestions/AmazonDropdown.d.ts.map +1 -1
  67. package/dist/components/suggestions/AmazonDropdown.js +3 -21
  68. package/dist/components/suggestions/GoogleDropdown.d.ts.map +1 -1
  69. package/dist/components/suggestions/GoogleDropdown.js +3 -20
  70. package/dist/components/suggestions/MinimalDropdown.d.ts.map +1 -1
  71. package/dist/components/suggestions/MinimalDropdown.js +2 -2
  72. package/dist/components/suggestions/MobileSheetDropdown.d.ts.map +1 -1
  73. package/dist/components/suggestions/MobileSheetDropdown.js +78 -78
  74. package/dist/components/suggestions/PinterestDropdown.d.ts.map +1 -1
  75. package/dist/components/suggestions/PinterestDropdown.js +41 -41
  76. package/dist/components/suggestions/ShopifyDropdown.d.ts.map +1 -1
  77. package/dist/components/suggestions/ShopifyDropdown.js +40 -41
  78. package/dist/components/suggestions/SpotlightDropdown.d.ts.map +1 -1
  79. package/dist/components/suggestions/SpotlightDropdown.js +2 -3
  80. package/dist/components/suggestions/SuggestionSearchBar.d.ts.map +1 -1
  81. package/dist/components/suggestions/SuggestionSearchBar.js +2 -15
  82. package/dist/components/suggestions/types.d.ts +0 -6
  83. package/dist/components/suggestions/types.d.ts.map +1 -1
  84. package/dist/components/suggestions-primitives/DropdownPanel.d.ts.map +1 -1
  85. package/dist/components/suggestions-primitives/DropdownPanel.js +15 -2
  86. package/dist/components/suggestions-primitives/ItemCard.d.ts.map +1 -1
  87. package/dist/components/suggestions-primitives/ItemCard.js +48 -11
  88. package/dist/components/suggestions-primitives/ItemGrid.d.ts.map +1 -1
  89. package/dist/components/suggestions-primitives/ItemGrid.js +18 -5
  90. package/dist/components/suggestions-primitives/ProductCard.d.ts.map +1 -1
  91. package/dist/components/suggestions-primitives/ProductCard.js +36 -12
  92. package/dist/components/suggestions-primitives/ProductCardLayouts.d.ts.map +1 -1
  93. package/dist/components/suggestions-primitives/ProductCardLayouts.js +52 -20
  94. package/dist/components/suggestions-primitives/ProductGrid.d.ts.map +1 -1
  95. package/dist/components/suggestions-primitives/ProductGrid.js +8 -3
  96. package/dist/components/suggestions-primitives/RecentSearchesList.d.ts.map +1 -1
  97. package/dist/components/suggestions-primitives/RecentSearchesList.js +12 -5
  98. package/dist/components/suggestions-primitives/SearchInput.d.ts.map +1 -1
  99. package/dist/components/suggestions-primitives/SearchInput.js +29 -10
  100. package/dist/components/suggestions-primitives/SuggestionItem.d.ts.map +1 -1
  101. package/dist/components/suggestions-primitives/SuggestionItem.js +8 -3
  102. package/dist/components/suggestions-primitives/SuggestionList.d.ts +1 -8
  103. package/dist/components/suggestions-primitives/SuggestionList.d.ts.map +1 -1
  104. package/dist/components/suggestions-primitives/SuggestionList.js +1 -7
  105. package/dist/components/suggestions-primitives/TrendingList.d.ts.map +1 -1
  106. package/dist/components/suggestions-primitives/TrendingList.js +14 -7
  107. package/dist/components/suggestions-primitives/index.d.ts +1 -3
  108. package/dist/components/suggestions-primitives/index.d.ts.map +1 -1
  109. package/dist/components/suggestions-primitives/index.js +1 -2
  110. package/dist/docsearch/components/DocSearch.d.ts.map +1 -1
  111. package/dist/docsearch/components/DocSearch.js +1 -1
  112. package/dist/docsearch/components/Results.d.ts +1 -3
  113. package/dist/docsearch/components/Results.d.ts.map +1 -1
  114. package/dist/docsearch/components/Results.js +1 -9
  115. package/dist/docsearch/components/SearchBox.d.ts +1 -2
  116. package/dist/docsearch/components/SearchBox.d.ts.map +1 -1
  117. package/dist/docsearch/components/SearchBox.js +4 -6
  118. package/dist/docsearch/hooks/useSeekoraSearch.d.ts.map +1 -1
  119. package/dist/docsearch/hooks/useSeekoraSearch.js +6 -0
  120. package/dist/docsearch/types.d.ts +0 -1
  121. package/dist/docsearch/types.d.ts.map +1 -1
  122. package/dist/docsearch.css +2 -5
  123. package/dist/hooks/useClickTracking.d.ts.map +1 -1
  124. package/dist/hooks/useClickTracking.js +4 -11
  125. package/dist/hooks/useExperiment.d.ts.map +1 -1
  126. package/dist/hooks/useExperiment.js +10 -33
  127. package/dist/hooks/useFilters.d.ts +27 -0
  128. package/dist/hooks/useFilters.d.ts.map +1 -0
  129. package/dist/hooks/useFilters.js +66 -0
  130. package/dist/index.d.ts +10 -5
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +4 -2
  133. package/dist/index.umd.js +1 -1
  134. package/dist/src/index.d.ts +166 -81
  135. package/dist/src/index.esm.js +2141 -1048
  136. package/dist/src/index.esm.js.map +1 -1
  137. package/dist/src/index.js +2142 -1049
  138. package/dist/src/index.js.map +1 -1
  139. package/dist/utils/responsive.d.ts +130 -0
  140. package/dist/utils/responsive.d.ts.map +1 -0
  141. package/dist/utils/responsive.js +231 -0
  142. package/package.json +7 -7
  143. package/src/docsearch/docsearch.css +2 -5
@@ -8,7 +8,7 @@ import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react'
8
8
  import { useSearchContext } from './SearchProvider';
9
9
  import { useSearchState } from '../hooks/useSearchState';
10
10
  import { clsx } from 'clsx';
11
- export const InfiniteHits = ({ renderHit, renderEmpty, showInitialLoading = false, renderLoading, renderShowMore, showMoreButton = true, useInfiniteScroll = false, scrollThreshold = 0.1, fieldMapping, showMoreLabel = 'Show more', loadingLabel = 'Loading...', onHitClick, className, style, theme: customTheme, syncWithState = true, }) => {
11
+ export const InfiniteHits = ({ renderHit, renderEmpty, renderShowMore, showMoreButton = true, useInfiniteScroll = false, scrollThreshold = 0.1, fieldMapping, showMoreLabel = 'Show more', onHitClick, className, style, theme: customTheme, syncWithState = true, }) => {
12
12
  const { theme, stateManager } = useSearchContext();
13
13
  const { results, loading, currentPage, setPage } = useSearchState();
14
14
  const infiniteHitsTheme = customTheme || {};
@@ -140,12 +140,6 @@ export const InfiniteHits = ({ renderHit, renderEmpty, showInitialLoading = fals
140
140
  textAlign: 'center',
141
141
  color: theme.colors.textSecondary,
142
142
  } }, "No results found"));
143
- // Default loading state
144
- const defaultRenderLoading = () => (React.createElement("div", { className: infiniteHitsTheme.loading, style: {
145
- padding: theme.spacing.medium,
146
- textAlign: 'center',
147
- color: theme.colors.textSecondary,
148
- } }, loadingLabel));
149
143
  // Default "Show More" button
150
144
  const defaultRenderShowMore = () => (React.createElement("button", { type: "button", onClick: handleShowMore, disabled: isLastPage || isLoadingMore, className: clsx(infiniteHitsTheme.loadMore, (isLastPage || isLoadingMore) && infiniteHitsTheme.loadMoreDisabled), style: {
151
145
  display: 'block',
@@ -162,11 +156,7 @@ export const InfiniteHits = ({ renderHit, renderEmpty, showInitialLoading = fals
162
156
  : theme.borderRadius.medium,
163
157
  cursor: isLastPage || isLoadingMore ? 'not-allowed' : 'pointer',
164
158
  transition: theme.transitions?.fast || '150ms ease-in-out',
165
- } }, isLoadingMore ? loadingLabel : isLastPage ? 'No more results' : showMoreLabel));
166
- // Initial loading state (only when showInitialLoading: default no loading screen)
167
- if (loading && accumulatedHits.length === 0 && showInitialLoading) {
168
- return (React.createElement("div", { className: clsx(infiniteHitsTheme.root, className), style: style }, renderLoading ? renderLoading() : defaultRenderLoading()));
169
- }
159
+ } }, isLastPage ? 'No more results' : showMoreLabel));
170
160
  if (loading && accumulatedHits.length === 0) {
171
161
  return React.createElement("div", { className: clsx(infiniteHitsTheme.root, className), style: style });
172
162
  }
@@ -179,6 +169,5 @@ export const InfiniteHits = ({ renderHit, renderEmpty, showInitialLoading = fals
179
169
  showMoreButton && !useInfiniteScroll && !isLastPage && (renderShowMore
180
170
  ? renderShowMore({ isLoading: isLoadingMore, isLastPage, onClick: handleShowMore })
181
171
  : defaultRenderShowMore()),
182
- isLoadingMore && (renderLoading ? renderLoading() : defaultRenderLoading()),
183
172
  useInfiniteScroll && !isLastPage && (React.createElement("div", { ref: sentinelRef, className: infiniteHitsTheme.sentinel, style: { height: '1px', visibility: 'hidden' }, "aria-hidden": "true" }))));
184
173
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../src/components/Pagination.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7F,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC9C,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AASD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAkbhD,CAAC"}
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../src/components/Pagination.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,8BAA8B;IAC9B,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI,CAAC;IAChC,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iCAAiC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,KAAK,CAAC,SAAS,CAAC;IAC7F,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC9C,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmBD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA0bhD,CAAC"}
@@ -16,16 +16,30 @@ import React from 'react';
16
16
  import { useSearchContext } from './SearchProvider';
17
17
  import { useSearchState } from '../hooks/useSearchState';
18
18
  import { clsx } from 'clsx';
19
- /** Size-specific style tokens */
20
- const SIZE_TOKENS = {
21
- small: { paddingKey: 'small', fontSizeKey: 'small', minWidth: '32px' },
22
- medium: { paddingKey: 'small', fontSizeKey: 'medium', minWidth: '40px' },
23
- large: { paddingKey: 'medium', fontSizeKey: 'large', minWidth: '48px' },
19
+ import { useIsMobile } from '../utils/responsive';
20
+ /** Size-specific style tokens (responsive) */
21
+ const getSizeTokens = (size, isMobile) => {
22
+ if (isMobile) {
23
+ // Larger touch targets on mobile
24
+ return {
25
+ small: { paddingKey: 'small', fontSizeKey: 'small', minWidth: '40px', minHeight: '40px' },
26
+ medium: { paddingKey: 'small', fontSizeKey: 'medium', minWidth: '44px', minHeight: '44px' },
27
+ large: { paddingKey: 'medium', fontSizeKey: 'large', minWidth: '48px', minHeight: '48px' },
28
+ }[size];
29
+ }
30
+ return {
31
+ small: { paddingKey: 'small', fontSizeKey: 'small', minWidth: '32px', minHeight: '32px' },
32
+ medium: { paddingKey: 'small', fontSizeKey: 'medium', minWidth: '40px', minHeight: '40px' },
33
+ large: { paddingKey: 'medium', fontSizeKey: 'large', minWidth: '48px', minHeight: '48px' },
34
+ }[size];
24
35
  };
25
- export const Pagination = ({ results: resultsProp, currentPage: currentPageProp, itemsPerPage: itemsPerPageProp, totalPages: totalPagesProp, onPageChange, maxPages = 7, showFirstLast = true, showPrevNext = true, renderPageButton, className, style, theme: customTheme, variant = 'numbered', loadMoreText = 'Load More', size = 'medium', showPageInfo, previousLabel = 'Previous', nextLabel = 'Next', }) => {
36
+ export const Pagination = ({ results: resultsProp, currentPage: currentPageProp, itemsPerPage: itemsPerPageProp, totalPages: totalPagesProp, onPageChange, maxPages: maxPagesProp = 7, showFirstLast = true, showPrevNext = true, renderPageButton, className, style, theme: customTheme, variant = 'numbered', loadMoreText = 'Load More', size = 'medium', showPageInfo, previousLabel = 'Previous', nextLabel = 'Next', }) => {
26
37
  const { theme } = useSearchContext();
27
38
  const { results: stateResults, currentPage: stateCurrentPage, setPage } = useSearchState();
28
39
  const paginationTheme = customTheme || {};
40
+ const isMobile = useIsMobile();
41
+ // Responsive maxPages - show fewer pages on mobile
42
+ const maxPages = isMobile ? Math.min(maxPagesProp, 5) : maxPagesProp;
29
43
  // Use results from prop if provided, otherwise from state manager
30
44
  const results = resultsProp || stateResults;
31
45
  // Use currentPage from prop if provided, otherwise from state manager
@@ -49,8 +63,8 @@ export const Pagination = ({ results: resultsProp, currentPage: currentPageProp,
49
63
  const resolvedShowPageInfo = showPageInfo !== undefined
50
64
  ? showPageInfo
51
65
  : variant === 'simple';
52
- // Size tokens
53
- const sizeTokens = SIZE_TOKENS[size];
66
+ // Size tokens (responsive)
67
+ const sizeTokens = getSizeTokens(size, isMobile);
54
68
  // CSS variable aware helpers — allow overrides via custom properties
55
69
  const cssVarBg = 'var(--seekora-pagination-bg, ' + theme.colors.background + ')';
56
70
  const cssVarColor = 'var(--seekora-pagination-color, ' + theme.colors.text + ')';
@@ -70,7 +84,7 @@ export const Pagination = ({ results: resultsProp, currentPage: currentPageProp,
70
84
  };
71
85
  const defaultRenderPageButton = (page, isActive, isDisabled) => (React.createElement("button", { type: "button", disabled: isDisabled, onClick: () => !isDisabled && handlePageChange(page), "aria-current": isActive ? 'page' : undefined, "aria-label": `Page ${page}`, className: clsx(paginationTheme.item, isActive && paginationTheme.itemActive, isDisabled && paginationTheme.itemDisabled), style: {
72
86
  padding: theme.spacing[sizeTokens.paddingKey],
73
- margin: `0 ${theme.spacing.small}`,
87
+ margin: isMobile ? `0 4px` : `0 ${theme.spacing.small}`,
74
88
  border: `1px solid ${cssVarBorder}`,
75
89
  borderRadius: cssVarRadius,
76
90
  backgroundColor: isActive ? cssVarActiveBg : cssVarBg,
@@ -79,6 +93,10 @@ export const Pagination = ({ results: resultsProp, currentPage: currentPageProp,
79
93
  opacity: isDisabled ? 0.5 : 1,
80
94
  fontSize: theme.typography.fontSize[sizeTokens.fontSizeKey],
81
95
  minWidth: sizeTokens.minWidth,
96
+ minHeight: sizeTokens.minHeight,
97
+ display: 'inline-flex',
98
+ alignItems: 'center',
99
+ justifyContent: 'center',
82
100
  ...(isActive && {
83
101
  fontWeight: 'bold',
84
102
  }),
@@ -16,7 +16,6 @@ export interface QuerySuggestionsTheme {
16
16
  suggestionItem?: string;
17
17
  suggestionItemHover?: string;
18
18
  suggestionItemActive?: string;
19
- loadingState?: string;
20
19
  emptyState?: string;
21
20
  }
22
21
  export interface QuerySuggestionsProps {
@@ -26,9 +25,6 @@ export interface QuerySuggestionsProps {
26
25
  minQueryLength?: number;
27
26
  onSuggestionClick?: (suggestion: string) => void;
28
27
  renderSuggestion?: (suggestion: SuggestionItem, index: number) => React.ReactNode;
29
- /** Show loading state when fetching and no previous suggestions (default false: show previous results until new render) */
30
- showLoadingState?: boolean;
31
- renderLoading?: () => React.ReactNode;
32
28
  renderEmpty?: () => React.ReactNode;
33
29
  showTitle?: boolean;
34
30
  title?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"QuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/QuerySuggestions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAMxC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAClF,2HAA2H;IAC3H,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA0K5D,CAAC"}
1
+ {"version":3,"file":"QuerySuggestions.d.ts","sourceRoot":"","sources":["../../src/components/QuerySuggestions.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAMxC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IAClF,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,KAAK,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAsI5D,CAAC"}
@@ -7,7 +7,7 @@ import React, { useState } from 'react';
7
7
  import { useSearchContext } from './SearchProvider';
8
8
  import { useQuerySuggestions } from '../hooks/useQuerySuggestions';
9
9
  import { clsx } from 'clsx';
10
- export const QuerySuggestions = ({ query = '', maxSuggestions = 10, debounceMs = 300, minQueryLength = 2, onSuggestionClick, renderSuggestion, showLoadingState = false, renderLoading, renderEmpty, showTitle = false, title = 'Suggestions', className, style, theme: customTheme, }) => {
10
+ export const QuerySuggestions = ({ query = '', maxSuggestions = 10, debounceMs = 300, minQueryLength = 2, onSuggestionClick, renderSuggestion, renderEmpty, showTitle = false, title = 'Suggestions', className, style, theme: customTheme, }) => {
11
11
  const { client, theme } = useSearchContext();
12
12
  const [selectedIndex, setSelectedIndex] = useState(-1);
13
13
  const { suggestions, loading, error } = useQuerySuggestions({
@@ -25,11 +25,6 @@ export const QuerySuggestions = ({ query = '', maxSuggestions = 10, debounceMs =
25
25
  "(",
26
26
  suggestion.count,
27
27
  ")"))));
28
- const defaultRenderLoading = () => (React.createElement("div", { style: {
29
- padding: theme.spacing.medium,
30
- textAlign: 'center',
31
- color: theme.colors.text,
32
- } }, "Loading suggestions..."));
33
28
  const defaultRenderEmpty = () => (React.createElement("div", { style: {
34
29
  padding: theme.spacing.medium,
35
30
  textAlign: 'center',
@@ -44,17 +39,6 @@ export const QuerySuggestions = ({ query = '', maxSuggestions = 10, debounceMs =
44
39
  if (query.length < minQueryLength) {
45
40
  return null;
46
41
  }
47
- // When loading with no previous results, show loading only if showLoadingState (default: show previous results, no loading screen)
48
- if (loading && displayedSuggestions.length === 0 && showLoadingState) {
49
- return (React.createElement("div", { className: clsx(suggestionsTheme.container, className), style: style },
50
- showTitle && (React.createElement("div", { className: suggestionsTheme.title, style: {
51
- fontSize: theme.typography.fontSize.large,
52
- fontWeight: 'bold',
53
- marginBottom: theme.spacing.medium,
54
- color: theme.colors.text,
55
- } }, title)),
56
- renderLoading ? renderLoading() : defaultRenderLoading()));
57
- }
58
42
  if (error || (!loading && displayedSuggestions.length === 0)) {
59
43
  return (React.createElement("div", { className: clsx(suggestionsTheme.container, className), style: style },
60
44
  showTitle && (React.createElement("div", { className: suggestionsTheme.title, style: {
@@ -28,8 +28,6 @@ export interface QuerySuggestionsDropdownProps extends QuerySuggestionsEventHand
28
28
  maxRecentSearches?: number;
29
29
  /** Show suggestion counts */
30
30
  showCounts?: boolean;
31
- /** Show loading state (default false: show previous results until new results render) */
32
- showLoading?: boolean;
33
31
  /** Show empty state when no results */
34
32
  showEmptyState?: boolean;
35
33
  /** Highlight configuration */
@@ -46,8 +44,6 @@ export interface QuerySuggestionsDropdownProps extends QuerySuggestionsEventHand
46
44
  renderSuggestion?: (suggestion: SuggestionItem, index: number, isActive: boolean, highlight: (text: string) => React.ReactNode) => React.ReactNode;
47
45
  /** Custom render for recent search item */
48
46
  renderRecentSearch?: (search: RecentSearch, index: number, isActive: boolean) => React.ReactNode;
49
- /** Custom render for loading state */
50
- renderLoading?: () => React.ReactNode;
51
47
  /** Custom render for empty state */
52
48
  renderEmpty?: () => React.ReactNode;
53
49
  /** Custom footer content */
@@ -1 +1 @@
1
- {"version":3,"file":"QuerySuggestionsDropdown.d.ts","sourceRoot":"","sources":["../../src/components/QuerySuggestionsDropdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,0BAA0B,EAC1B,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,6BAA6B,EAC9B,MAAM,0BAA0B,CAAC;AAMlC,MAAM,WAAW,6BAA8B,SAAQ,6BAA6B;IAClF,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yFAAyF;IACzF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,wCAAwC;IACxC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,8BAA8B;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,yBAAyB;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,wBAAwB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CACjB,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,KACzC,KAAK,CAAC,SAAS,CAAC;IACrB,2CAA2C;IAC3C,kBAAkB,CAAC,EAAE,CACnB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,KACd,KAAK,CAAC,SAAS,CAAC;IACrB,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACtC,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAChC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,6BAA6B;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,sBAAsB;IACtB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,uBAAuB;IACvB,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,4BAA4B;IAC5B,aAAa,EAAE,MAAM,MAAM,CAAC;CAC7B;AAsKD,eAAO,MAAM,wBAAwB,mHAmanC,CAAC;AAEH,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"QuerySuggestionsDropdown.d.ts","sourceRoot":"","sources":["../../src/components/QuerySuggestionsDropdown.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAQN,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,0BAA0B,EAC1B,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,6BAA6B,EAC9B,MAAM,0BAA0B,CAAC;AAuBlC,MAAM,WAAW,6BAA8B,SAAQ,6BAA6B;IAClF,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qCAAqC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,yCAAyC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,wCAAwC;IACxC,WAAW,CAAC,EAAE,iBAAiB,CAAC;IAChC,8BAA8B;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,yBAAyB;IACzB,UAAU,CAAC,EAAE,0BAA0B,CAAC;IACxC,wBAAwB;IACxB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,CACjB,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,KACzC,KAAK,CAAC,SAAS,CAAC;IACrB,2CAA2C;IAC3C,kBAAkB,CAAC,EAAE,CACnB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,OAAO,KACd,KAAK,CAAC,SAAS,CAAC;IACrB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACpC,4BAA4B;IAC5B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAChC,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;IAC7C,6BAA6B;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,0BAA0B;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,uCAAuC;IACvC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gCAAgC;IAChC,gBAAgB,EAAE,MAAM,IAAI,CAAC;IAC7B,sBAAsB;IACtB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,uBAAuB;IACvB,cAAc,EAAE,MAAM,MAAM,CAAC;IAC7B,4BAA4B;IAC5B,aAAa,EAAE,MAAM,MAAM,CAAC;CAC7B;AAsJD,eAAO,MAAM,wBAAwB,mHAqZnC,CAAC;AAEH,eAAe,wBAAwB,CAAC"}
@@ -14,13 +14,27 @@ import { useSearchContext } from './SearchProvider';
14
14
  import { useQuerySuggestionsEnhanced } from '../hooks/useQuerySuggestionsEnhanced';
15
15
  import { clsx } from 'clsx';
16
16
  // ============================================================================
17
+ // Constants
18
+ // ============================================================================
19
+ const TRANSITIONS = {
20
+ fast: '150ms ease-in-out',
21
+ normal: '200ms ease-in-out',
22
+ slow: '300ms ease-in-out',
23
+ };
24
+ const BORDER_RADIUS = {
25
+ sm: 4,
26
+ md: 6,
27
+ lg: 8,
28
+ full: 9999,
29
+ };
30
+ // ============================================================================
17
31
  // Styles
18
32
  // ============================================================================
19
33
  const defaultStyles = {
20
34
  container: {
21
- backgroundColor: 'var(--seekora-bg-surface, #ffffff)',
22
- border: '1px solid var(--seekora-border-color, #e5e7eb)',
23
- borderRadius: 'var(--seekora-border-radius, 8px)',
35
+ backgroundColor: 'var(--seekora-bg-surface, transparent)',
36
+ border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
37
+ borderRadius: `var(--seekora-border-radius, ${BORDER_RADIUS.lg}px)`,
24
38
  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))',
25
39
  maxHeight: '400px',
26
40
  overflowY: 'auto',
@@ -32,7 +46,7 @@ const defaultStyles = {
32
46
  sectionTitle: {
33
47
  fontSize: '12px',
34
48
  fontWeight: 600,
35
- color: 'var(--seekora-text-secondary, #6b7280)',
49
+ color: 'var(--seekora-text-secondary, inherit)',
36
50
  textTransform: 'uppercase',
37
51
  letterSpacing: '0.05em',
38
52
  padding: '8px 16px 4px',
@@ -43,9 +57,9 @@ const defaultStyles = {
43
57
  alignItems: 'center',
44
58
  padding: '10px 16px',
45
59
  cursor: 'pointer',
46
- transition: 'background-color 150ms ease',
60
+ transition: `background-color ${TRANSITIONS.fast}`,
47
61
  fontSize: '14px',
48
- color: 'var(--seekora-text-primary, #111827)',
62
+ color: 'var(--seekora-text-primary, inherit)',
49
63
  gap: '12px',
50
64
  },
51
65
  suggestionItemActive: {
@@ -65,10 +79,10 @@ const defaultStyles = {
65
79
  },
66
80
  highlight: {
67
81
  fontWeight: 600,
68
- color: 'var(--seekora-text-primary, #111827)',
82
+ color: 'var(--seekora-text-primary, inherit)',
69
83
  backgroundColor: 'var(--seekora-highlight-bg, #fef3c7)',
70
84
  padding: '0 2px',
71
- borderRadius: '2px',
85
+ borderRadius: `${BORDER_RADIUS.sm / 2}px`,
72
86
  },
73
87
  recentIcon: {
74
88
  width: '16px',
@@ -78,46 +92,37 @@ const defaultStyles = {
78
92
  },
79
93
  removeButton: {
80
94
  padding: '4px',
81
- borderRadius: '4px',
95
+ borderRadius: `${BORDER_RADIUS.sm}px`,
82
96
  border: 'none',
83
97
  background: 'transparent',
84
98
  cursor: 'pointer',
85
99
  color: 'var(--seekora-text-secondary, #9ca3af)',
86
100
  opacity: 0,
87
- transition: 'opacity 150ms ease, color 150ms ease',
101
+ transition: `opacity ${TRANSITIONS.fast}, color ${TRANSITIONS.fast}`,
88
102
  },
89
103
  removeButtonVisible: {
90
104
  opacity: 1,
91
105
  },
92
- loadingState: {
93
- display: 'flex',
94
- alignItems: 'center',
95
- justifyContent: 'center',
96
- padding: '24px 16px',
97
- color: 'var(--seekora-text-secondary, #6b7280)',
98
- fontSize: '14px',
99
- gap: '8px',
100
- },
101
106
  emptyState: {
102
107
  display: 'flex',
103
108
  flexDirection: 'column',
104
109
  alignItems: 'center',
105
110
  justifyContent: 'center',
106
111
  padding: '24px 16px',
107
- color: 'var(--seekora-text-secondary, #6b7280)',
112
+ color: 'var(--seekora-text-secondary, inherit)',
108
113
  fontSize: '14px',
109
114
  textAlign: 'center',
110
115
  },
111
116
  divider: {
112
117
  height: '1px',
113
- backgroundColor: 'var(--seekora-border-color, #e5e7eb)',
118
+ backgroundColor: 'var(--seekora-border-color, rgba(128,128,128,0.2))',
114
119
  margin: '4px 0',
115
120
  },
116
121
  footer: {
117
- borderTop: '1px solid var(--seekora-border-color, #e5e7eb)',
122
+ borderTop: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
118
123
  padding: '8px 16px',
119
124
  fontSize: '12px',
120
- color: 'var(--seekora-text-secondary, #6b7280)',
125
+ color: 'var(--seekora-text-secondary, inherit)',
121
126
  display: 'flex',
122
127
  alignItems: 'center',
123
128
  justifyContent: 'space-between',
@@ -135,9 +140,9 @@ const defaultStyles = {
135
140
  minWidth: '20px',
136
141
  height: '18px',
137
142
  padding: '0 4px',
138
- borderRadius: '3px',
139
- backgroundColor: 'var(--seekora-bg-secondary, #f3f4f6)',
140
- border: '1px solid var(--seekora-border-color, #e5e7eb)',
143
+ borderRadius: `${BORDER_RADIUS.sm - 1}px`,
144
+ backgroundColor: 'var(--seekora-bg-secondary, rgba(255, 255, 255, 0.1))',
145
+ border: '1px solid var(--seekora-border-color, rgba(128,128,128,0.2))',
141
146
  fontSize: '10px',
142
147
  fontWeight: 500,
143
148
  },
@@ -151,14 +156,11 @@ const ClockIcon = ({ className, style }) => (React.createElement("svg", { classN
151
156
  React.createElement("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z", clipRule: "evenodd" })));
152
157
  const CloseIcon = ({ className, style }) => (React.createElement("svg", { className: className, style: style, viewBox: "0 0 20 20", fill: "currentColor", width: "16", height: "16" },
153
158
  React.createElement("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd" })));
154
- const LoadingSpinner = ({ style }) => (React.createElement("svg", { style: { animation: 'spin 1s linear infinite', ...style }, viewBox: "0 0 24 24", width: "20", height: "20" },
155
- React.createElement("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", fill: "none", opacity: "0.25" }),
156
- React.createElement("path", { fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })));
157
159
  // ============================================================================
158
160
  // Component
159
161
  // ============================================================================
160
162
  export const QuerySuggestionsDropdown = forwardRef(function QuerySuggestionsDropdown(props, ref) {
161
- const { query, isOpen = true, maxSuggestions = 8, minQueryLength = 1, debounceMs = 200, showRecentSearches = true, maxRecentSearches = 5, showCounts = true, showLoading = false, showEmptyState = true, highlight = { enabled: true, preTag: '<mark>', postTag: '</mark>' }, keyboardNav = { enabled: true }, animation = { enabled: true, duration: 150, entrance: 'fade' }, classNames = {}, style, renderSuggestion, renderRecentSearch, renderLoading, renderEmpty, footer, position = 'absolute', width = '100%', zIndex = 1000, closeOnClickOutside = true, closeOnEscape = true, ariaLabel = 'Search suggestions', onSuggestionSelect, onRecentSearchClick, onRecentSearchRemove, onOpen, onClose, onNavigate, } = props;
163
+ const { query, isOpen = true, maxSuggestions = 8, minQueryLength = 1, debounceMs = 200, showRecentSearches = true, maxRecentSearches = 5, showCounts = true, showEmptyState = true, highlight = { enabled: true, preTag: '<mark>', postTag: '</mark>' }, keyboardNav = { enabled: true }, animation = { enabled: true, duration: 150, entrance: 'fade' }, classNames = {}, style, renderSuggestion, renderRecentSearch, renderEmpty, footer, position = 'absolute', width = '100%', zIndex = 1000, closeOnClickOutside = true, closeOnEscape = true, ariaLabel = 'Search suggestions', onSuggestionSelect, onRecentSearchClick, onRecentSearchRemove, onOpen, onClose, onNavigate, } = props;
162
164
  const { client, theme } = useSearchContext();
163
165
  const containerRef = useRef(null);
164
166
  const [activeIndex, setActiveIndex] = useState(-1);
@@ -340,9 +342,6 @@ export const QuerySuggestionsDropdown = forwardRef(function QuerySuggestionsDrop
340
342
  ...animationStyle,
341
343
  ...style,
342
344
  } },
343
- loading && showLoading && (React.createElement("div", { className: classNames.loadingState, style: defaultStyles.loadingState }, renderLoading ? renderLoading() : (React.createElement(React.Fragment, null,
344
- React.createElement(LoadingSpinner, null),
345
- React.createElement("span", null, "Searching..."))))),
346
345
  showRecent && (React.createElement("div", { className: clsx('seekora-suggestions-section', classNames.section, classNames.recentSearches) },
347
346
  React.createElement("div", { className: classNames.sectionTitle, style: defaultStyles.sectionTitle }, "Recent Searches"),
348
347
  recentSearches.slice(0, maxRecentSearches).map((search, index) => {
@@ -1 +1 @@
1
- {"version":3,"file":"RangeInput.d.ts","sourceRoot":"","sources":["../../src/components/RangeInput.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAoD,MAAM,OAAO,CAAC;AAKzE,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC3E,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QACzB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;QACxB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;QACxB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;QACjD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;QACjD,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,wBAAwB;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,8DAA8D;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA8BD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAsQhD,CAAC"}
1
+ {"version":3,"file":"RangeInput.d.ts","sourceRoot":"","sources":["../../src/components/RangeInput.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAKhE,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC3E,6BAA6B;IAC7B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QACzB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;QACxB,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;QACxB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;QACjD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;QACjD,OAAO,EAAE,MAAM,IAAI,CAAC;KACrB,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,wBAAwB;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,8DAA8D;IAC9D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA8BD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAuQhD,CAAC"}
@@ -4,7 +4,7 @@
4
4
  * Displays a range input for filtering numeric values (e.g., price range)
5
5
  * Integrates with SearchStateManager for automatic state sync
6
6
  */
7
- import React, { useState, useCallback, useEffect, useMemo } from 'react';
7
+ import React, { useState, useCallback, useEffect } from 'react';
8
8
  import { useSearchContext } from './SearchProvider';
9
9
  import { useSearchState } from '../hooks/useSearchState';
10
10
  import { clsx } from 'clsx';
@@ -35,11 +35,11 @@ export const RangeInput = ({ field, label, min, max, currentMin: currentMinProp,
35
35
  const { refinements, addRefinement, removeRefinement } = useSearchState();
36
36
  const rangeInputTheme = customTheme || {};
37
37
  // Parse current range from StateManager
38
- const stateRange = useMemo(() => {
39
- if (!syncWithState)
40
- return { min: undefined, max: undefined };
41
- return parseRangeFromRefinements(refinements, field);
42
- }, [syncWithState, refinements, field]);
38
+ // NOTE: computed every render (no useMemo) because the state manager mutates
39
+ // the refinements array in place — the reference never changes.
40
+ const stateRange = !syncWithState
41
+ ? { min: undefined, max: undefined }
42
+ : parseRangeFromRefinements(refinements, field);
43
43
  const [internalMin, setInternalMin] = useState(currentMinProp ?? stateRange.min);
44
44
  const [internalMax, setInternalMax] = useState(currentMaxProp ?? stateRange.max);
45
45
  const [appliedMin, setAppliedMin] = useState(currentMinProp ?? stateRange.min);
@@ -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,CAqUlD,CAAC"}
1
+ {"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../src/components/RangeSlider.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAYxE,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,CAsVlD,CAAC"}
@@ -4,18 +4,29 @@
4
4
  * Visual slider for numeric range filtering
5
5
  * Alternative to RangeInput for a more interactive UX
6
6
  */
7
- import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';
7
+ import React, { useState, useCallback, useEffect, useRef } from 'react';
8
8
  import { useSearchContext } from './SearchProvider';
9
9
  import { useSearchState } from '../hooks/useSearchState';
10
10
  import { clsx } from 'clsx';
11
+ const SHADOWS = {
12
+ sm: '0 1px 2px rgba(0,0,0,0.05)',
13
+ md: '0 2px 4px rgba(0,0,0,0.1)',
14
+ lg: '0 4px 6px rgba(0,0,0,0.1)',
15
+ xl: '0 10px 15px rgba(0,0,0,0.1)',
16
+ };
11
17
  export 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, }) => {
12
18
  const { theme } = useSearchContext();
13
19
  const { refinements, addRefinement, removeRefinement } = useSearchState();
14
20
  const rangeSliderTheme = customTheme || {};
21
+ const thumbClass = rangeSliderTheme.thumb || 'seekora-range-slider__thumb';
15
22
  // Parse current range from StateManager
16
- const stateRange = useMemo(() => {
17
- if (!syncWithState)
18
- return { min: undefined, max: undefined };
23
+ // NOTE: computed every render (no useMemo) because the state manager mutates
24
+ // the refinements array in place — the reference never changes.
25
+ let stateRange;
26
+ if (!syncWithState) {
27
+ stateRange = { min: undefined, max: undefined };
28
+ }
29
+ else {
19
30
  let minVal;
20
31
  let maxVal;
21
32
  refinements.forEach(r => {
@@ -28,15 +39,17 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
28
39
  maxVal = parseFloat(maxMatch[1]);
29
40
  }
30
41
  });
31
- return { min: minVal, max: maxVal };
32
- }, [syncWithState, refinements, field]);
42
+ stateRange = { min: minVal, max: maxVal };
43
+ }
33
44
  const [internalMin, setInternalMin] = useState(currentMinProp ?? stateRange.min ?? min);
34
45
  const [internalMax, setInternalMax] = useState(currentMaxProp ?? stateRange.max ?? max);
35
- const [isDragging, setIsDragging] = useState(false);
46
+ const isDraggingRef = useRef(false);
36
47
  const debounceRef = useRef(null);
37
- // Sync with StateManager changes
48
+ const pendingMinRef = useRef(internalMin);
49
+ const pendingMaxRef = useRef(internalMax);
50
+ // Sync with StateManager changes (only when stateRange actually changes, not on drag)
38
51
  useEffect(() => {
39
- if (syncWithState && !isDragging) {
52
+ if (syncWithState && !isDraggingRef.current) {
40
53
  if (stateRange.min !== undefined)
41
54
  setInternalMin(stateRange.min);
42
55
  else
@@ -46,7 +59,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
46
59
  else
47
60
  setInternalMax(max);
48
61
  }
49
- }, [syncWithState, stateRange.min, stateRange.max, isDragging, min, max]);
62
+ }, [syncWithState, stateRange.min, stateRange.max, min, max]);
50
63
  // Update StateManager with range refinements
51
64
  const updateStateManager = useCallback((minVal, maxVal) => {
52
65
  if (!syncWithState)
@@ -57,24 +70,24 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
57
70
  removeRefinement(field, r.value, false);
58
71
  }
59
72
  });
60
- // Add new range refinements
61
- if (minVal > min) {
73
+ // Add new range refinements — trigger search on the last one added
74
+ const setMin = minVal > min;
75
+ const setMax = maxVal < max;
76
+ if (setMin && setMax) {
62
77
  addRefinement(field, `>=${minVal}`, false);
78
+ addRefinement(field, `<=${maxVal}`, true);
63
79
  }
64
- if (maxVal < max) {
65
- addRefinement(field, `<=${maxVal}`, minVal <= min); // Trigger search if only max is set
66
- }
67
- if (minVal > min && maxVal >= max) {
68
- // Trigger search after setting min
80
+ else if (setMin) {
69
81
  addRefinement(field, `>=${minVal}`, true);
70
82
  }
71
- else if (minVal > min || maxVal < max) {
72
- // If both are set, we need to trigger search
73
- // already triggered above
83
+ else if (setMax) {
84
+ addRefinement(field, `<=${maxVal}`, true);
74
85
  }
75
86
  }, [syncWithState, field, refinements, addRefinement, removeRefinement, min, max]);
76
- // Debounced update
87
+ // Debounced update (during drag only)
77
88
  const debouncedUpdate = useCallback((minVal, maxVal) => {
89
+ pendingMinRef.current = minVal;
90
+ pendingMaxRef.current = maxVal;
78
91
  if (debounceRef.current) {
79
92
  clearTimeout(debounceRef.current);
80
93
  }
@@ -89,19 +102,28 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
89
102
  const handleMinChange = (e) => {
90
103
  const value = Math.min(Number(e.target.value), internalMax - step);
91
104
  setInternalMin(value);
92
- setIsDragging(true);
105
+ isDraggingRef.current = true;
93
106
  debouncedUpdate(value, internalMax);
94
107
  };
95
108
  // Handle max slider change
96
109
  const handleMaxChange = (e) => {
97
110
  const value = Math.max(Number(e.target.value), internalMin + step);
98
111
  setInternalMax(value);
99
- setIsDragging(true);
112
+ isDraggingRef.current = true;
100
113
  debouncedUpdate(internalMin, value);
101
114
  };
102
- // Handle drag end
115
+ // Handle drag end — flush pending update immediately
103
116
  const handleDragEnd = () => {
104
- setIsDragging(false);
117
+ isDraggingRef.current = false;
118
+ // Cancel the debounce and commit immediately
119
+ if (debounceRef.current) {
120
+ clearTimeout(debounceRef.current);
121
+ debounceRef.current = null;
122
+ }
123
+ updateStateManager(pendingMinRef.current, pendingMaxRef.current);
124
+ if (onRangeChange) {
125
+ onRangeChange(pendingMinRef.current, pendingMaxRef.current);
126
+ }
105
127
  };
106
128
  // Handle keyboard navigation for enhanced control (Shift+Arrow for 10x step, Home/End)
107
129
  const handleMinKeyDown = (e) => {
@@ -166,7 +188,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
166
188
  } }, label)),
167
189
  React.createElement("div", { className: rangeSliderTheme.slider, style: {
168
190
  position: 'relative',
169
- height: '40px',
191
+ minHeight: '40px',
170
192
  display: 'flex',
171
193
  alignItems: 'center',
172
194
  } },
@@ -185,7 +207,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
185
207
  backgroundColor: theme.colors.primary,
186
208
  borderRadius: '2px',
187
209
  } }),
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: {
210
+ 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: {
189
211
  position: 'absolute',
190
212
  width: '100%',
191
213
  height: '4px',
@@ -195,7 +217,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
195
217
  cursor: 'pointer',
196
218
  pointerEvents: 'none',
197
219
  }, "aria-label": `Minimum ${label || field}` }),
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: {
220
+ 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: {
199
221
  position: 'absolute',
200
222
  width: '100%',
201
223
  height: '4px',
@@ -215,7 +237,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
215
237
  React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMin)),
216
238
  React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMax)))),
217
239
  React.createElement("style", null, `
218
- .${rangeSliderTheme.thumb || 'seekora-range-slider__thumb'}::-webkit-slider-thumb {
240
+ .${thumbClass}::-webkit-slider-thumb {
219
241
  -webkit-appearance: none;
220
242
  appearance: none;
221
243
  width: 20px;
@@ -224,9 +246,9 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
224
246
  border-radius: 50%;
225
247
  cursor: pointer;
226
248
  pointer-events: all;
227
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
249
+ box-shadow: ${SHADOWS.md};
228
250
  }
229
- .${rangeSliderTheme.thumb || 'seekora-range-slider__thumb'}::-moz-range-thumb {
251
+ .${thumbClass}::-moz-range-thumb {
230
252
  width: 20px;
231
253
  height: 20px;
232
254
  background: ${theme.colors.primary};
@@ -234,7 +256,7 @@ export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: curr
234
256
  cursor: pointer;
235
257
  pointer-events: all;
236
258
  border: none;
237
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
259
+ box-shadow: ${SHADOWS.md};
238
260
  }
239
261
  `)));
240
262
  };