Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(List): handler for <List selection/> #1530

Merged
merged 10 commits into from
Apr 3, 2017
10 changes: 9 additions & 1 deletion src/elements/List/List.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { default as ListContent } from './ListContent';
import { default as ListDescription } from './ListDescription';
import { default as ListHeader } from './ListHeader';
import { default as ListIcon } from './ListIcon';
import { default as ListItem } from './ListItem';
import { default as ListItem, ListItemProps } from './ListItem';
import { default as ListList } from './ListList';

export interface ListProps {
Expand Down Expand Up @@ -51,6 +51,14 @@ export interface ListProps {
/** A list can be specially formatted for navigation links. */
link?: boolean;

/**
* onClick handler for ListItem. Mutually exclusive with children.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All item props.
*/
onItemClick?: (event: React.MouseEvent<HTMLAnchorElement>, data: ListItemProps) => void;

/** A list can be ordered numerically. */
ordered?: boolean;

Expand Down
220 changes: 120 additions & 100 deletions src/elements/List/List.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import cx from 'classnames'
import _ from 'lodash'
import React, { PropTypes } from 'react'
import React, { Component, PropTypes } from 'react'

import {
customPropTypes,
Expand All @@ -23,124 +23,144 @@ import ListList from './ListList'
/**
* A list groups related content.
*/
function List(props) {
const {
animated,
bulleted,
celled,
children,
className,
divided,
floated,
horizontal,
inverted,
items,
link,
ordered,
relaxed,
selection,
size,
verticalAlign,
} = props

const classes = cx(
'ui',
size,
useKeyOnly(animated, 'animated'),
useKeyOnly(bulleted, 'bulleted'),
useKeyOnly(celled, 'celled'),
useKeyOnly(divided, 'divided'),
useKeyOnly(horizontal, 'horizontal'),
useKeyOnly(inverted, 'inverted'),
useKeyOnly(link, 'link'),
useKeyOnly(ordered, 'ordered'),
useKeyOnly(selection, 'selection'),
useKeyOrValueAndKey(relaxed, 'relaxed'),
useValueAndKey(floated, 'floated'),
useVerticalAlignProp(verticalAlign),
'list',
className,
)
const rest = getUnhandledProps(List, props)
const ElementType = getElementType(List, props)

if (!_.isNil(children)) {
return <ElementType {...rest} role='list' className={classes}>{children}</ElementType>
}
class List extends Component {
static propTypes = {
/** An element type to render as (string or function). */
as: customPropTypes.as,

return (
<ElementType {...rest} role='list' className={classes}>
{_.map(items, (item) => ListItem.create(item))}
</ElementType>
)
}
/** A list can animate to set the current item apart from the list. */
animated: PropTypes.bool,

List._meta = {
name: 'List',
type: META.TYPES.ELEMENT,
}
/** A list can mark items with a bullet. */
bulleted: PropTypes.bool,

List.propTypes = {
/** An element type to render as (string or function). */
as: customPropTypes.as,
/** A list can divide its items into cells. */
celled: PropTypes.bool,

/** A list can animate to set the current item apart from the list. */
animated: PropTypes.bool,
/** Primary content. */
children: PropTypes.node,

/** A list can mark items with a bullet. */
bulleted: PropTypes.bool,
/** Additional classes. */
className: PropTypes.string,

/** A list can divide its items into cells. */
celled: PropTypes.bool,
/** A list can show divisions between content. */
divided: PropTypes.bool,

/** Primary content. */
children: PropTypes.node,
/** An list can be floated left or right. */
floated: PropTypes.oneOf(SUI.FLOATS),

/** Additional classes. */
className: PropTypes.string,
/** A list can be formatted to have items appear horizontally. */
horizontal: PropTypes.bool,

/** A list can show divisions between content. */
divided: PropTypes.bool,
/** A list can be inverted to appear on a dark background. */
inverted: PropTypes.bool,

/** An list can be floated left or right. */
floated: PropTypes.oneOf(SUI.FLOATS),
/** Shorthand array of props for ListItem. */
items: customPropTypes.collectionShorthand,

/** A list can be formatted to have items appear horizontally. */
horizontal: PropTypes.bool,
/** A list can be specially formatted for navigation links. */
link: PropTypes.bool,

/** A list can be inverted to appear on a dark background. */
inverted: PropTypes.bool,
/**
* onClick handler for ListItem. Mutually exclusive with children.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All item props.
*/
onItemClick: customPropTypes.every([
customPropTypes.disallow(['children']),
PropTypes.func,
]),

/** Shorthand array of props for ListItem. */
items: customPropTypes.collectionShorthand,
/** A list can be ordered numerically. */
ordered: PropTypes.bool,

/** A list can be specially formatted for navigation links. */
link: PropTypes.bool,
/** A list can relax its padding to provide more negative space. */
relaxed: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['very']),
]),

/** A list can be ordered numerically. */
ordered: PropTypes.bool,
/** A selection list formats list items as possible choices. */
selection: PropTypes.bool,

/** A list can relax its padding to provide more negative space. */
relaxed: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['very']),
]),
/** A list can vary in size. */
size: PropTypes.oneOf(SUI.SIZES),

/** A selection list formats list items as possible choices. */
selection: PropTypes.bool,
/** An element inside a list can be vertically aligned. */
verticalAlign: PropTypes.oneOf(SUI.VERTICAL_ALIGNMENTS),
}

/** A list can vary in size. */
size: PropTypes.oneOf(SUI.SIZES),
static _meta = {
name: 'List',
type: META.TYPES.ELEMENT,
}

/** An element inside a list can be vertically aligned. */
verticalAlign: PropTypes.oneOf(SUI.VERTICAL_ALIGNMENTS),
static Content = ListContent
static Description = ListDescription
static Header = ListHeader
static Icon = ListIcon
static Item = ListItem
static List = ListList

handleItemOverrides = predefinedProps => ({
onClick: (e, itemProps) => {
_.invoke(predefinedProps, 'onClick', e, itemProps)
_.invoke(this.props, 'onItemClick', e, itemProps)
},
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated handlers there like in #1428. I also removed index there, I think we don't really need it there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, the Menu only needs it as there is an activeIndex.


render() {
const {
animated,
bulleted,
celled,
children,
className,
divided,
floated,
horizontal,
inverted,
items,
link,
ordered,
relaxed,
selection,
size,
verticalAlign,
} = this.props

const classes = cx(
'ui',
size,
useKeyOnly(animated, 'animated'),
useKeyOnly(bulleted, 'bulleted'),
useKeyOnly(celled, 'celled'),
useKeyOnly(divided, 'divided'),
useKeyOnly(horizontal, 'horizontal'),
useKeyOnly(inverted, 'inverted'),
useKeyOnly(link, 'link'),
useKeyOnly(ordered, 'ordered'),
useKeyOnly(selection, 'selection'),
useKeyOrValueAndKey(relaxed, 'relaxed'),
useValueAndKey(floated, 'floated'),
useVerticalAlignProp(verticalAlign),
'list',
className,
)
const rest = getUnhandledProps(List, this.props)
const ElementType = getElementType(List, this.props)

if (!_.isNil(children)) {
return <ElementType {...rest} role='list' className={classes}>{children}</ElementType>
}

return (
<ElementType {...rest} role='list' className={classes}>
{_.map(items, item => ListItem.create(item, { overrideProps: this.handleItemOverrides }))}
</ElementType>
)
}
}

List.Content = ListContent
List.Description = ListDescription
List.Header = ListHeader
List.Icon = ListIcon
List.Item = ListItem
List.List = ListList

export default List
4 changes: 1 addition & 3 deletions src/elements/List/ListContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ function ListContent(props) {
const rest = getUnhandledProps(ListContent, props)
const ElementType = getElementType(ListContent, props)

if (!_.isNil(children)) {
return <ElementType {...rest} className={classes}>{children}</ElementType>
}
if (!_.isNil(children)) return <ElementType {...rest} className={classes}>{children}</ElementType>

return (
<ElementType {...rest} className={classes}>
Expand Down
8 changes: 8 additions & 0 deletions src/elements/List/ListItem.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ export interface ListItemProps {
/** Shorthand for Image. */
image?: any;

/**
* Called on click.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onClick?: (event: React.MouseEvent<HTMLAnchorElement>, data: ListItemProps) => void;

/** A value for an ordered list. */
value?: string;
}
Expand Down
Loading