From ffd1a6061cac6a4656c34324e453afd03c5dafe2 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Wed, 24 Aug 2016 14:01:24 +0300 Subject: [PATCH 01/18] wip --- src/views/Item/ItemDescription.js | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/views/Item/ItemDescription.js diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js new file mode 100644 index 0000000000..61302e0e59 --- /dev/null +++ b/src/views/Item/ItemDescription.js @@ -0,0 +1,41 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, +} from '../../lib' + +function ItemDescription(props) { + const { children, className, content } = props + const classes = cx(className, 'description') + const rest = getUnhandledProps(ItemDescription, props) + + return
{children || content}
+} + +ItemDescription._meta = { + name: 'ItemDescription', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemDescription.propTypes = { + /** Primary content of the ItemDescription. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemDescription From 580d38d8a6580430c4ea98ee57c2041863c0636e Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 16:44:48 +0300 Subject: [PATCH 02/18] wip --- .../app/Examples/views/Item/Content/Images.js | 22 +++++++ docs/app/Examples/views/Item/Content/index.js | 58 +++++++++++++++++++ docs/app/Examples/views/Item/Types/index.js | 12 ++++ .../Examples/views/Item/Variations/index.js | 12 ++++ docs/app/Examples/views/Item/index.js | 15 +++++ src/views/Item/Item.js | 54 ++++++----------- src/views/Item/ItemContent.js | 49 ++++++++++++++++ src/views/Item/ItemDescription.js | 10 +++- src/views/Item/ItemGroup.js | 25 +++++--- src/views/Item/ItemImage.js | 15 +++++ 10 files changed, 227 insertions(+), 45 deletions(-) create mode 100644 docs/app/Examples/views/Item/Content/Images.js create mode 100644 docs/app/Examples/views/Item/Content/index.js create mode 100644 docs/app/Examples/views/Item/Types/index.js create mode 100644 docs/app/Examples/views/Item/Variations/index.js create mode 100644 docs/app/Examples/views/Item/index.js create mode 100644 src/views/Item/ItemContent.js create mode 100644 src/views/Item/ItemImage.js diff --git a/docs/app/Examples/views/Item/Content/Images.js b/docs/app/Examples/views/Item/Content/Images.js new file mode 100644 index 0000000000..294d39a131 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Images.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Group, Image } = Item + +const Images = () => ( + + + + + + + + + + + + + +) + +export default Images diff --git a/docs/app/Examples/views/Item/Content/index.js b/docs/app/Examples/views/Item/Content/index.js new file mode 100644 index 0000000000..10670c13c0 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/index.js @@ -0,0 +1,58 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Content = () => ( + + + + + + + + + + + + + + + + + +) + +export default Content diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js new file mode 100644 index 0000000000..df1b7d52c1 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/index.js @@ -0,0 +1,12 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Types = () => ( + + + +) + +export default Types diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js new file mode 100644 index 0000000000..f7affd6648 --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -0,0 +1,12 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Variations = () => ( + + + +) + +export default Variations diff --git a/docs/app/Examples/views/Item/index.js b/docs/app/Examples/views/Item/index.js new file mode 100644 index 0000000000..e64f99cd82 --- /dev/null +++ b/docs/app/Examples/views/Item/index.js @@ -0,0 +1,15 @@ +import React from 'react' + +import Content from './Content' +import Types from './Types' +import Variations from './Variations' + +const ItemExamples = () => ( +
+ + + +
+) + +export default ItemExamples diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index 60c4455852..c32918f9db 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -1,5 +1,4 @@ import cx from 'classnames' -import _ from 'lodash' import React, { PropTypes } from 'react' import { @@ -8,35 +7,21 @@ import { getUnhandledProps, META, } from '../../lib' + +import ItemDescription from './ItemDescription' import ItemGroup from './ItemGroup' +import ItemImage from './ItemImage' function Item(props) { - const { children, className, contentClassName, description, extra, header, image, meta } = props - const rest = getUnhandledProps(Item, props) - - const { className: imageClassName, ...imageProps } = _.get(image, 'props', {}) - + const { children, className, image } = props const classes = cx(className, 'item') - const imageClasses = cx('ui', imageClassName, 'image') - const contentClasses = cx(contentClassName, 'content') - - const _description = children || description - - const content = header || meta || extra ? [ - header &&
{header}
, - meta &&
{meta}
, - _description &&
{_description}
, - extra &&
{extra}
, - ] : [ - _description, - ] - + const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) return ( - {image &&
} - {content &&
{content}
} + {image && } + {children}
) } @@ -46,6 +31,10 @@ Item._meta = { type: META.TYPES.VIEW, } +Item.Description = ItemDescription +Item.Group = ItemGroup +Item.Image = ItemImage + Item.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.oneOfType([ @@ -53,26 +42,17 @@ Item.propTypes = { PropTypes.func, ]), + /** Primary content of the Item. */ children: customPropTypes.every([ - customPropTypes.disallow(['description']), + customPropTypes.disallow(['content']), PropTypes.node, ]), + + /** Classes that will be added to the Item className. */ className: PropTypes.string, - contentClassName: PropTypes.string, - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), - extra: PropTypes.node, - header: PropTypes.node, - image: PropTypes.node, - meta: PropTypes.node, -} -Item.defaultProps = { - contentClassName: 'middle aligned', + /** Shorthand for ItemImage component. */ + image: PropTypes.string, } -Item.Group = ItemGroup - export default Item diff --git a/src/views/Item/ItemContent.js b/src/views/Item/ItemContent.js new file mode 100644 index 0000000000..8e959d29be --- /dev/null +++ b/src/views/Item/ItemContent.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, +getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemContent(props) { + const { children, className, content } = props + const classes = cx(className, 'content') + const rest = getUnhandledProps(ItemContent, props) + const ElementType = getElementType(ItemContent, props) + + return {children || content} +} + +ItemContent._meta = { + name: 'ItemContent', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemContent.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemContent. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + 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, + ]), +} + +export default ItemContent diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js index 61302e0e59..760b71627c 100644 --- a/src/views/Item/ItemDescription.js +++ b/src/views/Item/ItemDescription.js @@ -3,6 +3,7 @@ import React, { PropTypes } from 'react' import { customPropTypes, +getElementType, getUnhandledProps, META, } from '../../lib' @@ -11,8 +12,9 @@ function ItemDescription(props) { const { children, className, content } = props const classes = cx(className, 'description') const rest = getUnhandledProps(ItemDescription, props) + const ElementType = getElementType(ItemDescription, props) - return
{children || content}
+ return {children || content} } ItemDescription._meta = { @@ -22,6 +24,12 @@ ItemDescription._meta = { } ItemDescription.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + /** Primary content of the ItemDescription. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index c193fe304b..66178e2a05 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -1,6 +1,11 @@ -import React, { PropTypes } from 'react' import cx from 'classnames' -import { getElementType, getUnhandledProps, META } from '../../lib' +import React, { PropTypes } from 'react' + +import { + getElementType, + getUnhandledProps, + META, +} from '../../lib' function ItemGroup(props) { const { className, children } = props @@ -11,6 +16,12 @@ function ItemGroup(props) { return {children} } +ItemGroup._meta = { + name: 'ItemGroup', + type: META.TYPES.VIEW, + parent: 'Item', +} + ItemGroup.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.oneOfType([ @@ -18,14 +29,14 @@ ItemGroup.propTypes = { PropTypes.func, ]), + /** Primary content of the ItemGroup. */ children: PropTypes.node, + + /** Classes that will be added to the ItemGroup className. */ className: PropTypes.string, -} -ItemGroup._meta = { - name: 'ItemGroup', - type: META.TYPES.VIEW, - parent: 'Item', + /** Items can be divided to better distinguish between grouped content. */ + divided: PropTypes.bool, } export default ItemGroup diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js new file mode 100644 index 0000000000..07bb6f7c2d --- /dev/null +++ b/src/views/Item/ItemImage.js @@ -0,0 +1,15 @@ +import React, { PropTypes } from 'react' +import { META } from '../../lib' +import Image from '../../elements/Image/Image' + +function ItemImage(props) { + return +} + +ItemImage._meta = { + name: 'ItemImage', + parent: 'Item', + type: META.TYPES.VIEW, +} + +export default ItemImage From b6426b10249441dbf92b9bc832ee39c617430cf4 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 16:44:48 +0300 Subject: [PATCH 03/18] wip --- src/views/Item/ItemDescription.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js index 760b71627c..b498de4199 100644 --- a/src/views/Item/ItemDescription.js +++ b/src/views/Item/ItemDescription.js @@ -3,7 +3,7 @@ import React, { PropTypes } from 'react' import { customPropTypes, -getElementType, + getElementType, getUnhandledProps, META, } from '../../lib' From eb3d50a1f839c0837bd010055d3539fa78a92b20 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 18:57:23 +0300 Subject: [PATCH 04/18] wip --- .../Examples/views/Item/Content/Contents.js | 25 ++++++++ .../views/Item/Content/Descriptions.js | 42 +++++++++++++ .../views/Item/Content/ExtraContent.js | 38 ++++++++++++ .../Examples/views/Item/Content/Headers.js | 29 +++++++++ .../app/Examples/views/Item/Content/Images.js | 4 +- docs/app/Examples/views/Item/Content/Link.js | 39 ++++++++++++ .../Examples/views/Item/Content/Metadata.js | 39 ++++++++++++ .../Examples/views/Item/Content/Ratings.js | 32 ++++++++++ docs/app/Examples/views/Item/Content/index.js | 16 ++--- docs/app/Examples/views/Item/Types/Items.js | 34 +++++++++++ docs/app/Examples/views/Item/Types/index.js | 8 ++- .../Examples/views/Item/Variations/index.js | 2 + src/views/Item/Item.js | 59 ++++++++++++++++--- src/views/Item/ItemContent.js | 57 ++++++++++++++++-- src/views/Item/ItemExtra.js | 49 +++++++++++++++ src/views/Item/ItemGroup.js | 11 +++- src/views/Item/ItemHeader.js | 49 +++++++++++++++ src/views/Item/ItemImage.js | 12 +++- src/views/Item/ItemMeta.js | 49 +++++++++++++++ 19 files changed, 566 insertions(+), 28 deletions(-) create mode 100644 docs/app/Examples/views/Item/Content/Contents.js create mode 100644 docs/app/Examples/views/Item/Content/Descriptions.js create mode 100644 docs/app/Examples/views/Item/Content/ExtraContent.js create mode 100644 docs/app/Examples/views/Item/Content/Headers.js create mode 100644 docs/app/Examples/views/Item/Content/Link.js create mode 100644 docs/app/Examples/views/Item/Content/Metadata.js create mode 100644 docs/app/Examples/views/Item/Content/Ratings.js create mode 100644 docs/app/Examples/views/Item/Types/Items.js create mode 100644 src/views/Item/ItemExtra.js create mode 100644 src/views/Item/ItemHeader.js create mode 100644 src/views/Item/ItemMeta.js diff --git a/docs/app/Examples/views/Item/Content/Contents.js b/docs/app/Examples/views/Item/Content/Contents.js new file mode 100644 index 0000000000..da1f1dcce2 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Contents.js @@ -0,0 +1,25 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Image } = Item + +const Contents = () => ( + + + + Content A + + + + + Content B + + + + + + + +) + +export default Contents diff --git a/docs/app/Examples/views/Item/Content/Descriptions.js b/docs/app/Examples/views/Item/Content/Descriptions.js new file mode 100644 index 0000000000..40aa8e7242 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Descriptions.js @@ -0,0 +1,42 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Description, Group, Header, Image } = Item +const description = [ + 'Cute dogs come in a variety of shapes and sizes. Some cute dogs are cute for their adorable faces, others for their', + 'tiny stature, and even others for their massive size.', +].join(' ') + +const Descriptions = () => ( + + + + + +
Cute Dog
+ +

{description}

+

+ Many people also have their own barometers for what makes a cute dog. +

+
+
+
+ + + + + +
Cute Dog
+ +
+
+ + + + + +
+) + +export default Descriptions diff --git a/docs/app/Examples/views/Item/Content/ExtraContent.js b/docs/app/Examples/views/Item/Content/ExtraContent.js new file mode 100644 index 0000000000..707188f47a --- /dev/null +++ b/docs/app/Examples/views/Item/Content/ExtraContent.js @@ -0,0 +1,38 @@ +import React from 'react' +import { Item, Icon, Image as ImageComponent } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image } = Item +const image = + +const ExtraContent = () => ( + + + + + +
Cute Dog
+ {image} + + 121 Votes + +
+
+ + + + + +
Cute Dog
+ {image} + +
+
+ + + + + +
+) + +export default ExtraContent diff --git a/docs/app/Examples/views/Item/Content/Headers.js b/docs/app/Examples/views/Item/Content/Headers.js new file mode 100644 index 0000000000..879fb88154 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Headers.js @@ -0,0 +1,29 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Headers = () => ( + + + + +
12 Years a Slave
+
+
+ + + + +
+ + + + + + + + +) + +export default Headers diff --git a/docs/app/Examples/views/Item/Content/Images.js b/docs/app/Examples/views/Item/Content/Images.js index 294d39a131..3f89a8470c 100644 --- a/docs/app/Examples/views/Item/Content/Images.js +++ b/docs/app/Examples/views/Item/Content/Images.js @@ -6,9 +6,7 @@ const { Group, Image } = Item const Images = () => ( - - - + diff --git a/docs/app/Examples/views/Item/Content/Link.js b/docs/app/Examples/views/Item/Content/Link.js new file mode 100644 index 0000000000..32fa689ccd --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Link.js @@ -0,0 +1,39 @@ +import React from 'react' +import { Item, Image as ImageComponent } from 'stardust' + +const { Content, Description, Group, Header, Image, Meta } = Item +const image = + +const Link = () => ( + + + + + +
Arrowhead Valley Camp
+ + $1200 + 1 Month + + {image} +
+
+ + + + + +
Buck's Homebrew Stayaway
+ + {image} +
+
+ + + + + +
+) + +export default Link diff --git a/docs/app/Examples/views/Item/Content/Metadata.js b/docs/app/Examples/views/Item/Content/Metadata.js new file mode 100644 index 0000000000..3140bfe6ab --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Metadata.js @@ -0,0 +1,39 @@ +import React from 'react' +import { Item, Image as ImageComponent } from 'stardust' + +const { Content, Description, Group, Header, Image, Meta } = Item +const image = + +const Metadata = () => ( + + + + + +
Arrowhead Valley Camp
+ + $1200 + 1 Month + + {image} +
+
+ + + + + +
Buck's Homebrew Stayaway
+ + {image} +
+
+ + + + + +
+) + +export default Metadata diff --git a/docs/app/Examples/views/Item/Content/Ratings.js b/docs/app/Examples/views/Item/Content/Ratings.js new file mode 100644 index 0000000000..b7edeed215 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Ratings.js @@ -0,0 +1,32 @@ +import React from 'react' +import { Icon, Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Ratings = () => ( + + + + + +
+ + Veronika Ossi +
+
+
+ + + + + +
+ + Justen Kitsune +
+
+
+
+) + +export default Ratings diff --git a/docs/app/Examples/views/Item/Content/index.js b/docs/app/Examples/views/Item/Content/index.js index 10670c13c0..8c5e3bcc8e 100644 --- a/docs/app/Examples/views/Item/Content/index.js +++ b/docs/app/Examples/views/Item/Content/index.js @@ -14,13 +14,13 @@ const Content = () => ( ( ( examplePath='views/Item/Content/ExtraContent' /> - + ) diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js new file mode 100644 index 0000000000..fdd159eda6 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Image, Item } from 'stardust' + +const Metadata = () => ( + + + + + + Header + Description + + + + Additional Details + + + + + + + + Header + Description + + + + Additional Details + + + +) + +export default Metadata diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js index df1b7d52c1..8e5fe20e0c 100644 --- a/docs/app/Examples/views/Item/Types/index.js +++ b/docs/app/Examples/views/Item/Types/index.js @@ -3,9 +3,15 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' +// TODO: Example with props + const Types = () => ( - + ) diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js index f7affd6648..5dca4bad5f 100644 --- a/docs/app/Examples/views/Item/Variations/index.js +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -3,6 +3,8 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' +// TODO: All variations examples + const Variations = () => ( diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index c32918f9db..5ee24f9349 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -8,20 +8,37 @@ import { META, } from '../../lib' +import ItemContent from './ItemContent' import ItemDescription from './ItemDescription' +import ItemExtra from './ItemExtra' import ItemGroup from './ItemGroup' +import ItemHeader from './ItemHeader' import ItemImage from './ItemImage' +import ItemMeta from './ItemMeta' +/** + * An item view presents large collections of site content for display + * */ function Item(props) { - const { children, className, image } = props + const { children, className, content, extra, header, image, meta } = props const classes = cx(className, 'item') const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) + if (children) { + return {children} + } + return ( {image && } - {children} + + ) } @@ -31,9 +48,13 @@ Item._meta = { type: META.TYPES.VIEW, } +Item.Content = ItemContent Item.Description = ItemDescription +Item.Extra = ItemExtra Item.Group = ItemGroup +Item.Header = ItemHeader Item.Image = ItemImage +Item.Meta = ItemMeta Item.propTypes = { /** An element type to render as (string or function). */ @@ -43,16 +64,40 @@ Item.propTypes = { ]), /** Primary content of the Item. */ - children: customPropTypes.every([ - customPropTypes.disallow(['content']), - PropTypes.node, - ]), + children: 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 ItemExtra component. */ + extra: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + /** Shorthand for ItemImage component. */ - image: PropTypes.string, + image: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemHeader component. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemMeta component. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), } export default Item diff --git a/src/views/Item/ItemContent.js b/src/views/Item/ItemContent.js index 8e959d29be..f1df748a58 100644 --- a/src/views/Item/ItemContent.js +++ b/src/views/Item/ItemContent.js @@ -3,24 +3,46 @@ import React, { PropTypes } from 'react' import { customPropTypes, -getElementType, + getElementType, getUnhandledProps, META, + SUI, + useVerticalAlignProp, } from '../../lib' +import ItemHeader from './ItemHeader' +import ItemDescription from './ItemDescription' +import ItemExtra from './ItemExtra' +import ItemMeta from './ItemMeta' function ItemContent(props) { - const { children, className, content } = props - const classes = cx(className, 'content') + const { children, className, content, description, extra, header, meta, verticalAlign } = props + const classes = cx( + className, + useVerticalAlignProp(verticalAlign), + 'content', + ) + const rest = getUnhandledProps(ItemContent, props) const ElementType = getElementType(ItemContent, props) - return {children || content} + return ( + + {header && } + {meta && } + {description && } + {extra && } + {children || content} + + ) } ItemContent._meta = { name: 'ItemContent', parent: 'Item', type: META.TYPES.VIEW, + props: { + verticalAlign: SUI.VERTICAL_ALIGNMENTS, + }, } ItemContent.propTypes = { @@ -44,6 +66,33 @@ ItemContent.propTypes = { customPropTypes.disallow(['children']), PropTypes.string, ]), + + /** Shorthand for of the ItemDescription. Mutually exclusive with the children prop. */ + description: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemExtra component. Mutually exclusive with the children prop. */ + extra: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemHeader component. Mutually exclusive with the children prop. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemMeta component. Mutually exclusive with the children prop. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Content can specify its vertical alignment */ + verticalAlign: PropTypes.oneOf(ItemContent._meta.props.verticalAlign), } export default ItemContent diff --git a/src/views/Item/ItemExtra.js b/src/views/Item/ItemExtra.js new file mode 100644 index 0000000000..b9ea5940d4 --- /dev/null +++ b/src/views/Item/ItemExtra.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemExtra(props) { + const { children, className, content } = props + const classes = cx(className, 'extra') + const rest = getUnhandledProps(ItemExtra, props) + const ElementType = getElementType(ItemExtra, props) + + return {children || content} +} + +ItemExtra._meta = { + name: 'ItemExtra', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemExtra.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemExtra. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemExtra diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index 66178e2a05..decf90cc25 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -5,11 +5,18 @@ import { getElementType, getUnhandledProps, META, + useKeyOnly, } from '../../lib' function ItemGroup(props) { - const { className, children } = props - const classes = cx('ui', className, 'items') + const { className, children, divided } = props + const classes = cx( + 'ui', + className, + useKeyOnly(divided, 'divided'), + 'items' + ) + const rest = getUnhandledProps(ItemGroup, props) const ElementType = getElementType(ItemGroup, props) diff --git a/src/views/Item/ItemHeader.js b/src/views/Item/ItemHeader.js new file mode 100644 index 0000000000..6b767c91fd --- /dev/null +++ b/src/views/Item/ItemHeader.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemHeader(props) { + const { children, className, content } = props + const classes = cx(className, 'header') + const rest = getUnhandledProps(ItemHeader, props) + const ElementType = getElementType(ItemHeader, props) + + return {children || content} +} + +ItemHeader._meta = { + name: 'ItemHeader', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemHeader.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemHeader. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemHeader diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index 07bb6f7c2d..addcfa1d9a 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -1,9 +1,15 @@ -import React, { PropTypes } from 'react' -import { META } from '../../lib' +import React from 'react' + +import { + getElementType, + META, +} from '../../lib' import Image from '../../elements/Image/Image' function ItemImage(props) { - return + const ElementType = getElementType(ItemImage, props) + + return } ItemImage._meta = { diff --git a/src/views/Item/ItemMeta.js b/src/views/Item/ItemMeta.js new file mode 100644 index 0000000000..de49449277 --- /dev/null +++ b/src/views/Item/ItemMeta.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemMeta(props) { + const { children, className, content } = props + const classes = cx(className, 'meta') + const rest = getUnhandledProps(ItemMeta, props) + const ElementType = getElementType(ItemMeta, props) + + return {children || content} +} + +ItemMeta._meta = { + name: 'ItemMeta', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemMeta.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemMeta. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemMeta From 7f4d67230d8149c2f5232313df98fd18bb9901fb Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 18:59:18 +0300 Subject: [PATCH 05/18] wip --- docs/app/Examples/views/Item/Types/Items.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js index fdd159eda6..4bb7b09051 100644 --- a/docs/app/Examples/views/Item/Types/Items.js +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -4,7 +4,7 @@ import { Image, Item } from 'stardust' const Metadata = () => ( - + Header @@ -17,7 +17,7 @@ const Metadata = () => ( - + Header From 4414d3efa63e2c85a4a170bc56d411fb3bdefda8 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sun, 28 Aug 2016 15:45:50 +0300 Subject: [PATCH 06/18] wip --- .../views/Item/Content/ExtraContent.js | 8 +-- docs/app/Examples/views/Item/Content/Link.js | 8 +-- .../Examples/views/Item/Content/Metadata.js | 8 +-- docs/app/Examples/views/Item/Types/Items.js | 4 +- docs/app/Examples/views/Item/Types/Props.js | 27 ++++++++ docs/app/Examples/views/Item/Types/index.js | 3 +- .../views/Item/Variations/Alignment.js | 34 ++++++++++ .../Examples/views/Item/Variations/Divided.js | 66 +++++++++++++++++++ .../Examples/views/Item/Variations/Floated.js | 55 ++++++++++++++++ .../Examples/views/Item/Variations/Link.js | 38 +++++++++++ .../Examples/views/Item/Variations/Relaxed.js | 34 ++++++++++ .../views/Item/Variations/VeryRelaxed.js | 34 ++++++++++ .../Examples/views/Item/Variations/index.js | 31 ++++++++- src/views/Item/Item.js | 9 ++- src/views/Item/ItemContent.js | 3 + src/views/Item/ItemDescription.js | 3 + src/views/Item/ItemExtra.js | 3 + src/views/Item/ItemGroup.js | 43 +++++++++++- src/views/Item/ItemHeader.js | 3 + src/views/Item/ItemImage.js | 4 +- src/views/Item/ItemMeta.js | 3 + test/specs/views/Item/Item-test.js | 55 +++++++++++++++- test/specs/views/Item/ItemContent-test.js | 60 +++++++++++++++++ test/specs/views/Item/ItemDescription-test.js | 19 ++++++ test/specs/views/Item/ItemExtra-test.js | 19 ++++++ test/specs/views/Item/ItemGroup-test.js | 29 +++++++- test/specs/views/Item/ItemHeader-test.js | 19 ++++++ test/specs/views/Item/ItemImage-test.js | 9 +++ test/specs/views/Item/ItemMeta-test.js | 19 ++++++ 29 files changed, 624 insertions(+), 26 deletions(-) create mode 100644 docs/app/Examples/views/Item/Types/Props.js create mode 100644 docs/app/Examples/views/Item/Variations/Alignment.js create mode 100644 docs/app/Examples/views/Item/Variations/Divided.js create mode 100644 docs/app/Examples/views/Item/Variations/Floated.js create mode 100644 docs/app/Examples/views/Item/Variations/Link.js create mode 100644 docs/app/Examples/views/Item/Variations/Relaxed.js create mode 100644 docs/app/Examples/views/Item/Variations/VeryRelaxed.js create mode 100644 test/specs/views/Item/ItemContent-test.js create mode 100644 test/specs/views/Item/ItemDescription-test.js create mode 100644 test/specs/views/Item/ItemExtra-test.js create mode 100644 test/specs/views/Item/ItemHeader-test.js create mode 100644 test/specs/views/Item/ItemImage-test.js create mode 100644 test/specs/views/Item/ItemMeta-test.js diff --git a/docs/app/Examples/views/Item/Content/ExtraContent.js b/docs/app/Examples/views/Item/Content/ExtraContent.js index 707188f47a..eee1812af2 100644 --- a/docs/app/Examples/views/Item/Content/ExtraContent.js +++ b/docs/app/Examples/views/Item/Content/ExtraContent.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Icon, Image as ImageComponent } from 'stardust' +import { Icon, Image as ImageComponent, Item } from 'stardust' const { Content, Description, Extra, Group, Header, Image } = Item -const image = +const paragraph = const ExtraContent = () => ( @@ -11,7 +11,7 @@ const ExtraContent = () => (
Cute Dog
- {image} + {paragraph} 121 Votes @@ -23,7 +23,7 @@ const ExtraContent = () => (
Cute Dog
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Content/Link.js b/docs/app/Examples/views/Item/Content/Link.js index 32fa689ccd..824de9c754 100644 --- a/docs/app/Examples/views/Item/Content/Link.js +++ b/docs/app/Examples/views/Item/Content/Link.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Image as ImageComponent } from 'stardust' +import { Image as ImageComponent, Item } from 'stardust' const { Content, Description, Group, Header, Image, Meta } = Item -const image = +const paragraph = const Link = () => ( @@ -15,7 +15,7 @@ const Link = () => ( $1200 1 Month - {image} + {paragraph}
@@ -25,7 +25,7 @@ const Link = () => (
Buck's Homebrew Stayaway
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Content/Metadata.js b/docs/app/Examples/views/Item/Content/Metadata.js index 3140bfe6ab..c3b233a0dc 100644 --- a/docs/app/Examples/views/Item/Content/Metadata.js +++ b/docs/app/Examples/views/Item/Content/Metadata.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Image as ImageComponent } from 'stardust' +import { Image as ImageComponent, Item } from 'stardust' const { Content, Description, Group, Header, Image, Meta } = Item -const image = +const paragraph = const Metadata = () => ( @@ -15,7 +15,7 @@ const Metadata = () => ( $1200 1 Month - {image} + {paragraph} @@ -25,7 +25,7 @@ const Metadata = () => (
Buck's Homebrew Stayaway
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js index 4bb7b09051..be5e8360c7 100644 --- a/docs/app/Examples/views/Item/Types/Items.js +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -1,7 +1,7 @@ import React from 'react' import { Image, Item } from 'stardust' -const Metadata = () => ( +const Items = () => ( @@ -31,4 +31,4 @@ const Metadata = () => ( ) -export default Metadata +export default Items diff --git a/docs/app/Examples/views/Item/Types/Props.js b/docs/app/Examples/views/Item/Types/Props.js new file mode 100644 index 0000000000..375d2d0736 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/Props.js @@ -0,0 +1,27 @@ +import React from 'react' +import { Item } from 'stardust' + +const items = [ + { + childKey: 0, + image: 'http://semantic-ui.com/images/wireframe/image.png', + header: 'Header', + description: 'Description', + meta: 'Metadata', + extra: 'Extra', + }, + { + childKey: 1, + image: 'http://semantic-ui.com/images/wireframe/image.png', + header: 'Header', + description: 'Description', + meta: 'Metadata', + extra: 'Extra', + }, +] + +const Props = () => ( + +) + +export default Props diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js index 8e5fe20e0c..e56d9c409f 100644 --- a/docs/app/Examples/views/Item/Types/index.js +++ b/docs/app/Examples/views/Item/Types/index.js @@ -3,8 +3,6 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' -// TODO: Example with props - const Types = () => ( ( description='A group of items' examplePath='views/Item/Types/Items' /> + ) diff --git a/docs/app/Examples/views/Item/Variations/Alignment.js b/docs/app/Examples/views/Item/Variations/Alignment.js new file mode 100644 index 0000000000..665d35c73c --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Alignment.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Alignment = () => ( + + + + + +
Top Aligned
+
+
+ + + + + +
Middle Aligned
+
+
+ + + + + +
Bottom Aligned
+
+
+
+) + +export default Alignment diff --git a/docs/app/Examples/views/Item/Variations/Divided.js b/docs/app/Examples/views/Item/Variations/Divided.js new file mode 100644 index 0000000000..241e95bc6d --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Divided.js @@ -0,0 +1,66 @@ +import React from 'react' +import { Button, Icon, Image as ImageComponent, Item, Label } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image, Meta } = Item +const paragraph = + +// TODO: Update + + + + + + + + + +
Watchmen
+ + IFC + + {paragraph} + + + +
+
+
+) + +export default Divided diff --git a/docs/app/Examples/views/Item/Variations/Floated.js b/docs/app/Examples/views/Item/Variations/Floated.js new file mode 100644 index 0000000000..cb116195da --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Floated.js @@ -0,0 +1,55 @@ +import React from 'react' +import { Button, Image as ImageComponent, Item } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image } = Item +const paragraph = + +// TODO: Update + + + + + + + + +
Content B
+ {paragraph} + + + +
+
+ + + + + +
Content C
+ {paragraph} + + + +
+
+
+) + +export default Floated diff --git a/docs/app/Examples/views/Item/Variations/Link.js b/docs/app/Examples/views/Item/Variations/Link.js new file mode 100644 index 0000000000..497739a52e --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Link.js @@ -0,0 +1,38 @@ +import React from 'react' +import { Image as ImageComponent, Item } from 'stardust' + +const { Content, Description, Group, Header, Image } = Item +const paragraph = + +const Link = () => ( + + + + + +
Stevie Feliciano
+ {paragraph} +
+
+ + + + + +
Veronika Ossi
+ {paragraph} +
+
+ + + + + +
Jenny Hess
+ {paragraph} +
+
+
+) + +export default Link diff --git a/docs/app/Examples/views/Item/Variations/Relaxed.js b/docs/app/Examples/views/Item/Variations/Relaxed.js new file mode 100644 index 0000000000..045db0960a --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Relaxed.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Relaxed = () => ( + + + + + +
12 Years a Slave
+
+
+ + + + + +
My Neighbor Totoro
+
+
+ + + + + +
Watchmen
+
+
+
+) + +export default Relaxed diff --git a/docs/app/Examples/views/Item/Variations/VeryRelaxed.js b/docs/app/Examples/views/Item/Variations/VeryRelaxed.js new file mode 100644 index 0000000000..6ef3dca9c6 --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/VeryRelaxed.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const VeryRelaxed = () => ( + + + + + +
12 Years a Slave
+
+
+ + + + + +
My Neighbor Totoro
+
+
+ + + + + +
Watchmen
+
+
+
+) + +export default VeryRelaxed diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js index 5dca4bad5f..9ff5098084 100644 --- a/docs/app/Examples/views/Item/Variations/index.js +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -3,11 +3,38 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' -// TODO: All variations examples - const Variations = () => ( + + + + + + + + + ) diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index 5ee24f9349..a7d23709aa 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -20,7 +20,7 @@ import ItemMeta from './ItemMeta' * An item view presents large collections of site content for display * */ function Item(props) { - const { children, className, content, extra, header, image, meta } = props + const { children, className, content, description, extra, header, image, meta } = props const classes = cx(className, 'item') const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) @@ -35,6 +35,7 @@ function Item(props) { {children} + if (!items) { + return {children} + } + + const itemsJSX = _.map(items, item => ( + + )) + + return {itemsJSX} } ItemGroup._meta = { name: 'ItemGroup', type: META.TYPES.VIEW, parent: 'Item', + props: { + relaxed: ['very'], + }, } ItemGroup.propTypes = { @@ -44,6 +64,25 @@ ItemGroup.propTypes = { /** Items can be divided to better distinguish between grouped content. */ divided: PropTypes.bool, + + /** Array of props for Item. */ + items: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.arrayOf(PropTypes.shape({ + childKey: PropTypes.string, + // this object is spread on the Item + // allow it to validate props instead + })), + ]), + + /** An item can be formatted so that the entire contents link to another page. */ + link: PropTypes.bool, + + /** A group of items can relax its padding to provide more negative space. */ + relaxed: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.oneOf(ItemGroup._meta.props.relaxed), + ]), } export default ItemGroup diff --git a/src/views/Item/ItemHeader.js b/src/views/Item/ItemHeader.js index 6b767c91fd..11bf17fafc 100644 --- a/src/views/Item/ItemHeader.js +++ b/src/views/Item/ItemHeader.js @@ -8,6 +8,9 @@ import { META, } from '../../lib' +/** + * An item can contain a header + * */ function ItemHeader(props) { const { children, className, content } = props const classes = cx(className, 'header') diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index addcfa1d9a..bce174e2d5 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -1,11 +1,13 @@ import React from 'react' - import { getElementType, META, } from '../../lib' import Image from '../../elements/Image/Image' +/** + * An item can contain an image + * */ function ItemImage(props) { const ElementType = getElementType(ItemImage, props) diff --git a/src/views/Item/ItemMeta.js b/src/views/Item/ItemMeta.js index de49449277..3efd668beb 100644 --- a/src/views/Item/ItemMeta.js +++ b/src/views/Item/ItemMeta.js @@ -8,6 +8,9 @@ import { META, } from '../../lib' +/** + * An item can contain content metadata. + * */ function ItemMeta(props) { const { children, className, content } = props const classes = cx(className, 'meta') diff --git a/test/specs/views/Item/Item-test.js b/test/specs/views/Item/Item-test.js index af50987108..fe981ea6da 100644 --- a/test/specs/views/Item/Item-test.js +++ b/test/specs/views/Item/Item-test.js @@ -1,9 +1,60 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' import Item from 'src/views/Item/Item' +import ItemContent from 'src/views/Item/ItemContent' +import ItemDescription from 'src/views/Item/ItemDescription' +import ItemExtra from 'src/views/Item/ItemExtra' import ItemGroup from 'src/views/Item/ItemGroup' -import * as common from 'test/specs/commonTests' +import ItemHeader from 'src/views/Item/ItemHeader' +import ItemImage from 'src/views/Item/ItemImage' +import ItemMeta from 'src/views/Item/ItemMeta' describe('Item', () => { common.isConformant(Item) + common.hasSubComponents(Item, [ItemContent, ItemDescription, ItemExtra, ItemGroup, ItemHeader, ItemImage, ItemMeta]) common.rendersChildren(Item) - common.hasSubComponents(Item, [ItemGroup]) + + describe('content prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('description prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('extra prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('header prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('image prop', () => { + it('renders ItemImage component', () => { + shallow() + .should.have.descendants('ItemImage') + }) + }) + + describe('meta prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) }) diff --git a/test/specs/views/Item/ItemContent-test.js b/test/specs/views/Item/ItemContent-test.js new file mode 100644 index 0000000000..7865a7e2bb --- /dev/null +++ b/test/specs/views/Item/ItemContent-test.js @@ -0,0 +1,60 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemContent from 'src/views/Item/ItemContent' +import ItemDescription from 'src/views/Item/ItemDescription' +import ItemExtra from 'src/views/Item/ItemExtra' +import ItemHeader from 'src/views/Item/ItemHeader' +import ItemMeta from 'src/views/Item/ItemMeta' + +describe('ItemContent', () => { + common.isConformant(ItemContent) + common.implementsVerticalAlignProp(ItemContent) + common.rendersChildren(ItemContent) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) + + describe('description prop', () => { + it('renders ItemDescription component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('extra prop', () => { + it('renders ItemExtra component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('header prop', () => { + it('renders ItemHeader component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('meta prop', () => { + it('renders ItemMeta component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) +}) diff --git a/test/specs/views/Item/ItemDescription-test.js b/test/specs/views/Item/ItemDescription-test.js new file mode 100644 index 0000000000..d8966faec4 --- /dev/null +++ b/test/specs/views/Item/ItemDescription-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemDescription from 'src/views/Item/ItemDescription' + +describe('ItemDescription', () => { + common.isConformant(ItemDescription) + common.rendersChildren(ItemDescription) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemExtra-test.js b/test/specs/views/Item/ItemExtra-test.js new file mode 100644 index 0000000000..201a4555f0 --- /dev/null +++ b/test/specs/views/Item/ItemExtra-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemExtra from 'src/views/Item/ItemExtra' + +describe('ItemExtra', () => { + common.isConformant(ItemExtra) + common.rendersChildren(ItemExtra) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemGroup-test.js b/test/specs/views/Item/ItemGroup-test.js index 6ca6713403..f348db18ef 100644 --- a/test/specs/views/Item/ItemGroup-test.js +++ b/test/specs/views/Item/ItemGroup-test.js @@ -1,8 +1,33 @@ -import ItemGroup from 'src/views/Item/ItemGroup' +import faker from 'faker' +import React from 'react' + import * as common from 'test/specs/commonTests' +import ItemGroup from 'src/views/Item/ItemGroup' describe('ItemGroup', () => { - common.isConformant(ItemGroup) common.hasUIClassName(ItemGroup) + common.isConformant(ItemGroup) common.rendersChildren(ItemGroup) + + common.propKeyOnlyToClassName(ItemGroup, 'divided') + common.propKeyOnlyToClassName(ItemGroup, 'link') + common.propKeyOrValueToClassName(ItemGroup, 'relaxed') + + describe('items prop', () => { + it('renders children', () => { + const firstText = faker.hacker.phrase() + const secondText = faker.hacker.phrase() + const items = [ + { content: firstText }, + { content: secondText }, + ] + + const wrapper = mount() + const itemWrappers = wrapper.find('Item') + + wrapper.should.have.exactly(2).descendants('Item') + itemWrappers.first().find('ItemContent').should.contain.text(firstText) + itemWrappers.last().find('ItemContent').should.contain.text(secondText) + }) + }) }) diff --git a/test/specs/views/Item/ItemHeader-test.js b/test/specs/views/Item/ItemHeader-test.js new file mode 100644 index 0000000000..036cf4f438 --- /dev/null +++ b/test/specs/views/Item/ItemHeader-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemHeader from 'src/views/Item/ItemHeader' + +describe('ItemHeader', () => { + common.isConformant(ItemHeader) + common.rendersChildren(ItemHeader) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemImage-test.js b/test/specs/views/Item/ItemImage-test.js new file mode 100644 index 0000000000..ec83b54ff1 --- /dev/null +++ b/test/specs/views/Item/ItemImage-test.js @@ -0,0 +1,9 @@ +import React from 'react' +import ItemImage from 'src/views/Item/ItemImage' + +describe('ItemImage', () => { + it('renders Image component', () => { + shallow() + .should.have.descendants('Image') + }) +}) diff --git a/test/specs/views/Item/ItemMeta-test.js b/test/specs/views/Item/ItemMeta-test.js new file mode 100644 index 0000000000..d4e1a41640 --- /dev/null +++ b/test/specs/views/Item/ItemMeta-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemMeta from 'src/views/Item/ItemMeta' + +describe('ItemMeta', () => { + common.isConformant(ItemMeta) + common.rendersChildren(ItemMeta) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) From 35b4baa5c974fd51d9aa34d9157a4431a03ac857 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Wed, 24 Aug 2016 14:01:24 +0300 Subject: [PATCH 07/18] wip --- src/views/Item/ItemDescription.js | 41 +++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/views/Item/ItemDescription.js diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js new file mode 100644 index 0000000000..61302e0e59 --- /dev/null +++ b/src/views/Item/ItemDescription.js @@ -0,0 +1,41 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getUnhandledProps, + META, +} from '../../lib' + +function ItemDescription(props) { + const { children, className, content } = props + const classes = cx(className, 'description') + const rest = getUnhandledProps(ItemDescription, props) + + return
{children || content}
+} + +ItemDescription._meta = { + name: 'ItemDescription', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemDescription.propTypes = { + /** Primary content of the ItemDescription. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemDescription From a33c3e34ea50b413eaa7a75ee192917391d85295 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 16:44:48 +0300 Subject: [PATCH 08/18] wip --- .../app/Examples/views/Item/Content/Images.js | 22 +++++++ docs/app/Examples/views/Item/Content/index.js | 58 +++++++++++++++++++ docs/app/Examples/views/Item/Types/index.js | 12 ++++ .../Examples/views/Item/Variations/index.js | 12 ++++ docs/app/Examples/views/Item/index.js | 15 +++++ src/views/Item/Item.js | 54 ++++++----------- src/views/Item/ItemContent.js | 49 ++++++++++++++++ src/views/Item/ItemDescription.js | 10 +++- src/views/Item/ItemGroup.js | 25 +++++--- src/views/Item/ItemImage.js | 15 +++++ 10 files changed, 227 insertions(+), 45 deletions(-) create mode 100644 docs/app/Examples/views/Item/Content/Images.js create mode 100644 docs/app/Examples/views/Item/Content/index.js create mode 100644 docs/app/Examples/views/Item/Types/index.js create mode 100644 docs/app/Examples/views/Item/Variations/index.js create mode 100644 docs/app/Examples/views/Item/index.js create mode 100644 src/views/Item/ItemContent.js create mode 100644 src/views/Item/ItemImage.js diff --git a/docs/app/Examples/views/Item/Content/Images.js b/docs/app/Examples/views/Item/Content/Images.js new file mode 100644 index 0000000000..294d39a131 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Images.js @@ -0,0 +1,22 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Group, Image } = Item + +const Images = () => ( + + + + + + + + + + + + + +) + +export default Images diff --git a/docs/app/Examples/views/Item/Content/index.js b/docs/app/Examples/views/Item/Content/index.js new file mode 100644 index 0000000000..10670c13c0 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/index.js @@ -0,0 +1,58 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Content = () => ( + + + + + + + + + + + + + + + + + +) + +export default Content diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js new file mode 100644 index 0000000000..df1b7d52c1 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/index.js @@ -0,0 +1,12 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Types = () => ( + + + +) + +export default Types diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js new file mode 100644 index 0000000000..f7affd6648 --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -0,0 +1,12 @@ +import React from 'react' + +import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' + +const Variations = () => ( + + + +) + +export default Variations diff --git a/docs/app/Examples/views/Item/index.js b/docs/app/Examples/views/Item/index.js new file mode 100644 index 0000000000..e64f99cd82 --- /dev/null +++ b/docs/app/Examples/views/Item/index.js @@ -0,0 +1,15 @@ +import React from 'react' + +import Content from './Content' +import Types from './Types' +import Variations from './Variations' + +const ItemExamples = () => ( +
+ + + +
+) + +export default ItemExamples diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index 60c4455852..c32918f9db 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -1,5 +1,4 @@ import cx from 'classnames' -import _ from 'lodash' import React, { PropTypes } from 'react' import { @@ -8,35 +7,21 @@ import { getUnhandledProps, META, } from '../../lib' + +import ItemDescription from './ItemDescription' import ItemGroup from './ItemGroup' +import ItemImage from './ItemImage' function Item(props) { - const { children, className, contentClassName, description, extra, header, image, meta } = props - const rest = getUnhandledProps(Item, props) - - const { className: imageClassName, ...imageProps } = _.get(image, 'props', {}) - + const { children, className, image } = props const classes = cx(className, 'item') - const imageClasses = cx('ui', imageClassName, 'image') - const contentClasses = cx(contentClassName, 'content') - - const _description = children || description - - const content = header || meta || extra ? [ - header &&
{header}
, - meta &&
{meta}
, - _description &&
{_description}
, - extra &&
{extra}
, - ] : [ - _description, - ] - + const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) return ( - {image &&
} - {content &&
{content}
} + {image && } + {children}
) } @@ -46,6 +31,10 @@ Item._meta = { type: META.TYPES.VIEW, } +Item.Description = ItemDescription +Item.Group = ItemGroup +Item.Image = ItemImage + Item.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.oneOfType([ @@ -53,26 +42,17 @@ Item.propTypes = { PropTypes.func, ]), + /** Primary content of the Item. */ children: customPropTypes.every([ - customPropTypes.disallow(['description']), + customPropTypes.disallow(['content']), PropTypes.node, ]), + + /** Classes that will be added to the Item className. */ className: PropTypes.string, - contentClassName: PropTypes.string, - description: customPropTypes.every([ - customPropTypes.disallow(['children']), - PropTypes.node, - ]), - extra: PropTypes.node, - header: PropTypes.node, - image: PropTypes.node, - meta: PropTypes.node, -} -Item.defaultProps = { - contentClassName: 'middle aligned', + /** Shorthand for ItemImage component. */ + image: PropTypes.string, } -Item.Group = ItemGroup - export default Item diff --git a/src/views/Item/ItemContent.js b/src/views/Item/ItemContent.js new file mode 100644 index 0000000000..8e959d29be --- /dev/null +++ b/src/views/Item/ItemContent.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, +getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemContent(props) { + const { children, className, content } = props + const classes = cx(className, 'content') + const rest = getUnhandledProps(ItemContent, props) + const ElementType = getElementType(ItemContent, props) + + return {children || content} +} + +ItemContent._meta = { + name: 'ItemContent', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemContent.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemContent. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + 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, + ]), +} + +export default ItemContent diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js index 61302e0e59..760b71627c 100644 --- a/src/views/Item/ItemDescription.js +++ b/src/views/Item/ItemDescription.js @@ -3,6 +3,7 @@ import React, { PropTypes } from 'react' import { customPropTypes, +getElementType, getUnhandledProps, META, } from '../../lib' @@ -11,8 +12,9 @@ function ItemDescription(props) { const { children, className, content } = props const classes = cx(className, 'description') const rest = getUnhandledProps(ItemDescription, props) + const ElementType = getElementType(ItemDescription, props) - return
{children || content}
+ return {children || content} } ItemDescription._meta = { @@ -22,6 +24,12 @@ ItemDescription._meta = { } ItemDescription.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + /** Primary content of the ItemDescription. */ children: customPropTypes.every([ customPropTypes.disallow(['content']), diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index c193fe304b..66178e2a05 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -1,6 +1,11 @@ -import React, { PropTypes } from 'react' import cx from 'classnames' -import { getElementType, getUnhandledProps, META } from '../../lib' +import React, { PropTypes } from 'react' + +import { + getElementType, + getUnhandledProps, + META, +} from '../../lib' function ItemGroup(props) { const { className, children } = props @@ -11,6 +16,12 @@ function ItemGroup(props) { return {children} } +ItemGroup._meta = { + name: 'ItemGroup', + type: META.TYPES.VIEW, + parent: 'Item', +} + ItemGroup.propTypes = { /** An element type to render as (string or function). */ as: PropTypes.oneOfType([ @@ -18,14 +29,14 @@ ItemGroup.propTypes = { PropTypes.func, ]), + /** Primary content of the ItemGroup. */ children: PropTypes.node, + + /** Classes that will be added to the ItemGroup className. */ className: PropTypes.string, -} -ItemGroup._meta = { - name: 'ItemGroup', - type: META.TYPES.VIEW, - parent: 'Item', + /** Items can be divided to better distinguish between grouped content. */ + divided: PropTypes.bool, } export default ItemGroup diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js new file mode 100644 index 0000000000..07bb6f7c2d --- /dev/null +++ b/src/views/Item/ItemImage.js @@ -0,0 +1,15 @@ +import React, { PropTypes } from 'react' +import { META } from '../../lib' +import Image from '../../elements/Image/Image' + +function ItemImage(props) { + return +} + +ItemImage._meta = { + name: 'ItemImage', + parent: 'Item', + type: META.TYPES.VIEW, +} + +export default ItemImage From ec44f1b0ac7a066b89f63af3c035e531c4893f32 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 16:44:48 +0300 Subject: [PATCH 09/18] wip --- src/views/Item/ItemDescription.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Item/ItemDescription.js b/src/views/Item/ItemDescription.js index 760b71627c..b498de4199 100644 --- a/src/views/Item/ItemDescription.js +++ b/src/views/Item/ItemDescription.js @@ -3,7 +3,7 @@ import React, { PropTypes } from 'react' import { customPropTypes, -getElementType, + getElementType, getUnhandledProps, META, } from '../../lib' From 5260d3eacfedd537e937511e415e693aa475f1d1 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 18:57:23 +0300 Subject: [PATCH 10/18] wip --- .../Examples/views/Item/Content/Contents.js | 25 ++++++++ .../views/Item/Content/Descriptions.js | 42 +++++++++++++ .../views/Item/Content/ExtraContent.js | 38 ++++++++++++ .../Examples/views/Item/Content/Headers.js | 29 +++++++++ .../app/Examples/views/Item/Content/Images.js | 4 +- docs/app/Examples/views/Item/Content/Link.js | 39 ++++++++++++ .../Examples/views/Item/Content/Metadata.js | 39 ++++++++++++ .../Examples/views/Item/Content/Ratings.js | 32 ++++++++++ docs/app/Examples/views/Item/Content/index.js | 16 ++--- docs/app/Examples/views/Item/Types/Items.js | 34 +++++++++++ docs/app/Examples/views/Item/Types/index.js | 8 ++- .../Examples/views/Item/Variations/index.js | 2 + src/views/Item/Item.js | 59 ++++++++++++++++--- src/views/Item/ItemContent.js | 57 ++++++++++++++++-- src/views/Item/ItemExtra.js | 49 +++++++++++++++ src/views/Item/ItemGroup.js | 11 +++- src/views/Item/ItemHeader.js | 49 +++++++++++++++ src/views/Item/ItemImage.js | 12 +++- src/views/Item/ItemMeta.js | 49 +++++++++++++++ 19 files changed, 566 insertions(+), 28 deletions(-) create mode 100644 docs/app/Examples/views/Item/Content/Contents.js create mode 100644 docs/app/Examples/views/Item/Content/Descriptions.js create mode 100644 docs/app/Examples/views/Item/Content/ExtraContent.js create mode 100644 docs/app/Examples/views/Item/Content/Headers.js create mode 100644 docs/app/Examples/views/Item/Content/Link.js create mode 100644 docs/app/Examples/views/Item/Content/Metadata.js create mode 100644 docs/app/Examples/views/Item/Content/Ratings.js create mode 100644 docs/app/Examples/views/Item/Types/Items.js create mode 100644 src/views/Item/ItemExtra.js create mode 100644 src/views/Item/ItemHeader.js create mode 100644 src/views/Item/ItemMeta.js diff --git a/docs/app/Examples/views/Item/Content/Contents.js b/docs/app/Examples/views/Item/Content/Contents.js new file mode 100644 index 0000000000..da1f1dcce2 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Contents.js @@ -0,0 +1,25 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Image } = Item + +const Contents = () => ( + + + + Content A + + + + + Content B + + + + + + + +) + +export default Contents diff --git a/docs/app/Examples/views/Item/Content/Descriptions.js b/docs/app/Examples/views/Item/Content/Descriptions.js new file mode 100644 index 0000000000..40aa8e7242 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Descriptions.js @@ -0,0 +1,42 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Description, Group, Header, Image } = Item +const description = [ + 'Cute dogs come in a variety of shapes and sizes. Some cute dogs are cute for their adorable faces, others for their', + 'tiny stature, and even others for their massive size.', +].join(' ') + +const Descriptions = () => ( + + + + + +
Cute Dog
+ +

{description}

+

+ Many people also have their own barometers for what makes a cute dog. +

+
+
+
+ + + + + +
Cute Dog
+ +
+
+ + + + + +
+) + +export default Descriptions diff --git a/docs/app/Examples/views/Item/Content/ExtraContent.js b/docs/app/Examples/views/Item/Content/ExtraContent.js new file mode 100644 index 0000000000..707188f47a --- /dev/null +++ b/docs/app/Examples/views/Item/Content/ExtraContent.js @@ -0,0 +1,38 @@ +import React from 'react' +import { Item, Icon, Image as ImageComponent } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image } = Item +const image = + +const ExtraContent = () => ( + + + + + +
Cute Dog
+ {image} + + 121 Votes + +
+
+ + + + + +
Cute Dog
+ {image} + +
+
+ + + + + +
+) + +export default ExtraContent diff --git a/docs/app/Examples/views/Item/Content/Headers.js b/docs/app/Examples/views/Item/Content/Headers.js new file mode 100644 index 0000000000..879fb88154 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Headers.js @@ -0,0 +1,29 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Headers = () => ( + + + + +
12 Years a Slave
+
+
+ + + + +
+ + + + + + + + +) + +export default Headers diff --git a/docs/app/Examples/views/Item/Content/Images.js b/docs/app/Examples/views/Item/Content/Images.js index 294d39a131..3f89a8470c 100644 --- a/docs/app/Examples/views/Item/Content/Images.js +++ b/docs/app/Examples/views/Item/Content/Images.js @@ -6,9 +6,7 @@ const { Group, Image } = Item const Images = () => ( - - - + diff --git a/docs/app/Examples/views/Item/Content/Link.js b/docs/app/Examples/views/Item/Content/Link.js new file mode 100644 index 0000000000..32fa689ccd --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Link.js @@ -0,0 +1,39 @@ +import React from 'react' +import { Item, Image as ImageComponent } from 'stardust' + +const { Content, Description, Group, Header, Image, Meta } = Item +const image = + +const Link = () => ( + + + + + +
Arrowhead Valley Camp
+ + $1200 + 1 Month + + {image} +
+
+ + + + + +
Buck's Homebrew Stayaway
+ + {image} +
+
+ + + + + +
+) + +export default Link diff --git a/docs/app/Examples/views/Item/Content/Metadata.js b/docs/app/Examples/views/Item/Content/Metadata.js new file mode 100644 index 0000000000..3140bfe6ab --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Metadata.js @@ -0,0 +1,39 @@ +import React from 'react' +import { Item, Image as ImageComponent } from 'stardust' + +const { Content, Description, Group, Header, Image, Meta } = Item +const image = + +const Metadata = () => ( + + + + + +
Arrowhead Valley Camp
+ + $1200 + 1 Month + + {image} +
+
+ + + + + +
Buck's Homebrew Stayaway
+ + {image} +
+
+ + + + + +
+) + +export default Metadata diff --git a/docs/app/Examples/views/Item/Content/Ratings.js b/docs/app/Examples/views/Item/Content/Ratings.js new file mode 100644 index 0000000000..b7edeed215 --- /dev/null +++ b/docs/app/Examples/views/Item/Content/Ratings.js @@ -0,0 +1,32 @@ +import React from 'react' +import { Icon, Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Ratings = () => ( + + + + + +
+ + Veronika Ossi +
+
+
+ + + + + +
+ + Justen Kitsune +
+
+
+
+) + +export default Ratings diff --git a/docs/app/Examples/views/Item/Content/index.js b/docs/app/Examples/views/Item/Content/index.js index 10670c13c0..8c5e3bcc8e 100644 --- a/docs/app/Examples/views/Item/Content/index.js +++ b/docs/app/Examples/views/Item/Content/index.js @@ -14,13 +14,13 @@ const Content = () => ( ( ( examplePath='views/Item/Content/ExtraContent' /> - + ) diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js new file mode 100644 index 0000000000..fdd159eda6 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Image, Item } from 'stardust' + +const Metadata = () => ( + + + + + + Header + Description + + + + Additional Details + + + + + + + + Header + Description + + + + Additional Details + + + +) + +export default Metadata diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js index df1b7d52c1..8e5fe20e0c 100644 --- a/docs/app/Examples/views/Item/Types/index.js +++ b/docs/app/Examples/views/Item/Types/index.js @@ -3,9 +3,15 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' +// TODO: Example with props + const Types = () => ( - + ) diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js index f7affd6648..5dca4bad5f 100644 --- a/docs/app/Examples/views/Item/Variations/index.js +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -3,6 +3,8 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' +// TODO: All variations examples + const Variations = () => ( diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index c32918f9db..5ee24f9349 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -8,20 +8,37 @@ import { META, } from '../../lib' +import ItemContent from './ItemContent' import ItemDescription from './ItemDescription' +import ItemExtra from './ItemExtra' import ItemGroup from './ItemGroup' +import ItemHeader from './ItemHeader' import ItemImage from './ItemImage' +import ItemMeta from './ItemMeta' +/** + * An item view presents large collections of site content for display + * */ function Item(props) { - const { children, className, image } = props + const { children, className, content, extra, header, image, meta } = props const classes = cx(className, 'item') const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) + if (children) { + return {children} + } + return ( {image && } - {children} + + ) } @@ -31,9 +48,13 @@ Item._meta = { type: META.TYPES.VIEW, } +Item.Content = ItemContent Item.Description = ItemDescription +Item.Extra = ItemExtra Item.Group = ItemGroup +Item.Header = ItemHeader Item.Image = ItemImage +Item.Meta = ItemMeta Item.propTypes = { /** An element type to render as (string or function). */ @@ -43,16 +64,40 @@ Item.propTypes = { ]), /** Primary content of the Item. */ - children: customPropTypes.every([ - customPropTypes.disallow(['content']), - PropTypes.node, - ]), + children: 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 ItemExtra component. */ + extra: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + /** Shorthand for ItemImage component. */ - image: PropTypes.string, + image: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemHeader component. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemMeta component. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), } export default Item diff --git a/src/views/Item/ItemContent.js b/src/views/Item/ItemContent.js index 8e959d29be..f1df748a58 100644 --- a/src/views/Item/ItemContent.js +++ b/src/views/Item/ItemContent.js @@ -3,24 +3,46 @@ import React, { PropTypes } from 'react' import { customPropTypes, -getElementType, + getElementType, getUnhandledProps, META, + SUI, + useVerticalAlignProp, } from '../../lib' +import ItemHeader from './ItemHeader' +import ItemDescription from './ItemDescription' +import ItemExtra from './ItemExtra' +import ItemMeta from './ItemMeta' function ItemContent(props) { - const { children, className, content } = props - const classes = cx(className, 'content') + const { children, className, content, description, extra, header, meta, verticalAlign } = props + const classes = cx( + className, + useVerticalAlignProp(verticalAlign), + 'content', + ) + const rest = getUnhandledProps(ItemContent, props) const ElementType = getElementType(ItemContent, props) - return {children || content} + return ( + + {header && } + {meta && } + {description && } + {extra && } + {children || content} + + ) } ItemContent._meta = { name: 'ItemContent', parent: 'Item', type: META.TYPES.VIEW, + props: { + verticalAlign: SUI.VERTICAL_ALIGNMENTS, + }, } ItemContent.propTypes = { @@ -44,6 +66,33 @@ ItemContent.propTypes = { customPropTypes.disallow(['children']), PropTypes.string, ]), + + /** Shorthand for of the ItemDescription. Mutually exclusive with the children prop. */ + description: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemExtra component. Mutually exclusive with the children prop. */ + extra: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemHeader component. Mutually exclusive with the children prop. */ + header: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Shorthand for ItemMeta component. Mutually exclusive with the children prop. */ + meta: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.string, + ]), + + /** Content can specify its vertical alignment */ + verticalAlign: PropTypes.oneOf(ItemContent._meta.props.verticalAlign), } export default ItemContent diff --git a/src/views/Item/ItemExtra.js b/src/views/Item/ItemExtra.js new file mode 100644 index 0000000000..b9ea5940d4 --- /dev/null +++ b/src/views/Item/ItemExtra.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemExtra(props) { + const { children, className, content } = props + const classes = cx(className, 'extra') + const rest = getUnhandledProps(ItemExtra, props) + const ElementType = getElementType(ItemExtra, props) + + return {children || content} +} + +ItemExtra._meta = { + name: 'ItemExtra', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemExtra.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemExtra. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemExtra diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index 66178e2a05..decf90cc25 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -5,11 +5,18 @@ import { getElementType, getUnhandledProps, META, + useKeyOnly, } from '../../lib' function ItemGroup(props) { - const { className, children } = props - const classes = cx('ui', className, 'items') + const { className, children, divided } = props + const classes = cx( + 'ui', + className, + useKeyOnly(divided, 'divided'), + 'items' + ) + const rest = getUnhandledProps(ItemGroup, props) const ElementType = getElementType(ItemGroup, props) diff --git a/src/views/Item/ItemHeader.js b/src/views/Item/ItemHeader.js new file mode 100644 index 0000000000..6b767c91fd --- /dev/null +++ b/src/views/Item/ItemHeader.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemHeader(props) { + const { children, className, content } = props + const classes = cx(className, 'header') + const rest = getUnhandledProps(ItemHeader, props) + const ElementType = getElementType(ItemHeader, props) + + return {children || content} +} + +ItemHeader._meta = { + name: 'ItemHeader', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemHeader.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemHeader. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemHeader diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index 07bb6f7c2d..addcfa1d9a 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -1,9 +1,15 @@ -import React, { PropTypes } from 'react' -import { META } from '../../lib' +import React from 'react' + +import { + getElementType, + META, +} from '../../lib' import Image from '../../elements/Image/Image' function ItemImage(props) { - return + const ElementType = getElementType(ItemImage, props) + + return } ItemImage._meta = { diff --git a/src/views/Item/ItemMeta.js b/src/views/Item/ItemMeta.js new file mode 100644 index 0000000000..de49449277 --- /dev/null +++ b/src/views/Item/ItemMeta.js @@ -0,0 +1,49 @@ +import cx from 'classnames' +import React, { PropTypes } from 'react' + +import { + customPropTypes, + getElementType, + getUnhandledProps, + META, +} from '../../lib' + +function ItemMeta(props) { + const { children, className, content } = props + const classes = cx(className, 'meta') + const rest = getUnhandledProps(ItemMeta, props) + const ElementType = getElementType(ItemMeta, props) + + return {children || content} +} + +ItemMeta._meta = { + name: 'ItemMeta', + parent: 'Item', + type: META.TYPES.VIEW, +} + +ItemMeta.propTypes = { + /** An element type to render as (string or function). */ + as: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.func, + ]), + + /** Primary content of the ItemMeta. */ + children: customPropTypes.every([ + customPropTypes.disallow(['content']), + PropTypes.node, + ]), + + /** 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, + ]), +} + +export default ItemMeta From 9610c2882f4a9775ccaf5e89174d08e02fa530d1 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sat, 27 Aug 2016 18:59:18 +0300 Subject: [PATCH 11/18] wip --- docs/app/Examples/views/Item/Types/Items.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js index fdd159eda6..4bb7b09051 100644 --- a/docs/app/Examples/views/Item/Types/Items.js +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -4,7 +4,7 @@ import { Image, Item } from 'stardust' const Metadata = () => ( - + Header @@ -17,7 +17,7 @@ const Metadata = () => ( - + Header From 7ca63590b3b54719e97ccec6adc83e15b1b905f9 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Sun, 28 Aug 2016 15:45:50 +0300 Subject: [PATCH 12/18] wip --- .../views/Item/Content/ExtraContent.js | 8 +-- docs/app/Examples/views/Item/Content/Link.js | 8 +-- .../Examples/views/Item/Content/Metadata.js | 8 +-- docs/app/Examples/views/Item/Types/Items.js | 4 +- docs/app/Examples/views/Item/Types/Props.js | 27 ++++++++ docs/app/Examples/views/Item/Types/index.js | 3 +- .../views/Item/Variations/Alignment.js | 34 ++++++++++ .../Examples/views/Item/Variations/Divided.js | 66 +++++++++++++++++++ .../Examples/views/Item/Variations/Floated.js | 55 ++++++++++++++++ .../Examples/views/Item/Variations/Link.js | 38 +++++++++++ .../Examples/views/Item/Variations/Relaxed.js | 34 ++++++++++ .../views/Item/Variations/VeryRelaxed.js | 34 ++++++++++ .../Examples/views/Item/Variations/index.js | 31 ++++++++- src/views/Item/Item.js | 9 ++- src/views/Item/ItemContent.js | 3 + src/views/Item/ItemDescription.js | 3 + src/views/Item/ItemExtra.js | 3 + src/views/Item/ItemGroup.js | 43 +++++++++++- src/views/Item/ItemHeader.js | 3 + src/views/Item/ItemImage.js | 4 +- src/views/Item/ItemMeta.js | 3 + test/specs/views/Item/Item-test.js | 55 +++++++++++++++- test/specs/views/Item/ItemContent-test.js | 60 +++++++++++++++++ test/specs/views/Item/ItemDescription-test.js | 19 ++++++ test/specs/views/Item/ItemExtra-test.js | 19 ++++++ test/specs/views/Item/ItemGroup-test.js | 29 +++++++- test/specs/views/Item/ItemHeader-test.js | 19 ++++++ test/specs/views/Item/ItemImage-test.js | 9 +++ test/specs/views/Item/ItemMeta-test.js | 19 ++++++ 29 files changed, 624 insertions(+), 26 deletions(-) create mode 100644 docs/app/Examples/views/Item/Types/Props.js create mode 100644 docs/app/Examples/views/Item/Variations/Alignment.js create mode 100644 docs/app/Examples/views/Item/Variations/Divided.js create mode 100644 docs/app/Examples/views/Item/Variations/Floated.js create mode 100644 docs/app/Examples/views/Item/Variations/Link.js create mode 100644 docs/app/Examples/views/Item/Variations/Relaxed.js create mode 100644 docs/app/Examples/views/Item/Variations/VeryRelaxed.js create mode 100644 test/specs/views/Item/ItemContent-test.js create mode 100644 test/specs/views/Item/ItemDescription-test.js create mode 100644 test/specs/views/Item/ItemExtra-test.js create mode 100644 test/specs/views/Item/ItemHeader-test.js create mode 100644 test/specs/views/Item/ItemImage-test.js create mode 100644 test/specs/views/Item/ItemMeta-test.js diff --git a/docs/app/Examples/views/Item/Content/ExtraContent.js b/docs/app/Examples/views/Item/Content/ExtraContent.js index 707188f47a..eee1812af2 100644 --- a/docs/app/Examples/views/Item/Content/ExtraContent.js +++ b/docs/app/Examples/views/Item/Content/ExtraContent.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Icon, Image as ImageComponent } from 'stardust' +import { Icon, Image as ImageComponent, Item } from 'stardust' const { Content, Description, Extra, Group, Header, Image } = Item -const image = +const paragraph = const ExtraContent = () => ( @@ -11,7 +11,7 @@ const ExtraContent = () => (
Cute Dog
- {image} + {paragraph} 121 Votes @@ -23,7 +23,7 @@ const ExtraContent = () => (
Cute Dog
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Content/Link.js b/docs/app/Examples/views/Item/Content/Link.js index 32fa689ccd..824de9c754 100644 --- a/docs/app/Examples/views/Item/Content/Link.js +++ b/docs/app/Examples/views/Item/Content/Link.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Image as ImageComponent } from 'stardust' +import { Image as ImageComponent, Item } from 'stardust' const { Content, Description, Group, Header, Image, Meta } = Item -const image = +const paragraph = const Link = () => ( @@ -15,7 +15,7 @@ const Link = () => ( $1200 1 Month - {image} + {paragraph}
@@ -25,7 +25,7 @@ const Link = () => (
Buck's Homebrew Stayaway
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Content/Metadata.js b/docs/app/Examples/views/Item/Content/Metadata.js index 3140bfe6ab..c3b233a0dc 100644 --- a/docs/app/Examples/views/Item/Content/Metadata.js +++ b/docs/app/Examples/views/Item/Content/Metadata.js @@ -1,8 +1,8 @@ import React from 'react' -import { Item, Image as ImageComponent } from 'stardust' +import { Image as ImageComponent, Item } from 'stardust' const { Content, Description, Group, Header, Image, Meta } = Item -const image = +const paragraph = const Metadata = () => ( @@ -15,7 +15,7 @@ const Metadata = () => ( $1200 1 Month - {image} + {paragraph} @@ -25,7 +25,7 @@ const Metadata = () => (
Buck's Homebrew Stayaway
- {image} + {paragraph}
diff --git a/docs/app/Examples/views/Item/Types/Items.js b/docs/app/Examples/views/Item/Types/Items.js index 4bb7b09051..be5e8360c7 100644 --- a/docs/app/Examples/views/Item/Types/Items.js +++ b/docs/app/Examples/views/Item/Types/Items.js @@ -1,7 +1,7 @@ import React from 'react' import { Image, Item } from 'stardust' -const Metadata = () => ( +const Items = () => ( @@ -31,4 +31,4 @@ const Metadata = () => ( ) -export default Metadata +export default Items diff --git a/docs/app/Examples/views/Item/Types/Props.js b/docs/app/Examples/views/Item/Types/Props.js new file mode 100644 index 0000000000..375d2d0736 --- /dev/null +++ b/docs/app/Examples/views/Item/Types/Props.js @@ -0,0 +1,27 @@ +import React from 'react' +import { Item } from 'stardust' + +const items = [ + { + childKey: 0, + image: 'http://semantic-ui.com/images/wireframe/image.png', + header: 'Header', + description: 'Description', + meta: 'Metadata', + extra: 'Extra', + }, + { + childKey: 1, + image: 'http://semantic-ui.com/images/wireframe/image.png', + header: 'Header', + description: 'Description', + meta: 'Metadata', + extra: 'Extra', + }, +] + +const Props = () => ( + +) + +export default Props diff --git a/docs/app/Examples/views/Item/Types/index.js b/docs/app/Examples/views/Item/Types/index.js index 8e5fe20e0c..e56d9c409f 100644 --- a/docs/app/Examples/views/Item/Types/index.js +++ b/docs/app/Examples/views/Item/Types/index.js @@ -3,8 +3,6 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' -// TODO: Example with props - const Types = () => ( ( description='A group of items' examplePath='views/Item/Types/Items' /> + ) diff --git a/docs/app/Examples/views/Item/Variations/Alignment.js b/docs/app/Examples/views/Item/Variations/Alignment.js new file mode 100644 index 0000000000..665d35c73c --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Alignment.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Alignment = () => ( + + + + + +
Top Aligned
+
+
+ + + + + +
Middle Aligned
+
+
+ + + + + +
Bottom Aligned
+
+
+
+) + +export default Alignment diff --git a/docs/app/Examples/views/Item/Variations/Divided.js b/docs/app/Examples/views/Item/Variations/Divided.js new file mode 100644 index 0000000000..241e95bc6d --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Divided.js @@ -0,0 +1,66 @@ +import React from 'react' +import { Button, Icon, Image as ImageComponent, Item, Label } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image, Meta } = Item +const paragraph = + +// TODO: Update + + + + + + + + + +
Watchmen
+ + IFC + + {paragraph} + + + +
+
+
+) + +export default Divided diff --git a/docs/app/Examples/views/Item/Variations/Floated.js b/docs/app/Examples/views/Item/Variations/Floated.js new file mode 100644 index 0000000000..cb116195da --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Floated.js @@ -0,0 +1,55 @@ +import React from 'react' +import { Button, Image as ImageComponent, Item } from 'stardust' + +const { Content, Description, Extra, Group, Header, Image } = Item +const paragraph = + +// TODO: Update + + + + + + + + +
Content B
+ {paragraph} + + + +
+
+ + + + + +
Content C
+ {paragraph} + + + +
+
+
+) + +export default Floated diff --git a/docs/app/Examples/views/Item/Variations/Link.js b/docs/app/Examples/views/Item/Variations/Link.js new file mode 100644 index 0000000000..497739a52e --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Link.js @@ -0,0 +1,38 @@ +import React from 'react' +import { Image as ImageComponent, Item } from 'stardust' + +const { Content, Description, Group, Header, Image } = Item +const paragraph = + +const Link = () => ( + + + + + +
Stevie Feliciano
+ {paragraph} +
+
+ + + + + +
Veronika Ossi
+ {paragraph} +
+
+ + + + + +
Jenny Hess
+ {paragraph} +
+
+
+) + +export default Link diff --git a/docs/app/Examples/views/Item/Variations/Relaxed.js b/docs/app/Examples/views/Item/Variations/Relaxed.js new file mode 100644 index 0000000000..045db0960a --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/Relaxed.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const Relaxed = () => ( + + + + + +
12 Years a Slave
+
+
+ + + + + +
My Neighbor Totoro
+
+
+ + + + + +
Watchmen
+
+
+
+) + +export default Relaxed diff --git a/docs/app/Examples/views/Item/Variations/VeryRelaxed.js b/docs/app/Examples/views/Item/Variations/VeryRelaxed.js new file mode 100644 index 0000000000..6ef3dca9c6 --- /dev/null +++ b/docs/app/Examples/views/Item/Variations/VeryRelaxed.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Item } from 'stardust' + +const { Content, Group, Header, Image } = Item + +const VeryRelaxed = () => ( + + + + + +
12 Years a Slave
+
+
+ + + + + +
My Neighbor Totoro
+
+
+ + + + + +
Watchmen
+
+
+
+) + +export default VeryRelaxed diff --git a/docs/app/Examples/views/Item/Variations/index.js b/docs/app/Examples/views/Item/Variations/index.js index 5dca4bad5f..9ff5098084 100644 --- a/docs/app/Examples/views/Item/Variations/index.js +++ b/docs/app/Examples/views/Item/Variations/index.js @@ -3,11 +3,38 @@ import React from 'react' import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample' import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection' -// TODO: All variations examples - const Variations = () => ( + + + + + + + + + ) diff --git a/src/views/Item/Item.js b/src/views/Item/Item.js index 5ee24f9349..a7d23709aa 100644 --- a/src/views/Item/Item.js +++ b/src/views/Item/Item.js @@ -20,7 +20,7 @@ import ItemMeta from './ItemMeta' * An item view presents large collections of site content for display * */ function Item(props) { - const { children, className, content, extra, header, image, meta } = props + const { children, className, content, description, extra, header, image, meta } = props const classes = cx(className, 'item') const rest = getUnhandledProps(Item, props) const ElementType = getElementType(Item, props) @@ -35,6 +35,7 @@ function Item(props) { {children} + if (!items) { + return {children} + } + + const itemsJSX = _.map(items, item => ( + + )) + + return {itemsJSX} } ItemGroup._meta = { name: 'ItemGroup', type: META.TYPES.VIEW, parent: 'Item', + props: { + relaxed: ['very'], + }, } ItemGroup.propTypes = { @@ -44,6 +64,25 @@ ItemGroup.propTypes = { /** Items can be divided to better distinguish between grouped content. */ divided: PropTypes.bool, + + /** Array of props for Item. */ + items: customPropTypes.every([ + customPropTypes.disallow(['children']), + PropTypes.arrayOf(PropTypes.shape({ + childKey: PropTypes.string, + // this object is spread on the Item + // allow it to validate props instead + })), + ]), + + /** An item can be formatted so that the entire contents link to another page. */ + link: PropTypes.bool, + + /** A group of items can relax its padding to provide more negative space. */ + relaxed: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.oneOf(ItemGroup._meta.props.relaxed), + ]), } export default ItemGroup diff --git a/src/views/Item/ItemHeader.js b/src/views/Item/ItemHeader.js index 6b767c91fd..11bf17fafc 100644 --- a/src/views/Item/ItemHeader.js +++ b/src/views/Item/ItemHeader.js @@ -8,6 +8,9 @@ import { META, } from '../../lib' +/** + * An item can contain a header + * */ function ItemHeader(props) { const { children, className, content } = props const classes = cx(className, 'header') diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index addcfa1d9a..bce174e2d5 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -1,11 +1,13 @@ import React from 'react' - import { getElementType, META, } from '../../lib' import Image from '../../elements/Image/Image' +/** + * An item can contain an image + * */ function ItemImage(props) { const ElementType = getElementType(ItemImage, props) diff --git a/src/views/Item/ItemMeta.js b/src/views/Item/ItemMeta.js index de49449277..3efd668beb 100644 --- a/src/views/Item/ItemMeta.js +++ b/src/views/Item/ItemMeta.js @@ -8,6 +8,9 @@ import { META, } from '../../lib' +/** + * An item can contain content metadata. + * */ function ItemMeta(props) { const { children, className, content } = props const classes = cx(className, 'meta') diff --git a/test/specs/views/Item/Item-test.js b/test/specs/views/Item/Item-test.js index af50987108..fe981ea6da 100644 --- a/test/specs/views/Item/Item-test.js +++ b/test/specs/views/Item/Item-test.js @@ -1,9 +1,60 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' import Item from 'src/views/Item/Item' +import ItemContent from 'src/views/Item/ItemContent' +import ItemDescription from 'src/views/Item/ItemDescription' +import ItemExtra from 'src/views/Item/ItemExtra' import ItemGroup from 'src/views/Item/ItemGroup' -import * as common from 'test/specs/commonTests' +import ItemHeader from 'src/views/Item/ItemHeader' +import ItemImage from 'src/views/Item/ItemImage' +import ItemMeta from 'src/views/Item/ItemMeta' describe('Item', () => { common.isConformant(Item) + common.hasSubComponents(Item, [ItemContent, ItemDescription, ItemExtra, ItemGroup, ItemHeader, ItemImage, ItemMeta]) common.rendersChildren(Item) - common.hasSubComponents(Item, [ItemGroup]) + + describe('content prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('description prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('extra prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('header prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) + + describe('image prop', () => { + it('renders ItemImage component', () => { + shallow() + .should.have.descendants('ItemImage') + }) + }) + + describe('meta prop', () => { + it('renders ItemContent component', () => { + shallow() + .should.have.descendants('ItemContent') + }) + }) }) diff --git a/test/specs/views/Item/ItemContent-test.js b/test/specs/views/Item/ItemContent-test.js new file mode 100644 index 0000000000..7865a7e2bb --- /dev/null +++ b/test/specs/views/Item/ItemContent-test.js @@ -0,0 +1,60 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemContent from 'src/views/Item/ItemContent' +import ItemDescription from 'src/views/Item/ItemDescription' +import ItemExtra from 'src/views/Item/ItemExtra' +import ItemHeader from 'src/views/Item/ItemHeader' +import ItemMeta from 'src/views/Item/ItemMeta' + +describe('ItemContent', () => { + common.isConformant(ItemContent) + common.implementsVerticalAlignProp(ItemContent) + common.rendersChildren(ItemContent) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) + + describe('description prop', () => { + it('renders ItemDescription component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('extra prop', () => { + it('renders ItemExtra component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('header prop', () => { + it('renders ItemHeader component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) + + describe('meta prop', () => { + it('renders ItemMeta component', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain() + }) + }) +}) diff --git a/test/specs/views/Item/ItemDescription-test.js b/test/specs/views/Item/ItemDescription-test.js new file mode 100644 index 0000000000..d8966faec4 --- /dev/null +++ b/test/specs/views/Item/ItemDescription-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemDescription from 'src/views/Item/ItemDescription' + +describe('ItemDescription', () => { + common.isConformant(ItemDescription) + common.rendersChildren(ItemDescription) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemExtra-test.js b/test/specs/views/Item/ItemExtra-test.js new file mode 100644 index 0000000000..201a4555f0 --- /dev/null +++ b/test/specs/views/Item/ItemExtra-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemExtra from 'src/views/Item/ItemExtra' + +describe('ItemExtra', () => { + common.isConformant(ItemExtra) + common.rendersChildren(ItemExtra) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemGroup-test.js b/test/specs/views/Item/ItemGroup-test.js index 6ca6713403..f348db18ef 100644 --- a/test/specs/views/Item/ItemGroup-test.js +++ b/test/specs/views/Item/ItemGroup-test.js @@ -1,8 +1,33 @@ -import ItemGroup from 'src/views/Item/ItemGroup' +import faker from 'faker' +import React from 'react' + import * as common from 'test/specs/commonTests' +import ItemGroup from 'src/views/Item/ItemGroup' describe('ItemGroup', () => { - common.isConformant(ItemGroup) common.hasUIClassName(ItemGroup) + common.isConformant(ItemGroup) common.rendersChildren(ItemGroup) + + common.propKeyOnlyToClassName(ItemGroup, 'divided') + common.propKeyOnlyToClassName(ItemGroup, 'link') + common.propKeyOrValueToClassName(ItemGroup, 'relaxed') + + describe('items prop', () => { + it('renders children', () => { + const firstText = faker.hacker.phrase() + const secondText = faker.hacker.phrase() + const items = [ + { content: firstText }, + { content: secondText }, + ] + + const wrapper = mount() + const itemWrappers = wrapper.find('Item') + + wrapper.should.have.exactly(2).descendants('Item') + itemWrappers.first().find('ItemContent').should.contain.text(firstText) + itemWrappers.last().find('ItemContent').should.contain.text(secondText) + }) + }) }) diff --git a/test/specs/views/Item/ItemHeader-test.js b/test/specs/views/Item/ItemHeader-test.js new file mode 100644 index 0000000000..036cf4f438 --- /dev/null +++ b/test/specs/views/Item/ItemHeader-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemHeader from 'src/views/Item/ItemHeader' + +describe('ItemHeader', () => { + common.isConformant(ItemHeader) + common.rendersChildren(ItemHeader) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) diff --git a/test/specs/views/Item/ItemImage-test.js b/test/specs/views/Item/ItemImage-test.js new file mode 100644 index 0000000000..ec83b54ff1 --- /dev/null +++ b/test/specs/views/Item/ItemImage-test.js @@ -0,0 +1,9 @@ +import React from 'react' +import ItemImage from 'src/views/Item/ItemImage' + +describe('ItemImage', () => { + it('renders Image component', () => { + shallow() + .should.have.descendants('Image') + }) +}) diff --git a/test/specs/views/Item/ItemMeta-test.js b/test/specs/views/Item/ItemMeta-test.js new file mode 100644 index 0000000000..d4e1a41640 --- /dev/null +++ b/test/specs/views/Item/ItemMeta-test.js @@ -0,0 +1,19 @@ +import faker from 'faker' +import React from 'react' + +import * as common from 'test/specs/commonTests' +import ItemMeta from 'src/views/Item/ItemMeta' + +describe('ItemMeta', () => { + common.isConformant(ItemMeta) + common.rendersChildren(ItemMeta) + + describe('content prop', () => { + it('renders text', () => { + const text = faker.hacker.phrase() + + shallow() + .should.contain.text(text) + }) + }) +}) From 010b00c92529a8878a468e5eb57a00fead7e223d Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Mon, 29 Aug 2016 10:58:48 -0700 Subject: [PATCH 13/18] feat(Image): configurable ui className --- src/elements/Image/Image.js | 8 ++++++-- test/specs/elements/Image/Image-test.js | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/elements/Image/Image.js b/src/elements/Image/Image.js index 03b9a1d28e..b1ba6158ab 100644 --- a/src/elements/Image/Image.js +++ b/src/elements/Image/Image.js @@ -20,11 +20,11 @@ import ImageGroup from './ImageGroup' function Image(props) { const { verticalAlign, alt, avatar, bordered, centered, className, disabled, floated, fluid, - hidden, height, href, inline, shape, size, spaced, src, width, + hidden, height, href, inline, shape, size, spaced, src, width, ui, } = props const classes = cx( - 'ui', + ui && 'ui', size, useVerticalAlignProp(verticalAlign, 'aligned'), useKeyOnly(avatar, 'avatar'), @@ -140,6 +140,9 @@ Image.propTypes = { /** Specifies the URL of the image */ src: PropTypes.string, + /** Whether or not to add the ui className */ + ui: PropTypes.bool, + /** The img element width attribute */ width: PropTypes.oneOfType([ PropTypes.string, @@ -156,6 +159,7 @@ Image.propTypes = { Image.defaultProps = { as: 'img', + ui: true, } export default Image diff --git a/test/specs/elements/Image/Image-test.js b/test/specs/elements/Image/Image-test.js index 8aa9e2678d..56e3448859 100644 --- a/test/specs/elements/Image/Image-test.js +++ b/test/specs/elements/Image/Image-test.js @@ -41,6 +41,21 @@ describe('Image Component', () => { }) }) + describe('ui', () => { + it('is true by default', () => { + Image.defaultProps.should.have.any.keys('ui') + Image.defaultProps.ui.should.equal(true) + }) + it('adds the "ui" className when true', () => { + shallow() + .should.have.className('ui') + }) + it('removes the "ui" className when false', () => { + shallow() + .should.not.have.className('ui') + }) + }) + describe('wrapped', () => { it('applies all img attribute props to the img tag', () => { const props = { src: 'http://g.co', alt: 'alt text', width: 10, height: '10' } From 40da9feea41af1ceb22e8f1229b5725ea1190abb Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Mon, 29 Aug 2016 10:59:20 -0700 Subject: [PATCH 14/18] fix(Item): use getUnhandledProps --- src/views/Item/ItemImage.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index bce174e2d5..30578cbd65 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -1,6 +1,7 @@ import React from 'react' import { getElementType, + getUnhandledProps, META, } from '../../lib' import Image from '../../elements/Image/Image' @@ -10,8 +11,8 @@ import Image from '../../elements/Image/Image' * */ function ItemImage(props) { const ElementType = getElementType(ItemImage, props) - - return + const rest = getUnhandledProps(ItemImage, props) + return } ItemImage._meta = { From 4c5cd26a35808758fbcb20b9a6f5e223fcaf6b02 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Mon, 29 Aug 2016 21:35:48 +0300 Subject: [PATCH 15/18] fix (ItemGroup) Fix in prop handling --- src/views/Item/ItemGroup.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index 4f63076aae..977c743424 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -33,9 +33,12 @@ function ItemGroup(props) { return {children} } - const itemsJSX = _.map(items, item => ( - - )) + const itemsJSX = _.map(items, item => { + const {childKey, ...itemProps} = item + const finalKey = childKey || [itemProps.content, itemProps.description, itemProps.header, itemProps.meta].join('-') + + return + }) return {itemsJSX} } @@ -69,7 +72,10 @@ ItemGroup.propTypes = { items: customPropTypes.every([ customPropTypes.disallow(['children']), PropTypes.arrayOf(PropTypes.shape({ - childKey: PropTypes.string, + childKey: PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), // this object is spread on the Item // allow it to validate props instead })), From bc60ee7cd218f3d8c60a8cb8586c59b67238ef63 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Mon, 29 Aug 2016 21:38:17 +0300 Subject: [PATCH 16/18] fix(Item) Fix lint issues --- src/views/Item/ItemGroup.js | 4 ++-- src/views/Item/ItemImage.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index 977c743424..b5b8ed4de9 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -34,10 +34,10 @@ function ItemGroup(props) { } const itemsJSX = _.map(items, item => { - const {childKey, ...itemProps} = item + const { childKey, ...itemProps } = item const finalKey = childKey || [itemProps.content, itemProps.description, itemProps.header, itemProps.meta].join('-') - return + return }) return {itemsJSX} diff --git a/src/views/Item/ItemImage.js b/src/views/Item/ItemImage.js index 30578cbd65..a81eb84454 100644 --- a/src/views/Item/ItemImage.js +++ b/src/views/Item/ItemImage.js @@ -12,6 +12,7 @@ import Image from '../../elements/Image/Image' function ItemImage(props) { const ElementType = getElementType(ItemImage, props) const rest = getUnhandledProps(ItemImage, props) + return } From cd5085db7457cf73126b321012c58db4d6034e90 Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Mon, 29 Aug 2016 21:55:56 +0300 Subject: [PATCH 17/18] fix(Item) Fix key handling --- src/views/Item/ItemGroup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Item/ItemGroup.js b/src/views/Item/ItemGroup.js index b5b8ed4de9..28efe2c5ec 100644 --- a/src/views/Item/ItemGroup.js +++ b/src/views/Item/ItemGroup.js @@ -37,7 +37,7 @@ function ItemGroup(props) { const { childKey, ...itemProps } = item const finalKey = childKey || [itemProps.content, itemProps.description, itemProps.header, itemProps.meta].join('-') - return + return }) return {itemsJSX} From 0d34c02d45e7eb83738367dc45e797da3c4a1e3c Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Mon, 29 Aug 2016 13:03:26 -0700 Subject: [PATCH 18/18] fix(Image): use useKeyOnly for ui class --- src/elements/Image/Image.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elements/Image/Image.js b/src/elements/Image/Image.js index b1ba6158ab..5e43cfcd75 100644 --- a/src/elements/Image/Image.js +++ b/src/elements/Image/Image.js @@ -24,7 +24,7 @@ function Image(props) { } = props const classes = cx( - ui && 'ui', + useKeyOnly(ui, 'ui'), size, useVerticalAlignProp(verticalAlign, 'aligned'), useKeyOnly(avatar, 'avatar'),