Skip to content

Commit 071f918

Browse files
PrincessMadMathlevithomason
authored andcommitted
feat(Search): custom category layout renderer (#3672)
* [WIP] First implementation of custom SearchCategoryRenderer * [WIP] Added Typescript file and props validation * [wip] updating documentation * WIP remove unecessary change in PR * WIP fix unnecessary parenthesis * added proptypes to the search component * forgot to put the props optional * remove v2 in example title
1 parent b5d46f9 commit 071f918

7 files changed

Lines changed: 103 additions & 4 deletions

File tree

docs/src/examples/modules/Search/Types/SearchExampleCategoryCustom.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,20 @@ import faker from 'faker'
44
import React, { Component } from 'react'
55
import { Search, Grid, Header, Segment, Label } from 'semantic-ui-react'
66

7+
const categoryLayoutRenderer = ({ categoryContent, resultsContent }) => (
8+
<div>
9+
<h3 className='name'>{categoryContent}</h3>
10+
<div style={{ background: 'red' }} className='results'>
11+
{resultsContent}
12+
</div>
13+
</div>
14+
)
15+
16+
categoryLayoutRenderer.propTypes = {
17+
categoryContent: PropTypes.node,
18+
resultsContent: PropTypes.node,
19+
}
20+
721
const categoryRenderer = ({ name }) => <Label as='span' content={name} />
822

923
categoryRenderer.propTypes = {
@@ -79,6 +93,7 @@ export default class SearchExampleCategory extends Component {
7993
<Grid.Column width={8}>
8094
<Search
8195
category
96+
categoryLayoutRenderer={categoryLayoutRenderer}
8297
categoryRenderer={categoryRenderer}
8398
loading={isLoading}
8499
onResultSelect={this.handleResultSelect}

src/modules/Search/Search.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ export interface StrictSearchProps {
5858
// ------------------------------------
5959
// Rendering
6060
// ------------------------------------
61+
/**
62+
* Renders the SearchCategory layout.
63+
*
64+
* @param {object} categoryContent - The Renderable SearchCategory contents.
65+
* @param {object} resultsContent - The Renderable SearchResult contents.
66+
* @returns {*} - Renderable SearchCategory layout.
67+
*/
68+
categoryLayoutRenderer?: (props: SearchCategoryProps) => React.ReactElement<any>
6169

6270
/**
6371
* Renders the SearchCategory contents.

src/modules/Search/Search.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ export default class Search extends Component {
8383
// Rendering
8484
// ------------------------------------
8585

86+
/**
87+
* Renders the SearchCategory layout.
88+
*
89+
* @param {object} categoryContent - The Renderable SearchCategory contents.
90+
* @param {object} resultsContent - The Renderable SearchResult contents.
91+
* @returns {*} - Renderable SearchCategory layout.
92+
*/
93+
categoryLayoutRenderer: PropTypes.func,
94+
8695
/**
8796
* Renders the SearchCategory contents.
8897
*
@@ -577,7 +586,7 @@ export default class Search extends Component {
577586
}
578587

579588
renderCategories = () => {
580-
const { categoryRenderer, results: categories } = this.props
589+
const { categoryLayoutRenderer, categoryRenderer, results: categories } = this.props
581590
const { selectedIndex } = this.state
582591

583592
let count = 0
@@ -586,6 +595,7 @@ export default class Search extends Component {
586595
const categoryProps = {
587596
key: childKey || category.name,
588597
active: _.inRange(selectedIndex, count, count + category.results.length),
598+
layoutRenderer: categoryLayoutRenderer,
589599
renderer: categoryRenderer,
590600
...category,
591601
}

src/modules/Search/SearchCategory.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ export interface StrictSearchCategoryProps {
2626
/** Display name. */
2727
name?: string
2828

29+
/**
30+
* Renders the SearchCategory layout.
31+
*
32+
* @param {object} categoryContent - The Renderable SearchCategory contents.
33+
* @param {object} resultsContent - The Renderable SearchResult contents.
34+
* @returns {*} - Renderable SearchCategory layout.
35+
*/
36+
layoutRenderer?: (
37+
categoryContent: React.ReactElement<any>,
38+
resultsContent: React.ReactElement<any>,
39+
) => React.ReactElement<any>
40+
2941
/**
3042
* Renders the category contents.
3143
*

src/modules/Search/SearchCategory.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,26 @@ import {
99
getUnhandledProps,
1010
useKeyOnly,
1111
} from '../../lib'
12+
import SearchCategoryLayout from './SearchCategoryLayout'
1213

1314
function SearchCategory(props) {
14-
const { active, children, className, content, renderer } = props
15+
const { active, children, className, content, layoutRenderer, renderer } = props
1516
const classes = cx(useKeyOnly(active, 'active'), 'category', className)
1617
const rest = getUnhandledProps(SearchCategory, props)
1718
const ElementType = getElementType(SearchCategory, props)
1819

20+
const categoryContent = renderer(props)
21+
const resultsContent = childrenUtils.isNil(children) ? content : children
22+
1923
return (
2024
<ElementType {...rest} className={classes}>
21-
<div className='name'>{renderer(props)}</div>
22-
<div className='results'>{childrenUtils.isNil(children) ? content : children}</div>
25+
{layoutRenderer({ categoryContent, resultsContent })}
2326
</ElementType>
2427
)
2528
}
2629

2730
SearchCategory.defaultProps = {
31+
layoutRenderer: SearchCategoryLayout,
2832
renderer: ({ name }) => name,
2933
}
3034

@@ -47,6 +51,14 @@ SearchCategory.propTypes = {
4751
/** Display name. */
4852
name: PropTypes.string,
4953

54+
/**
55+
* Renders the category layout contents.
56+
*
57+
* @param {object} props - The SearchCategoryLayout props object.
58+
* @returns {*} - Renderable category layout contents.
59+
*/
60+
layoutRenderer: PropTypes.func,
61+
5062
/**
5163
* Renders the category contents.
5264
*
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import * as React from 'react'
2+
3+
import { SemanticShorthandContent } from '../../generic'
4+
import SearchResult from './SearchResult'
5+
6+
export interface SearchCategoryLayoutProps extends StrictSearchCategoryLayoutProps {
7+
[key: string]: any
8+
}
9+
10+
export interface StrictSearchCategoryLayoutProps {
11+
/** The rendered category content */
12+
categoryContent: React.ReactElement<any>
13+
14+
/** The rendered results content */
15+
resultsContent: React.ReactElement<any>
16+
}
17+
18+
declare const SearchCategoryLayout: React.StatelessComponent<SearchCategoryLayoutProps>
19+
20+
export default SearchCategoryLayout
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import PropTypes from 'prop-types'
2+
import React from 'react'
3+
4+
function SearchCategoryLayout(props) {
5+
const { categoryContent, resultsContent } = props
6+
return (
7+
<>
8+
<div className='name'>{categoryContent}</div>
9+
<div className='results'>{resultsContent}</div>
10+
</>
11+
)
12+
}
13+
14+
SearchCategoryLayout.propTypes = {
15+
/** The rendered category content */
16+
categoryContent: PropTypes.element.isRequired,
17+
18+
/** The rendered results content */
19+
resultsContent: PropTypes.element.isRequired,
20+
}
21+
22+
export default SearchCategoryLayout

0 commit comments

Comments
 (0)