Skip to content

Commit a8183d0

Browse files
committed
feat: add SearchSourceResultsContext
1 parent ba85fa0 commit a8183d0

9 files changed

+66
-58
lines changed

src/context/ComponentContext.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,7 @@ import {
5252
import {
5353
SearchProps,
5454
SearchResultsPresearchProps,
55-
SearchSourceResultListFooterProps,
5655
SearchSourceResultListProps,
57-
SearchSourceResultsEmptyProps,
5856
} from '../experimental';
5957

6058
import type {
@@ -64,7 +62,6 @@ import type {
6462
UnknownType,
6563
} from '../types/types';
6664
import type { DefaultSearchSources, SearchSource } from '../experimental/Search/SearchController';
67-
import { SearchSourceResultsHeaderProps } from '../experimental/Search/SearchResults/SearchSourceResultsHeader';
6865

6966
export type ComponentContextValue<
7067
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
@@ -187,19 +184,19 @@ export type ComponentContextValue<
187184
SearchResultsPresearchProps<StreamChatGenerics, SearchSources>
188185
>;
189186
/** Custom component to display the search source results UI during the search query execution, defaults to and accepts same props as: [SearchSourceLoadingResults](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Search/SearchResults/SearchSourceLoadingResults.tsx) */
190-
SearchSourceLoadingResults?: React.ComponentType<SearchSourceResultsEmptyProps>;
187+
SearchSourceLoadingResults?: React.ComponentType;
191188
/** Custom component to display the search source items results, defaults to and accepts same props as: [SearchSourceResultList](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Search/SearchResults/SearchSourceResultList.tsx) */
192189
SearchSourceResultList?: React.ComponentType<
193190
SearchSourceResultListProps<StreamChatGenerics, SearchSources>
194191
>;
195192
/** Custom component to indicate the end of the last page for a searched source, defaults to and accepts same props as: [SearchSourceResultListFooter](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Search/SearchResults/SearchSourceResultListFooter.tsx) */
196-
SearchSourceResultListFooter?: React.ComponentType<SearchSourceResultListFooterProps>;
193+
SearchSourceResultListFooter?: React.ComponentType;
197194
/** Custom UI component to display search results items for a given search source pane, defaults to and accepts same props as: [SearchSourceResults](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Search/SearchResults/SourceSearchResults.tsx) */
198195
SearchSourceResults?: React.ComponentType;
199196
/** Custom component to display the search source results UI with 0 items found, defaults to and accepts same props as: [SearchSourceResultsEmpty](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Search/SearchResults/SearchSourceResultsEmpty.tsx) */
200-
SearchSourceResultsEmpty?: React.ComponentType<SearchSourceResultsEmptyProps>;
197+
SearchSourceResultsEmpty?: React.ComponentType;
201198
/** Custom component to display the header content for a given search source results, no default component is provided. */
202-
SearchSourceResultsHeader?: React.ComponentType<SearchSourceResultsHeaderProps>;
199+
SearchSourceResultsHeader?: React.ComponentType;
203200
/** Custom UI component for send button, defaults to and accepts same props as: [SendButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MessageInput/icons.tsx) */
204201
SendButton?: React.ComponentType<SendButtonProps<StreamChatGenerics>>;
205202
/** Custom UI component button for initiating audio recording, defaults to and accepts same props as: [StartRecordingAudioButton](https://github.com/GetStream/stream-chat-react/blob/master/src/components/MediaRecorder/AudioRecorder/AudioRecordingButtons.tsx) */

src/experimental/Search/SearchContext.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export type SearchContextValue<
3030
export const SearchContext = createContext<SearchContextValue | undefined>(undefined);
3131

3232
/**
33-
* Context provider for components rendered within the `ChannelSearch`
33+
* Context provider for components rendered within the `Search` component
3434
*/
3535
export const SearchContextProvider = <
3636
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
@@ -51,14 +51,5 @@ export const useSearchContext = <
5151
Sources extends SearchSource[] = DefaultSearchSources<StreamChatGenerics>
5252
>() => {
5353
const contextValue = useContext(SearchContext);
54-
55-
if (!contextValue) {
56-
console.warn(
57-
`The useChannelSearchContext hook was called outside of the ChannelSearchContext provider. Make sure this hook is called within the ChannelSearch component.`,
58-
);
59-
60-
return {} as SearchContextValue<StreamChatGenerics, Sources>;
61-
}
62-
6354
return (contextValue as unknown) as SearchContextValue<StreamChatGenerics, Sources>;
6455
};

src/experimental/Search/SearchResults/SearchSourceLoadingResults.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
import React from 'react';
22
import { useTranslationContext } from '../../../context';
3-
import { SearchSource } from '../SearchController';
3+
import { useSearchSourceResultsContext } from '../SearchSourceResultsContext';
44

5-
export type SearchSourceLoadingResultsProps = {
6-
searchSource: SearchSource;
7-
};
8-
9-
export const SearchSourceLoadingResults = ({ searchSource }: SearchSourceLoadingResultsProps) => {
5+
export const SearchSourceLoadingResults = () => {
106
const { t } = useTranslationContext();
11-
7+
const { searchSource } = useSearchSourceResultsContext();
128
return (
139
<div
1410
className='str-chat__channel-search-container-searching'

src/experimental/Search/SearchResults/SearchSourceResultList.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
import React, { ComponentType, useCallback } from 'react';
2-
import { InfiniteScrollPaginator } from '../../../components/InfiniteScrollPaginator/InfiniteScrollPaginator';
32
import { DefaultSearchResultItems, SearchResultItemComponents } from './SearchResultItem';
43
import { SearchSourceResultListFooter as DefaultSearchSourceResultListFooter } from './SearchSourceResultListFooter';
4+
import { useSearchSourceResultsContext } from '../SearchSourceResultsContext';
5+
import { InfiniteScrollPaginator } from '../../../components/InfiniteScrollPaginator/InfiniteScrollPaginator';
56
import { useComponentContext } from '../../../context';
6-
import type { DefaultSearchSources, SearchSource, SourceItemsRecord } from '../SearchController';
7+
import { useStateStore } from '../../../store';
8+
import type { DefaultSearchSources, SearchSource, SearchSourceState } from '../SearchController';
79
import type { DefaultStreamChatGenerics } from '../../../types';
810

11+
const searchSourceStateSelector = (nextValue: SearchSourceState) => ({
12+
items: nextValue.items,
13+
});
14+
915
export type SearchSourceResultListProps<
1016
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
1117
Sources extends SearchSource[] = DefaultSearchSources<StreamChatGenerics>
1218
> = {
13-
searchSource: SearchSource;
14-
items?: SourceItemsRecord<StreamChatGenerics, Sources>[Sources[number]['type']];
1519
loadMoreDebounceMs?: number;
1620
loadMoreThresholdPx?: number;
1721
SearchResultItems?: SearchResultItemComponents<Sources>;
@@ -21,16 +25,19 @@ export const SearchSourceResultList = <
2125
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
2226
SearchSources extends SearchSource[] = DefaultSearchSources<StreamChatGenerics>
2327
>({
24-
items,
2528
loadMoreThresholdPx = 80,
2629
loadMoreDebounceMs = 100,
27-
searchSource,
2830
SearchResultItems = DefaultSearchResultItems as SearchResultItemComponents<SearchSources>,
2931
}: SearchSourceResultListProps<StreamChatGenerics, SearchSources>) => {
3032
const {
3133
SearchSourceResultListFooter = DefaultSearchSourceResultListFooter,
3234
} = useComponentContext<StreamChatGenerics, NonNullable<unknown>, SearchSources>();
35+
36+
const { searchSource } = useSearchSourceResultsContext();
37+
const { items } = useStateStore(searchSource.state, searchSourceStateSelector);
38+
3339
const loadMore = useCallback(() => searchSource.search(), [searchSource]);
40+
3441
const SearchResultItem = SearchResultItems[
3542
searchSource.type as SearchSources[number]['type']
3643
] as ComponentType<{ item: unknown }>;
@@ -47,7 +54,7 @@ export const SearchSourceResultList = <
4754
{items?.map((item, i) => (
4855
<SearchResultItem item={item} key={`source-search-result-${searchSource.type}-${i}`} />
4956
))}
50-
<SearchSourceResultListFooter searchSource={searchSource} />
57+
<SearchSourceResultListFooter />
5158
</InfiniteScrollPaginator>
5259
</div>
5360
);

src/experimental/Search/SearchResults/SearchSourceResultListFooter.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import type { DefaultSearchSources, SearchSource, SearchSourceState } from '../SearchController';
33
import { SearchSourceLoadingResults as DefaultSearchSourceLoadingResults } from './SearchSourceLoadingResults';
4+
import { useSearchSourceResultsContext } from '../SearchSourceResultsContext';
45
import { useComponentContext, useTranslationContext } from '../../../context';
56
import { useStateStore } from '../../../store';
67
import type { DefaultStreamChatGenerics } from '../../../types';
@@ -10,28 +11,23 @@ const searchSourceStateSelector = (value: SearchSourceState) => ({
1011
isLoading: value.isLoading,
1112
});
1213

13-
export type SearchSourceResultListFooterProps = {
14-
searchSource: SearchSource;
15-
};
16-
1714
export const SearchSourceResultListFooter = <
1815
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
1916
SearchSources extends SearchSource[] = DefaultSearchSources<StreamChatGenerics>
20-
>({
21-
searchSource,
22-
}: SearchSourceResultListFooterProps) => {
17+
>() => {
2318
const { t } = useTranslationContext();
2419
const { SearchSourceLoadingResults = DefaultSearchSourceLoadingResults } = useComponentContext<
2520
StreamChatGenerics,
2621
NonNullable<unknown>,
2722
SearchSources
2823
>();
24+
const { searchSource } = useSearchSourceResultsContext();
2925
const { hasMore, isLoading } = useStateStore(searchSource.state, searchSourceStateSelector);
3026

3127
return (
3228
<div className='str-chat__search-source-result-list__footer'>
3329
{isLoading ? (
34-
<SearchSourceLoadingResults searchSource={searchSource} />
30+
<SearchSourceLoadingResults />
3531
) : !hasMore ? (
3632
<div className='str-chat__search-source-results---empty'>
3733
{t<string>('All results loaded')}

src/experimental/Search/SearchResults/SearchSourceResults.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { SearchSourceResultList as DefaultSearchSourceResultList } from './SearchSourceResultList';
33
import { SearchSourceResultsEmpty as DefaultSearchSourceResultsEmpty } from './SearchSourceResultsEmpty';
44
import { SearchSourceResultsHeader as DefaultSearchSourceResultsHeader } from './SearchSourceResultsHeader';
5+
import { SearchSourceResultsContextProvider } from '../SearchSourceResultsContext';
56
import { useComponentContext } from '../../../context';
67
import { useStateStore } from '../../../store';
78
import type { DefaultSearchSources, SearchSource, SearchSourceState } from '../SearchController';
@@ -14,6 +15,7 @@ const searchSourceStateSelector = (nextValue: SearchSourceState) => ({
1415
});
1516

1617
export type SearchSourceResultsProps = { searchSource: SearchSource };
18+
1719
export const SearchSourceResults = <
1820
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
1921
SearchSources extends SearchSource[] = DefaultSearchSources<StreamChatGenerics>
@@ -28,14 +30,13 @@ export const SearchSourceResults = <
2830
const { isLoading, items } = useStateStore(searchSource.state, searchSourceStateSelector);
2931

3032
if (!items && !isLoading) return null;
33+
3134
return (
32-
<div className='str-chat__search-source-results'>
33-
<SearchSourceResultsHeader searchSource={searchSource} />
34-
{items?.length || isLoading ? (
35-
<SearchSourceResultList items={items} searchSource={searchSource} />
36-
) : (
37-
<SearchSourceResultsEmpty searchSource={searchSource} />
38-
)}
39-
</div>
35+
<SearchSourceResultsContextProvider value={{ searchSource }}>
36+
<div className='str-chat__search-source-results'>
37+
<SearchSourceResultsHeader />
38+
{items?.length || isLoading ? <SearchSourceResultList /> : <SearchSourceResultsEmpty />}
39+
</div>
40+
</SearchSourceResultsContextProvider>
4041
);
4142
};

src/experimental/Search/SearchResults/SearchSourceResultsEmpty.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import React from 'react';
2-
import { SearchSource } from '../SearchController';
32
import { useTranslationContext } from '../../../context';
43

5-
export type SearchSourceResultsEmptyProps = {
6-
searchSource: SearchSource;
7-
};
8-
94
export const SearchSourceResultsEmpty = () => {
105
const { t } = useTranslationContext();
116
return (
Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1 @@
1-
import type { SearchSource } from '../SearchController';
2-
3-
export type SearchSourceResultsHeaderProps = {
4-
searchSource: SearchSource;
5-
};
6-
71
export const SearchSourceResultsHeader = () => null;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React, { createContext, PropsWithChildren, useContext } from 'react';
2+
import { SearchSource } from './SearchController';
3+
4+
export type SearchSourceResultsContextValue = {
5+
searchSource: SearchSource;
6+
};
7+
8+
export const SearchSourceResultsContext = createContext<
9+
SearchSourceResultsContextValue | undefined
10+
>(undefined);
11+
12+
/**
13+
* Context provider for components rendered within the `SearchSourceResults`
14+
*/
15+
export const SearchSourceResultsContextProvider = ({
16+
children,
17+
value,
18+
}: PropsWithChildren<{
19+
value: SearchSourceResultsContextValue;
20+
}>) => (
21+
<SearchSourceResultsContext.Provider
22+
value={(value as unknown) as SearchSourceResultsContextValue}
23+
>
24+
{children}
25+
</SearchSourceResultsContext.Provider>
26+
);
27+
28+
export const useSearchSourceResultsContext = () => {
29+
const contextValue = useContext(SearchSourceResultsContext);
30+
return (contextValue as unknown) as SearchSourceResultsContextValue;
31+
};

0 commit comments

Comments
 (0)