Add a GroupName custom component

This commit is contained in:
Tom Southall
2022-02-24 15:37:46 +00:00
parent c94a5d18ee
commit 96525d8b6d
11 changed files with 54 additions and 13 deletions

View File

@@ -3,7 +3,8 @@ import Turnstone from '../../src/lib'
import styles from './styles/App.module.css' import styles from './styles/App.module.css'
import autocompleteStyles from './styles/autocomplete.module.css' import autocompleteStyles from './styles/autocomplete.module.css'
import defaultListbox from '../_shared/defaultListbox' import defaultListbox from '../_shared/defaultListbox'
import Item from './components/item/item' import ItemContents from './components/itemContents/itemContents'
import GroupName from './components/groupName/groupName'
const maxItems = 10 const maxItems = 10
const placeholder = 'Enter a city or airport' const placeholder = 'Enter a city or airport'
@@ -59,7 +60,6 @@ const App = () => {
defaultListbox={defaultListbox} defaultListbox={defaultListbox}
defaultListboxIsImmutable={false} defaultListboxIsImmutable={false}
id='autocomplete' id='autocomplete'
itemComponent={Item}
listbox={listbox} listbox={listbox}
listboxIsImmutable={true} listboxIsImmutable={true}
maxItems={maxItems} maxItems={maxItems}
@@ -70,6 +70,8 @@ const App = () => {
onTab={onTab} onTab={onTab}
placeholder={placeholder} placeholder={placeholder}
styles={autocompleteStyles} styles={autocompleteStyles}
GroupName={GroupName}
ItemContents={ItemContents}
/> />
</div> </div>
</main> </main>

View File

@@ -0,0 +1,27 @@
import React from 'react'
import styles from './groupName.module.css'
export default function GroupName(props) {
const {
children: name
} = props
const icons = {
cities: '\u{1F3D9}',
airports: '\u{2708}'
}
const icon = icons[name.toLowerCase()] || ''
return (
<>
{icon && (
<span className={styles.icon}>
{icon}
</span>
)}
{name}
</>
)
}

View File

@@ -0,0 +1,4 @@
.icon {
display: inline-block;
padding-right: 6px;
}

View File

@@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import SplitMatch from '../splitMatch/splitMatch' import SplitMatch from '../splitMatch/splitMatch'
import imgNewYork from'../../images/newyork.jpg' import imgNewYork from'../../images/newyork.jpg'
import styles from './item.module.css' import styles from './itemContents.module.css'
const SplitComponent = (props) => { const SplitComponent = (props) => {
const { const {
@@ -20,7 +20,7 @@ const MatchComponent = (props) => {
return <span className={styles.match}>{children}</span> return <span className={styles.match}>{children}</span>
} }
export default function Item(props) { export default function ItemContents(props) {
const { const {
appearsInDefaultListbox, appearsInDefaultListbox,
index, index,

View File

@@ -47,7 +47,7 @@
text-align: center; text-align: center;
} }
.groupName { .groupHeading {
text-transform: uppercase; text-transform: uppercase;
font-size: 0.8em; font-size: 0.8em;
color: #777; color: #777;

View File

@@ -3,7 +3,7 @@
exports[`ItemFirst > Component renders correctly 1`] = ` exports[`ItemFirst > Component renders correctly 1`] = `
[ [
<div <div
className="group-name-class" className="group-heading-class"
> >
Cities Cities
</div>, </div>,

View File

@@ -13,7 +13,7 @@ export default function Item(props) {
} = useContext(StateContext) } = useContext(StateContext)
const { customStyles, highlighted, query } = state const { customStyles, highlighted, query } = state
const CustomItem = state.props.itemComponent const ItemContents = state.props.ItemContents
const globalMatch = item.dataSearchType === 'contains' const globalMatch = item.dataSearchType === 'contains'
const isHighlighted = highlighted && index === highlighted.index const isHighlighted = highlighted && index === highlighted.index
@@ -37,8 +37,8 @@ export default function Item(props) {
dispatch(setSelected(index)) dispatch(setSelected(index))
} }
const itemContents = (CustomItem) const itemContents = (ItemContents)
? <CustomItem ? <ItemContents
appearsInDefaultListbox={item.defaultListbox} appearsInDefaultListbox={item.defaultListbox}
groupName={item.groupName} groupName={item.groupName}
index={index} index={index}

View File

@@ -6,10 +6,17 @@ export default function ItemFirst(props) {
const { groupName, index, item } = props const { groupName, index, item } = props
const { state } = useContext(StateContext) const { state } = useContext(StateContext)
const { customStyles } = state const { customStyles } = state
const GroupName = state.props.GroupName
const groupHeading = !!groupName && (
GroupName
? <GroupName index={item.groupIndex}>{groupName}</GroupName>
: groupName
)
return ( return (
<React.Fragment> <React.Fragment>
{!!groupName && <div className={customStyles.groupName}>{groupName}</div>} {!!groupHeading && <div className={customStyles.groupHeading}>{groupHeading}</div>}
<Item index={index} key={`item${index}`} item={item} /> <Item index={index} key={`item${index}`} item={item} />
</React.Fragment> </React.Fragment>
) )

View File

@@ -10,7 +10,7 @@ vi.mock('./item', () => ({ default: () => 'Item' }))
describe('ItemFirst', () => { describe('ItemFirst', () => {
test('Component renders correctly', () => { test('Component renders correctly', () => {
const customStyles = { const customStyles = {
groupName: 'group-name-class' groupHeading: 'group-heading-class'
} }
const component = renderer.create( const component = renderer.create(

View File

@@ -73,7 +73,6 @@ Turnstone.propTypes = {
disabled: PropTypes.bool, disabled: PropTypes.bool,
displayField: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), displayField: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
id: PropTypes.string, id: PropTypes.string,
itemComponent: PropTypes.elementType,
listbox: listboxRules.isRequired, listbox: listboxRules.isRequired,
listboxIsImmutable: PropTypes.bool, listboxIsImmutable: PropTypes.bool,
matchText: PropTypes.bool, matchText: PropTypes.bool,
@@ -98,7 +97,9 @@ Turnstone.propTypes = {
maxItems: PropTypes.number, maxItems: PropTypes.number,
styles: PropTypes.object, styles: PropTypes.object,
tabIndex: PropTypes.number, tabIndex: PropTypes.number,
text: PropTypes.string text: PropTypes.string,
ItemContents: PropTypes.elementType,
GroupName: PropTypes.elementType
} }
////////////////////////////////////////////////////// //////////////////////////////////////////////////////