diff --git a/docs/app/Examples/collections/Table/States/TableWarningShorthand.js b/docs/app/Examples/collections/Table/States/TableWarningShorthand.js new file mode 100644 index 0000000000..4be66cf4a5 --- /dev/null +++ b/docs/app/Examples/collections/Table/States/TableWarningShorthand.js @@ -0,0 +1,36 @@ +import React from 'react' +import { Icon, Table } from 'stardust' + +const headerRow = [ + 'Name', + 'Status', + 'Notes', +] + +const bodyRow = ({ name, status, notes }) => ({ + warning: !!(status && status.match('Requires Action')), + items: [ + name || 'No name specified', + status + ? { icon: 'attention', content: status } + : 'Unknown', + notes + ? { icon: 'attention', content: notes, warning: true } + : 'None', + ] +}) + +const tableData = [ + { name: undefined, status: undefined, notes: undefined }, + { name: 'Jimmy', status: 'Requires Action', notes: undefined }, + { name: 'Jamie', status: undefined, notes: 'Hostile' }, + { name: 'Jill', status: undefined, notes: undefined }, +] + +const TableWarningShorthand = () => { + return ( + + ) +} + +export default TableWarningShorthand diff --git a/docs/app/Examples/collections/Table/States/index.js b/docs/app/Examples/collections/Table/States/index.js index bb7973fa31..2e33b1e288 100644 --- a/docs/app/Examples/collections/Table/States/index.js +++ b/docs/app/Examples/collections/Table/States/index.js @@ -21,6 +21,11 @@ const States = () => { description='A cell or row may warn a user' examplePath='collections/Table/States/TableWarning' /> + {children} + if (children) { + return {children} + } + + return ( + + {headerRow && {TableRow.create(headerRow, { itemAs: 'th' })}} + {{tableData.map((item, index) => TableRow.create(bodyRow(item, index)))}} + {footerRow && {TableRow.create(footerRow)}} + + ) } Table._meta = { @@ -100,11 +114,23 @@ Table.propTypes = { PropTypes.oneOf(Table._meta.props.basic), ]), + /** + * A function that takes (data, index) and returns shorthand for a TableRow + * to be placed within Table.Body. + */ + bodyRow: customPropTypes.every([ + customPropTypes.demand(['bodyRow']), + PropTypes.func, + ]), + /** A table may be divided each row into separate cells. */ celled: PropTypes.bool, /** Primary content of the Table. */ - children: PropTypes.node, + children: customPropTypes.every([ + customPropTypes.disallow(['headerRow', 'bodyRow', 'footerRow', 'tableData']), + PropTypes.node, + ]), /** Classes that will be added to the Table className. */ className: PropTypes.string, @@ -132,6 +158,18 @@ Table.propTypes = { * */ fixed: PropTypes.bool, + /** Shorthand for a TableRow to be placed within Table.Footer. */ + footerRow: PropTypes.oneOfType([ + PropTypes.array, + PropTypes.element, + ]), + + /** Shorthand for a TableRow to be placed within Table.Header. */ + headerRow: PropTypes.oneOfType([ + PropTypes.array, + PropTypes.element, + ]), + /** A table's colors can be inverted. */ inverted: PropTypes.bool, @@ -159,6 +197,12 @@ Table.propTypes = { /** A table can be formatted to display complex structured data. */ structured: PropTypes.bool, + /** Data to be passed to the bodyRow function. */ + tableData: customPropTypes.every([ + customPropTypes.demand(['bodyRow']), + PropTypes.array, + ]), + /** A table can specify how it stacks table content responsively. */ unstackable: PropTypes.bool, } diff --git a/src/collections/Table/TableCell.js b/src/collections/Table/TableCell.js index d3b625f9fb..359141c0c8 100644 --- a/src/collections/Table/TableCell.js +++ b/src/collections/Table/TableCell.js @@ -2,6 +2,7 @@ import cx from 'classnames' import React, { PropTypes } from 'react' import { + createShorthandFactory, customPropTypes, getElementType, getUnhandledProps, @@ -12,6 +13,7 @@ import { useVerticalAlignProp, useWidthProp, } from '../../lib' +import { Icon } from '../../elements' function TableCell(props) { const { @@ -19,8 +21,10 @@ function TableCell(props) { children, className, collapsing, + content, disabled, error, + icon, negative, positive, singleLine, @@ -47,7 +51,16 @@ function TableCell(props) { const ElementType = getElementType(TableCell, props) const rest = getUnhandledProps(TableCell, props) - return {children} + if (children) { + return {children} + } + + return ( + + {Icon.create(icon)} + {content} + + ) } TableCell._meta = { @@ -73,7 +86,10 @@ TableCell.propTypes = { active: PropTypes.bool, /** Primary content of the TableCell. */ - children: PropTypes.node, + children: customPropTypes.every([ + customPropTypes.disallow(['content', 'icon']), + PropTypes.node, + ]), /** Classes that will be added to the TableCell className. */ className: PropTypes.string, @@ -81,12 +97,28 @@ TableCell.propTypes = { /** A cell can be collapsing so that it only uses as much space as required. */ collapsing: PropTypes.bool, + /** Shorthand for primary content of the TableCell. Mutually exclusive with the children. */ + content: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + /** A cell can be disabled. */ disabled: PropTypes.bool, /** A cell may call attention to an error or a negative value. */ error: PropTypes.bool, + /** Add an Icon by name, props object, or pass an */ + icon: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + PropTypes.element, + ]), + ]), + /** A cell may let a user know whether a value is bad. */ negative: PropTypes.bool, @@ -109,4 +141,6 @@ TableCell.propTypes = { width: PropTypes.oneOf(TableCell._meta.props.width), } +TableCell.create = createShorthandFactory(TableCell, content => ({ content })) + export default TableCell diff --git a/src/collections/Table/TableRow.js b/src/collections/Table/TableRow.js index 35a1337b00..984c5bbc19 100644 --- a/src/collections/Table/TableRow.js +++ b/src/collections/Table/TableRow.js @@ -2,6 +2,7 @@ import cx from 'classnames' import React, { PropTypes } from 'react' import { + createShorthandFactory, customPropTypes, getElementType, getUnhandledProps, @@ -11,6 +12,7 @@ import { useTextAlignProp, useVerticalAlignProp, } from '../../lib' +import TableCell from './TableCell' function TableRow(props) { const { @@ -19,6 +21,8 @@ function TableRow(props) { className, disabled, error, + itemAs, + items, negative, positive, textAlign, @@ -40,7 +44,15 @@ function TableRow(props) { const ElementType = getElementType(TableRow, props) const rest = getUnhandledProps(TableRow, props) - return {children} + if (children) { + return {children} + } + + return ( + + {items.map((item) => TableCell.create(item, { as: itemAs }))} + + ) } TableRow._meta = { @@ -55,6 +67,7 @@ TableRow._meta = { TableRow.defaultProps = { as: 'tr', + itemAs: 'td', } TableRow.propTypes = { @@ -65,7 +78,10 @@ TableRow.propTypes = { active: PropTypes.bool, /** Primary content of the TableRow. */ - children: PropTypes.node, + children: customPropTypes.every([ + customPropTypes.disallow(['content', 'icon']), + PropTypes.node, + ]), /** Classes that will be added to the TableRow className. */ className: PropTypes.string, @@ -76,6 +92,20 @@ TableRow.propTypes = { /** A row may call attention to an error or a negative value. */ error: PropTypes.bool, + /** An element type to render as (string or function). */ + itemAs: customPropTypes.as, + + /** Shorthand array of props for TableCell. Mutually exclusive with children. */ + items: customPropTypes.every([ + customPropTypes.disallow(['children']), + // Array of shorthands for MenuItem + PropTypes.arrayOf(PropTypes.oneOfType([ + PropTypes.string, + PropTypes.element, + PropTypes.object, + ])), + ]), + /** A row may let a user know whether a value is bad. */ negative: PropTypes.bool, @@ -92,4 +122,6 @@ TableRow.propTypes = { warning: PropTypes.bool, } +TableRow.create = createShorthandFactory(TableRow, items => ({ items })) + export default TableRow diff --git a/src/lib/factories.js b/src/lib/factories.js index 959a68381b..e899ef9897 100644 --- a/src/lib/factories.js +++ b/src/lib/factories.js @@ -46,7 +46,7 @@ export function createShorthand(Component, mapValueToProps, val, defaultProps = } else if (_.isPlainObject(val)) { type = 'props' usersProps = val - } else if (_.isString(val) || _.isNumber(val)) { + } else if (_.isString(val) || _.isNumber(val) || _.isArray(val)) { type = 'literal' usersProps = mapValueToProps(val) }