diff --git a/src/addons/Confirm/Confirm.js b/src/addons/Confirm/Confirm.js index 81dbfccdca..9935cb70d0 100644 --- a/src/addons/Confirm/Confirm.js +++ b/src/addons/Confirm/Confirm.js @@ -2,7 +2,12 @@ import React, { PropTypes } from 'react' import { Button } from '../../elements' import { Modal } from '../../modules' -import { getUnhandledProps, META } from '../../lib' +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' /** * A Confirm modal gives the user a choice to confirm or cancel an action @@ -30,6 +35,9 @@ Confirm._meta = { } Confirm.propTypes = { + /** An element type to render as (string or function). */ + as: customPropTypes.as, + /** Whether or not the modal is visible */ active: PropTypes.bool, diff --git a/src/elements/Header/Header.js b/src/elements/Header/Header.js index ec5119edb6..6c01345c95 100644 --- a/src/elements/Header/Header.js +++ b/src/elements/Header/Header.js @@ -100,10 +100,7 @@ Header.propTypes = { children: PropTypes.node, /** Primary content. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + content: customPropTypes.shorthand, /** Add an icon by icon name or pass an */ icon: customPropTypes.every([ diff --git a/src/lib/customPropTypes.js b/src/lib/customPropTypes.js index 70a388fee3..23febf1499 100644 --- a/src/lib/customPropTypes.js +++ b/src/lib/customPropTypes.js @@ -219,3 +219,62 @@ export const deprecate = (help, validator) => { return error } } + +// ---------------------------------------- +// Prop specific types +// ---------------------------------------- + +/** + * Ensure a prop conforms to shorthand prop standards. + */ +export const shorthand = (...args) => every([ + disallow(['children']), + PropTypes.string, +])(...args) + +/** + * Ensure a prop conforms to icon prop standards. + */ +export const icon = (...args) => every([ + disallow(['children', 'image']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object, + PropTypes.element, + ]), +])(...args) + +/** + * Ensure a prop conforms to icon prop standards. + */ +export const image = (...args) => every([ + disallow(['children', 'icon']), + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object, + PropTypes.element, + ]), +])(...args) + +/** + * Ensure a prop conforms to children prop standards. + */ +export const children = (Component) => (props, ...rest) => { + const disallowedProps = _.flow( + _.pickBy(checker => checker === shorthand || checker === icon || checker === image), + _.keys, + )(Component.propTypes) + + return every([ + disallow(disallowedProps), + PropTypes.node, + ])(props, ...rest) +} + +/** + * Ensure a prop can be used as a React key in an array of child components. + */ +export const childKey = (...args) => every([ + PropTypes.string, + PropTypes.number, +])(...args) diff --git a/src/views/Card/Card.js b/src/views/Card/Card.js index f9c00d8775..f3c9c7a50d 100644 --- a/src/views/Card/Card.js +++ b/src/views/Card/Card.js @@ -87,7 +87,7 @@ Card.propTypes = { /** A Card can center itself inside its container. */ centered: PropTypes.bool, - /** Primary content of the Card. */ + /** Primary content of the Card. Mutually exclusive with all shorthand props. */ children: customPropTypes.every([ customPropTypes.disallow(['description', 'header', 'image', 'meta']), PropTypes.node, @@ -99,41 +99,26 @@ Card.propTypes = { /** A Card can be formatted to display different colors. */ color: PropTypes.oneOf(Card._meta.props.color), - /** Shorthand prop for CardDescription. Mutually exclusive with children. */ - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + /** Shorthand prop for the CardDescription component. Mutually exclusive with children. */ + description: CardContent.propTypes.description, - /** Shorthand prop for CardContent containing extra prop. Mutually exclusive with children. */ - extra: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + /** Shorthand prop for the CardContent component containing extra prop. Mutually exclusive with children. */ + extra: PropTypes.shorthand, /** A Card can be formatted to take up the width of its container. */ fluid: PropTypes.bool, - /** Shorthand prop for CardHeader. Mutually exclusive with children. */ - header: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + /** Shorthand prop for the CardHeader component. Mutually exclusive with children. */ + header: CardContent.propTypes.header, /** Render as an `a` tag instead of a `div` and adds the href attribute. */ href: PropTypes.string, - /** A card can contain an Image component. */ - image: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + /** A card can contain an Image component. Mutually exclusive with children. */ + image: customPropTypes.image, - /** Shorthand prop for CardMeta. Mutually exclusive with children. */ - meta: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + /** Shorthand prop for the CardMeta component. Mutually exclusive with children. */ + meta: CardContent.propTypes.meta, /** Render as an `a` tag instead of a `div` and called with event on Card click. */ onClick: PropTypes.func, diff --git a/src/views/Card/CardContent.js b/src/views/Card/CardContent.js index faddf5d8c7..bf6f33584f 100644 --- a/src/views/Card/CardContent.js +++ b/src/views/Card/CardContent.js @@ -59,34 +59,16 @@ CardContent.propTypes = { className: PropTypes.string, /** Shorthand prop for CardDescription. Mutually exclusive with children. */ - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + description: CardDescription.propTypes.content, /** A card can contain extra content meant to be formatted separately from the main content */ extra: PropTypes.bool, - /** Shorthand prop for CardHeader. Mutually exclusive with children. */ - header: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + /** Shorthand prop for the CardHeader component. Mutually exclusive with children. */ + header: CardHeader.propTypes.content, - /** Shorthand prop for CardMeta. Mutually exclusive with children. */ - meta: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + /** Shorthand prop for the CardMeta component. Mutually exclusive with children. */ + meta: CardMeta.propTypes.content, } export default CardContent diff --git a/src/views/Card/CardDescription.js b/src/views/Card/CardDescription.js index 3b6b2dd430..df1df2d71a 100644 --- a/src/views/Card/CardDescription.js +++ b/src/views/Card/CardDescription.js @@ -40,13 +40,7 @@ CardDescription.propTypes = { className: PropTypes.string, /** Primary content of the CardDescription. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, } export default CardDescription diff --git a/src/views/Card/CardGroup.js b/src/views/Card/CardGroup.js index 621f20cf6d..1beaaddcf1 100644 --- a/src/views/Card/CardGroup.js +++ b/src/views/Card/CardGroup.js @@ -1,4 +1,5 @@ import cx from 'classnames' +import _ from 'lodash' import React, { PropTypes } from 'react' import { @@ -27,12 +28,18 @@ function CardGroup(props) { const rest = getUnhandledProps(CardGroup, props) const ElementType = getElementType(CardGroup, props) - const content = !items ? children : items.map(item => { - const key = item.key || [item.header, item.description].join('-') - return + if (children) { + return {children} + } + + const itemsJSX = _.map(items, item => { + const { childKey, itemProps } = item + const finalKey = childKey || [itemProps.header, itemProps.description].join('-') + + return }) - return {content} + return {itemsJSX} } CardGroup._meta = { @@ -64,10 +71,10 @@ CardGroup.propTypes = { items: customPropTypes.every([ customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ - description: PropTypes.node, - meta: PropTypes.node, - key: PropTypes.string, - header: PropTypes.node, + childKey: PropTypes.childKey, + // do not spread Card propTypes here + // it will be undefined due to circular imports + // allow the Card to validate the props it is sent })), ]), diff --git a/src/views/Card/CardHeader.js b/src/views/Card/CardHeader.js index 3c947d916b..5409f641ef 100644 --- a/src/views/Card/CardHeader.js +++ b/src/views/Card/CardHeader.js @@ -40,10 +40,7 @@ CardHeader.propTypes = { className: PropTypes.string, /** Primary content of the CardHeader. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), + content: customPropTypes.shorthand, } export default CardHeader diff --git a/src/views/Card/CardMeta.js b/src/views/Card/CardMeta.js index c6c20eff9f..193ac4255f 100644 --- a/src/views/Card/CardMeta.js +++ b/src/views/Card/CardMeta.js @@ -40,13 +40,7 @@ CardMeta.propTypes = { className: PropTypes.string, /** Primary content of the CardMeta. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, } export default CardMeta diff --git a/src/views/Feed/FeedContent.js b/src/views/Feed/FeedContent.js index 6e051db084..d8f049506b 100644 --- a/src/views/Feed/FeedContent.js +++ b/src/views/Feed/FeedContent.js @@ -61,13 +61,7 @@ FeedContent.propTypes = { className: PropTypes.string, /** Shorthand for children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, /** An event can contain a date. */ date: FeedDate.propTypes.content, @@ -81,7 +75,7 @@ FeedContent.propTypes = { /** Shorthand for the FeedMeta component. Mutually exclusive with children. */ meta: FeedMeta.propTypes.content, - /** Shorthand for the FeedSummary component. Mutually exclusive with children. */ + /** Shorthand for FeedSummary. */ summary: FeedSummary.propTypes.content, } diff --git a/src/views/Feed/FeedDate.js b/src/views/Feed/FeedDate.js index 7f80d3c4bf..c1d1c3b534 100644 --- a/src/views/Feed/FeedDate.js +++ b/src/views/Feed/FeedDate.js @@ -39,13 +39,7 @@ FeedDate.propTypes = { className: PropTypes.string, /** Shorthand for children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, } export default FeedDate diff --git a/src/views/Feed/FeedEvent.js b/src/views/Feed/FeedEvent.js index 844c2db149..eb9548c037 100644 --- a/src/views/Feed/FeedEvent.js +++ b/src/views/Feed/FeedEvent.js @@ -12,7 +12,7 @@ import FeedContent from './FeedContent' import FeedLabel from './FeedLabel' function FeedEvent(props) { - const { content, children, className, date, extraImages, extraText, image, icon, meta, summary } = props + const { children, className, date, extraImages, extraText, image, icon, meta, summary } = props const classes = cx(className, 'event') const rest = getUnhandledProps(FeedEvent, props) const ElementType = getElementType(FeedEvent, props) @@ -41,18 +41,7 @@ FeedEvent.propTypes = { as: customPropTypes.as, /** Primary content of the FeedEvent. Mutually exclusive with all shorthand props. */ - children: customPropTypes.every([ - customPropTypes.disallow([ - 'date', - 'extraImages', - 'extraText', - 'icon', - 'image', - 'meta', - 'summary', - ]), - PropTypes.node, - ]), + children: customPropTypes.children(FeedEvent), /** Classes that will be added to the FeedEvent className. */ className: PropTypes.string, @@ -70,26 +59,10 @@ FeedEvent.propTypes = { extraText: FeedContent.propTypes.extraText, /** An event can contain icon label. Mutually exclusive with children. */ - icon: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.element, - ]), - ]), + icon: customPropTypes.icon, /** An event can contain image label. Mutually exclusive with children. */ - image: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.element, - ]), - ]), + image: customPropTypes.image, /** Shorthand for FeedMeta. Mutually exclusive with children. */ meta: FeedContent.propTypes.meta, diff --git a/src/views/Feed/FeedLabel.js b/src/views/Feed/FeedLabel.js index 2f584c7f4d..ba4befb19a 100644 --- a/src/views/Feed/FeedLabel.js +++ b/src/views/Feed/FeedLabel.js @@ -49,35 +49,13 @@ FeedLabel.propTypes = { className: PropTypes.string, /** Shorthand for children. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, /** An event can contain icon label. Mutually exclusive with children. */ - icon: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.element, - ]), - ]), + icon: customPropTypes.icon, /** An event can contain image label. Mutually exclusive with children. */ - image: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.element, - ]), - ]), + image: customPropTypes.image, } export default FeedLabel diff --git a/src/views/Feed/FeedLike.js b/src/views/Feed/FeedLike.js index 4280df363c..69d9378ffd 100644 --- a/src/views/Feed/FeedLike.js +++ b/src/views/Feed/FeedLike.js @@ -51,24 +51,10 @@ FeedLike.propTypes = { className: PropTypes.string, /** Shorthand for children. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, /** Shorthand for icon. Mutually exclusive with children. */ - icon: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.object, - PropTypes.element, - ]), - ]), + icon: customPropTypes.icon, } export default FeedLike diff --git a/src/views/Feed/FeedMeta.js b/src/views/Feed/FeedMeta.js index 4ac79c5240..3cd87f33b4 100644 --- a/src/views/Feed/FeedMeta.js +++ b/src/views/Feed/FeedMeta.js @@ -38,7 +38,7 @@ FeedMeta.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the FeedMeta. */ + /** Primary content of the FeedMeta. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content', 'like']), PropTypes.node, @@ -48,13 +48,7 @@ FeedMeta.propTypes = { className: PropTypes.string, /** Shorthand for children. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, /** Shorthand for the FeedLike component. Mutually exclusive with children. */ like: FeedLike.propTypes.content, diff --git a/src/views/Feed/FeedSummary.js b/src/views/Feed/FeedSummary.js index 36dc0de047..4cbbe76bdf 100644 --- a/src/views/Feed/FeedSummary.js +++ b/src/views/Feed/FeedSummary.js @@ -41,40 +41,19 @@ FeedSummary.propTypes = { as: customPropTypes.as, /** Primary content of the FeedSummary. */ - children: customPropTypes.every([ - customPropTypes.disallow(['content', 'date', 'user']), - PropTypes.node, - ]), + children: customPropTypes.children(FeedSummary), /** Classes that will be added to the FeedSummary className. */ className: PropTypes.string, /** Shorthand for children. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, /** Shorthand for the FeedDate component. Mutually exclusive with children. */ - date: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + date: customPropTypes.shorthand, /** Shorthand for the FeedUser component. Mutually exclusive with children. */ - user: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + user: customPropTypes.shorthand, } export default FeedSummary diff --git a/src/views/Feed/FeedUser.js b/src/views/Feed/FeedUser.js index bc49ff432e..1aaab9cdc5 100644 --- a/src/views/Feed/FeedUser.js +++ b/src/views/Feed/FeedUser.js @@ -37,13 +37,7 @@ FeedUser.propTypes = { className: PropTypes.string, /** Shorthand for children. Mutually exclusive with children. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + content: customPropTypes.shorthand, } FeedUser.defaultProps = { diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index 45c9d87b53..aafcd59ca2 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -61,47 +61,32 @@ Item.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the Item. */ - children: PropTypes.node, + /** Primary content of the Item. Mutually exclusive with all shorthand props. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content', 'description', 'extra', 'image', 'header', 'meta']), + PropTypes.node, + ]), /** Classes that will be added to the Item className. */ className: PropTypes.string, - /** Shorthand for ItemContent component. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemContent component. Mutually exclusive with content. */ + content: ItemContent.propTypes.content, - /** Shorthand for ItemDescription component. */ - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemDescription component. Mutually exclusive with content. */ + description: ItemContent.propTypes.description, - /** Shorthand for ItemExtra component. */ - extra: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemExtra component. Mutually exclusive with content. */ + extra: ItemContent.propTypes.extra, - /** Shorthand for ItemImage component. */ - image: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemImage component. Mutually exclusive with content. */ + image: customPropTypes.image, - /** Shorthand for ItemHeader component. */ - header: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemHeader component. Mutually exclusive with content. */ + header: ItemContent.propTypes.header, - /** Shorthand for ItemMeta component. */ - meta: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemMeta component. Mutually exclusive with content. */ + meta: ItemContent.propTypes.meta, } export default Item diff --git a/src/views/Item/ItemContent.js b/src/views/Item/ItemContent.js index 5a645aefe0..9899511198 100644 --- a/src/views/Item/ItemContent.js +++ b/src/views/Item/ItemContent.js @@ -53,46 +53,31 @@ ItemContent.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemContent. */ + /** Primary content of the ItemContent. Mutually exclusive with all shorthand props. */ children: customPropTypes.every([ - customPropTypes.disallow(['content']), + customPropTypes.disallow(['content', 'description', 'extra', 'header', 'meta']), PropTypes.node, ]), /** Classes that will be added to the ItemContent className. */ className: PropTypes.string, - /** Primary content of the ItemContent. Mutually exclusive with the children prop. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for primary content of the ItemContent. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, - /** Shorthand for of the ItemDescription. Mutually exclusive with the children prop. */ - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for of the ItemDescription. Mutually exclusive with the children. */ + description: ItemDescription.propTypes.content, - /** Shorthand for ItemExtra component. Mutually exclusive with the children prop. */ - extra: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemExtra component. Mutually exclusive with the children. */ + extra: ItemExtra.propTypes.content, - /** Shorthand for ItemHeader component. Mutually exclusive with the children prop. */ - header: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for ItemHeader component. Mutually exclusive with the children. */ + header: ItemHeader.propTypes.content, - /** Shorthand for ItemMeta component. Mutually exclusive with the children prop. */ - meta: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for the ItemMeta component. Mutually exclusive with the children. */ + meta: ItemMeta.propTypes.content, - /** Content can specify its vertical alignment */ + /** Content can specify its vertical alignment. */ verticalAlign: PropTypes.oneOf(ItemContent._meta.props.verticalAlign), } diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js index 174a30dc89..1b36380faa 100644 --- a/src/views/Item/ItemDescription.js +++ b/src/views/Item/ItemDescription.js @@ -30,7 +30,7 @@ ItemDescription.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemDescription. */ + /** Primary content of the ItemDescription. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, @@ -39,11 +39,8 @@ ItemDescription.propTypes = { /** Classes that will be added to the ItemDescription className. */ className: PropTypes.string, - /** Primary content of the ItemDescription. Mutually exclusive with the children prop. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for primary content of the ItemDescription. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, } export default ItemDescription diff --git a/src/views/Item/ItemExtra.js b/src/views/Item/ItemExtra.js index 46757c844c..948389dcea 100644 --- a/src/views/Item/ItemExtra.js +++ b/src/views/Item/ItemExtra.js @@ -30,7 +30,7 @@ ItemExtra.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemExtra. */ + /** Primary content of the ItemExtra. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, @@ -39,11 +39,8 @@ ItemExtra.propTypes = { /** Classes that will be added to the ItemExtra className. */ className: PropTypes.string, - /** Primary content of the ItemExtra. Mutually exclusive with the children prop. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for primary content of the ItemExtra. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, } export default ItemExtra diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index 540c959bac..0ef0ae2499 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -56,8 +56,11 @@ ItemGroup.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemGroup. */ - children: PropTypes.node, + /** Primary content of the ItemGroup. Mutually exclusive with items. */ + children: customPropTypes.every([ + customPropTypes.disallow(['items']), + PropTypes.node, + ]), /** Classes that will be added to the ItemGroup className. */ className: PropTypes.string, @@ -65,16 +68,14 @@ ItemGroup.propTypes = { /** Items can be divided to better distinguish between grouped content. */ divided: PropTypes.bool, - /** Array of props for Item. */ + /** Array of props for Item. Mutually exclusive with children. */ items: customPropTypes.every([ customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ - childKey: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string, - ]), - // this object is spread on the Item - // allow it to validate props instead + childKey: customPropTypes.childKey, + // do not spread Item propTypes here + // it will be undefined due to circular imports + // allow the Item to validate the props it is sent })), ]), diff --git a/src/views/Item/ItemHeader.js b/src/views/Item/ItemHeader.js index de3269a236..cc686b5180 100644 --- a/src/views/Item/ItemHeader.js +++ b/src/views/Item/ItemHeader.js @@ -30,7 +30,7 @@ ItemHeader.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemHeader. */ + /** Primary content of the ItemHeader. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, @@ -39,11 +39,8 @@ ItemHeader.propTypes = { /** Classes that will be added to the ItemHeader className. */ className: PropTypes.string, - /** Primary content of the ItemHeader. Mutually exclusive with the children prop. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for primary content of the ItemHeader. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, } export default ItemHeader diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index a81eb84454..f93076e675 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -22,4 +22,6 @@ ItemImage._meta = { type: META.TYPES.VIEW, } +ItemImage.propTypes = Image.propTypes + export default ItemImage diff --git a/src/views/Item/ItemMeta.js b/src/views/Item/ItemMeta.js index 5cee57eff1..8d4ff30bac 100644 --- a/src/views/Item/ItemMeta.js +++ b/src/views/Item/ItemMeta.js @@ -30,7 +30,7 @@ ItemMeta.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the ItemMeta. */ + /** Primary content of the ItemMeta. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, @@ -39,11 +39,8 @@ ItemMeta.propTypes = { /** Classes that will be added to the ItemMeta className. */ className: PropTypes.string, - /** Primary content of the ItemMeta. Mutually exclusive with the children prop. */ - content: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for primary content of the ItemMeta. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, } export default ItemMeta diff --git a/src/views/Statistic/Statistic.js b/src/views/Statistic/Statistic.js index 3fdbfbbb95..4d3ffe6266 100644 --- a/src/views/Statistic/Statistic.js +++ b/src/views/Statistic/Statistic.js @@ -36,8 +36,8 @@ function Statistic(props) { return ( - - + + ) } @@ -56,7 +56,7 @@ Statistic.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the Statistic. */ + /** Primary content of the Statistic. Mutually exclusive with all shorthand props. */ children: customPropTypes.every([ customPropTypes.disallow(['label', 'value']), PropTypes.node, @@ -77,11 +77,8 @@ Statistic.propTypes = { /** A statistic can be formatted to fit on a dark background. */ inverted: PropTypes.bool, - /** Label content of the Statistic. Mutually exclusive with the children prop. */ - label: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), + /** Shorthand for the StatisticLabel component. Mutually exclusive with the children. */ + label: customPropTypes.shorthand, /** A statistic can vary in size. */ size: PropTypes.oneOf(Statistic._meta.props.size), @@ -89,14 +86,8 @@ Statistic.propTypes = { /** Format the StatisticValue with smaller font size to fit nicely beside number values. */ text: PropTypes.bool, - /** Value content of the Statistic. Mutually exclusive with the children prop. */ - value: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + /** Shorthand for the StatisticValue component. Mutually exclusive with the children. */ + value: customPropTypes.shorthand, } Statistic.Group = StatisticGroup diff --git a/src/views/Statistic/StatisticGroup.js b/src/views/Statistic/StatisticGroup.js index 03dd6c57ab..7c28e5f57b 100644 --- a/src/views/Statistic/StatisticGroup.js +++ b/src/views/Statistic/StatisticGroup.js @@ -49,9 +49,9 @@ StatisticGroup.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the StatisticGroup. */ + /** Primary content of the StatisticGroup. Mutually exclusive with items. */ children: customPropTypes.every([ - customPropTypes.disallow(['content']), + customPropTypes.disallow(['items']), PropTypes.node, ]), @@ -61,13 +61,14 @@ StatisticGroup.propTypes = { /** A statistic can present its measurement horizontally. */ horizontal: PropTypes.bool, - /** Array of props for Statistic. */ + /** Array of props for Statistic. Mutually exclusive with children. */ items: customPropTypes.every([ customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ - childKey: PropTypes.string, - // this object is spread on the Statistic - // allow it to validate props instead + childKey: customPropTypes.childKey, + // do not spread Statistic propTypes here + // it will be undefined due to circular imports + // allow the Statistic to validate the props it is sent })), ]), diff --git a/src/views/Statistic/StatisticLabel.js b/src/views/Statistic/StatisticLabel.js index 62e1edba39..a5538401f6 100644 --- a/src/views/Statistic/StatisticLabel.js +++ b/src/views/Statistic/StatisticLabel.js @@ -9,12 +9,12 @@ import { } from '../../lib' function StatisticLabel(props) { - const { children, className, label } = props + const { children, className, content } = props const classes = cx(className, 'label') const rest = getUnhandledProps(StatisticLabel, props) const ElementType = getElementType(StatisticLabel, props) - return {children || label} + return {children || content} } StatisticLabel._meta = { @@ -27,20 +27,17 @@ StatisticLabel.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the StatisticLabel. */ + /** Primary content of the StatisticLabel. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, ]), + /** Shorthand for primary content of the StatisticLabel. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, + /** Classes that will be added to the StatisticLabel className. */ className: PropTypes.string, - - /** Primary content of the StatisticLabel. Mutually exclusive with the children prop. */ - label: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), } export default StatisticLabel diff --git a/src/views/Statistic/StatisticValue.js b/src/views/Statistic/StatisticValue.js index 27c35a2afd..3ec105e1ae 100644 --- a/src/views/Statistic/StatisticValue.js +++ b/src/views/Statistic/StatisticValue.js @@ -10,12 +10,12 @@ import { } from '../../lib' function StatisticValue(props) { - const { children, className, text, value } = props + const { children, className, content, text } = props const classes = cx(useKeyOnly(text, 'text'), className, 'value') const rest = getUnhandledProps(StatisticValue, props) const ElementType = getElementType(StatisticValue, props) - return {children || value} + return {children || content} } StatisticValue._meta = { @@ -28,7 +28,7 @@ StatisticValue.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Primary content of the StatisticValue. */ + /** Primary content of the StatisticValue. Mutually exclusive with content. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), PropTypes.node, @@ -37,14 +37,11 @@ StatisticValue.propTypes = { /** Classes that will be added to the StatisticValue className. */ className: PropTypes.string, + /** Shorthand for primary content of the StatisticValue. Mutually exclusive with the children. */ + content: customPropTypes.shorthand, + /** Format the value with smaller font size to fit nicely beside number values. */ text: PropTypes.bool, - - /** Primary content of the StatisticValue. Mutually exclusive with the children prop. */ - value: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.string, - ]), } export default StatisticValue