@seekora-ai/ui-sdk-react 0.2.18 → 0.2.20

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.
@@ -58,6 +58,9 @@ interface SearchBarProps {
58
58
  renderSubmitButton?: () => React__default.ReactNode;
59
59
  /** Size variant controlling padding and font size (default: 'medium') */
60
60
  size?: SearchBarSize;
61
+ /** Trigger search automatically as user types, with debounce (default: false).
62
+ * When true, uses `debounceMs` for the delay. Enter still triggers immediately. */
63
+ searchAsYouType?: boolean;
61
64
  }
62
65
  declare const SearchBar: React__default.FC<SearchBarProps>;
63
66
 
@@ -1685,7 +1685,7 @@ const DefaultSearchIcon = ({ size = 18 }) => (React.createElement("svg", { width
1685
1685
  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" },
1686
1686
  React.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1687
1687
  React.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })));
1688
- const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, renderSuggestion, renderSearchIcon, showClearButton = true, renderClearIcon, showSubmitButton = false, renderSubmitButton, size = 'medium', }) => {
1688
+ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true, debounceMs = 300, minQueryLength = 2, maxSuggestions = 10, onSearch, onQueryChange, onSuggestionSelect, onSearchStateChange, searchOptions, className, style, theme: customTheme, renderSuggestion, renderSearchIcon, showClearButton = true, renderClearIcon, showSubmitButton = false, renderSubmitButton, size = 'medium', searchAsYouType = false, }) => {
1689
1689
  const { client, theme, enableAnalytics, autoTrackSearch } = useSearchContext();
1690
1690
  const { query, setQuery, search: triggerSearch, results, loading: searchLoading, error: searchError } = useSearchState();
1691
1691
  const [isFocused, setIsFocused] = useState(false);
@@ -1693,6 +1693,14 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
1693
1693
  const inputRef = useRef(null);
1694
1694
  const containerRef = useRef(null);
1695
1695
  const isSearchingRef = useRef(false); // Flag to prevent blur handler from interfering
1696
+ const searchAsYouTypeRef = useRef(null);
1697
+ // Cleanup searchAsYouType timer on unmount
1698
+ useEffect(() => {
1699
+ return () => {
1700
+ if (searchAsYouTypeRef.current)
1701
+ clearTimeout(searchAsYouTypeRef.current);
1702
+ };
1703
+ }, []);
1696
1704
  const { suggestions, loading: suggestionsLoading } = useQuerySuggestions({
1697
1705
  client,
1698
1706
  query,
@@ -1722,6 +1730,11 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
1722
1730
  }
1723
1731
  }, [query, onQueryChange]);
1724
1732
  const handleSearch = useCallback(async (searchQuery) => {
1733
+ // Cancel any pending searchAsYouType debounce — user explicitly submitted
1734
+ if (searchAsYouTypeRef.current) {
1735
+ clearTimeout(searchAsYouTypeRef.current);
1736
+ searchAsYouTypeRef.current = null;
1737
+ }
1725
1738
  // Allow empty queries - use empty string for search
1726
1739
  const query = searchQuery.trim();
1727
1740
  log.info('SearchBar: Triggering search', { query, originalQuery: searchQuery, isEmpty: !query });
@@ -1758,10 +1771,18 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
1758
1771
  const handleInputChange = useCallback((e) => {
1759
1772
  const value = e.target.value;
1760
1773
  // Update query in state manager but don't trigger search immediately
1761
- // Search will be triggered on Enter or suggestion select
1774
+ // Search will be triggered on Enter, suggestion select, or after debounce if searchAsYouType
1762
1775
  setQuery(value, false); // false = don't trigger search immediately
1763
1776
  setSelectedIndex(-1);
1764
- }, [setQuery]);
1777
+ if (searchAsYouType) {
1778
+ if (searchAsYouTypeRef.current)
1779
+ clearTimeout(searchAsYouTypeRef.current);
1780
+ searchAsYouTypeRef.current = setTimeout(() => {
1781
+ searchAsYouTypeRef.current = null;
1782
+ triggerSearch();
1783
+ }, debounceMs);
1784
+ }
1785
+ }, [setQuery, searchAsYouType, debounceMs, triggerSearch]);
1765
1786
  const handleKeyDown = useCallback((e) => {
1766
1787
  switch (e.key) {
1767
1788
  case 'ArrowDown':
@@ -1837,10 +1858,17 @@ const SearchBar = ({ placeholder = 'Powered by Seekora', showSuggestions = true,
1837
1858
  ? `0 0 0 3px var(--seekora-border-focus-alpha, ${theme.colors.focus}33)`
1838
1859
  : undefined;
1839
1860
  const handleClear = useCallback(() => {
1861
+ if (searchAsYouTypeRef.current) {
1862
+ clearTimeout(searchAsYouTypeRef.current);
1863
+ searchAsYouTypeRef.current = null;
1864
+ }
1840
1865
  setQuery('', false);
1841
1866
  setSelectedIndex(-1);
1842
1867
  inputRef.current?.focus();
1843
- }, [setQuery]);
1868
+ if (searchAsYouType) {
1869
+ triggerSearch();
1870
+ }
1871
+ }, [setQuery, searchAsYouType, triggerSearch]);
1844
1872
  const handleSubmit = useCallback(() => {
1845
1873
  const currentValue = inputRef.current?.value || query;
1846
1874
  handleSearch(currentValue);