diff --git a/src/elements/Loader/Loader.js b/src/elements/Loader/Loader.js index 4a266a116b..3e96a1ee22 100644 --- a/src/elements/Loader/Loader.js +++ b/src/elements/Loader/Loader.js @@ -44,16 +44,16 @@ function Loader(props) { const rest = getUnhandledProps(Loader, props) const ElementType = getElementType(Loader, props) - return {_.isNil(children) ? content : children} + return ( + + {_.isNil(children) ? content : children} + + ) } Loader._meta = { name: 'Loader', type: META.TYPES.ELEMENT, - props: { - inline: ['centered'], - size: SUI.SIZES, - }, } Loader.propTypes = { @@ -81,14 +81,14 @@ Loader.propTypes = { /** Loaders can appear inline with content. */ inline: PropTypes.oneOfType([ PropTypes.bool, - PropTypes.oneOf(Loader._meta.props.inline), + PropTypes.oneOf(['centered']), ]), /** Loaders can have their colors inverted. */ inverted: PropTypes.bool, /** Loaders can have different sizes. */ - size: PropTypes.oneOf(Loader._meta.props.size), + size: PropTypes.oneOf(SUI.SIZES), } export default Loader diff --git a/src/elements/Loader/index.d.ts b/src/elements/Loader/index.d.ts index ddf854829c..4737dfeb85 100644 --- a/src/elements/Loader/index.d.ts +++ b/src/elements/Loader/index.d.ts @@ -1,9 +1,9 @@ -import { SemanticSIZES } from '../..'; import * as React from 'react'; - +import { SemanticSIZES } from '../..'; interface LoaderProps { - + [key: string]: any; + /** An element type to render as (string or function). */ as?: any; @@ -34,5 +34,5 @@ interface LoaderProps { /** Loaders can have different sizes. */ size?: SemanticSIZES; } -export class Loader extends React.Component { -} \ No newline at end of file + +export const Loader: React.StatelessComponent; diff --git a/src/elements/Reveal/Reveal.js b/src/elements/Reveal/Reveal.js index c58b3273b1..a160195efc 100644 --- a/src/elements/Reveal/Reveal.js +++ b/src/elements/Reveal/Reveal.js @@ -41,13 +41,6 @@ function Reveal(props) { Reveal._meta = { name: 'Reveal', type: META.TYPES.ELEMENT, - props: { - animated: [ - 'fade', 'small fade', - 'move', 'move right', 'move up', 'move down', - 'rotate', 'rotate left', - ], - }, } Reveal.propTypes = { @@ -57,6 +50,13 @@ Reveal.propTypes = { /** An active reveal displays its hidden content. */ active: PropTypes.bool, + /** An animation name that will be applied to Reveal. */ + animated: PropTypes.oneOf([ + 'fade', 'small fade', + 'move', 'move right', 'move up', 'move down', + 'rotate', 'rotate left', + ]), + /** Primary content. */ children: PropTypes.node, @@ -66,9 +66,6 @@ Reveal.propTypes = { /** A disabled reveal will not animate when hovered. */ disabled: PropTypes.bool, - /** An animation name that will be applied to Reveal. */ - animated: PropTypes.oneOf(Reveal._meta.props.animated), - /** An element can show its content without delay. */ instant: PropTypes.bool, } diff --git a/src/elements/Reveal/index.d.ts b/src/elements/Reveal/index.d.ts index a43bdf78f0..c9ed28c3c3 100644 --- a/src/elements/Reveal/index.d.ts +++ b/src/elements/Reveal/index.d.ts @@ -1,34 +1,25 @@ import * as React from 'react'; -interface RevealContentProps { +interface RevealProps { + [key: string]: any; + /** An element type to render as (string or function). */ as?: any; - /** Additional classes. */ - className?: string; - - /** A reveal may contain content that is visible before interaction. */ - hidden?: boolean; - - /** A reveal may contain content that is hidden before user interaction. */ - visible?: boolean; -} - -export const RevealContent: React.ComponentClass; - -interface RevealProps { /** An active reveal displays its hidden content. */ active?: boolean; /** An animation name that will be applied to Reveal. */ - animated?: 'fade' | 'small fade' | 'move' | 'move right' | 'move up' | 'move down' | 'rotate' | 'rotate left'; - - /** An element type to render as (string or function). */ - as?: any; + animated?: 'fade' | 'small fade' + | 'move' | 'move right' | 'move up' | 'move down' + | 'rotate' | 'rotate left'; /** Additional classes. */ className?: string; + /** Primary content. */ + children?: React.ReactNode; + /** A disabled reveal will not animate when hovered. */ disabled?: boolean; @@ -36,8 +27,29 @@ interface RevealProps { instant?: boolean; } -interface RevealClass extends React.ComponentClass { +interface RevealComponent extends React.StatelessComponent { Content: typeof RevealContent; } -export const Reveal: RevealClass; +export const Reveal: RevealComponent; + +interface RevealContentProps { + [key: string]: any; + + /** An element type to render as (string or function). */ + as?: any; + + /** Primary content. */ + children?: React.ReactNode; + + /** Additional classes. */ + className?: string; + + /** A reveal may contain content that is visible before interaction. */ + hidden?: boolean; + + /** A reveal may contain content that is hidden before user interaction. */ + visible?: boolean; +} + +export const RevealContent: React.StatelessComponent; diff --git a/src/elements/Segment/Segment.js b/src/elements/Segment/Segment.js index 8b83ca4961..928ddc9803 100644 --- a/src/elements/Segment/Segment.js +++ b/src/elements/Segment/Segment.js @@ -47,25 +47,25 @@ function Segment(props) { 'ui', color, size, - useKeyOrValueAndKey(attached, 'attached'), useKeyOnly(basic, 'basic'), useKeyOnly(circular, 'circular'), useKeyOnly(clearing, 'clearing'), useKeyOnly(compact, 'compact'), useKeyOnly(disabled, 'disabled'), - useValueAndKey(floated, 'floated'), useKeyOnly(inverted, 'inverted'), useKeyOnly(loading, 'loading'), - useKeyOrValueAndKey(padded, 'padded'), useKeyOnly(piled, 'piled'), useKeyOnly(raised, 'raised'), useKeyOnly(secondary, 'secondary'), useKeyOnly(stacked, 'stacked'), useKeyOnly(tertiary, 'tertiary'), - useTextAlignProp(textAlign), useKeyOnly(vertical, 'vertical'), - className, + useKeyOrValueAndKey(attached, 'attached'), + useKeyOrValueAndKey(padded, 'padded'), + useTextAlignProp(textAlign), + useValueAndKey(floated, 'floated'), 'segment', + className, ) const rest = getUnhandledProps(Segment, props) const ElementType = getElementType(Segment, props) @@ -78,63 +78,55 @@ Segment.Group = SegmentGroup Segment._meta = { name: 'Segment', type: META.TYPES.ELEMENT, - props: { - attached: ['top', 'bottom'], - color: SUI.COLORS, - floated: SUI.FLOATS, - padded: ['very'], - size: _.without(SUI.SIZES, 'medium'), - textAlign: SUI.TEXT_ALIGNMENTS, - }, } Segment.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Attach segment to other content, like a header */ + /** Attach segment to other content, like a header. */ attached: PropTypes.oneOfType([ - PropTypes.oneOf(Segment._meta.props.attached), PropTypes.bool, + PropTypes.oneOf('top', 'bottom'), ]), - /** A basic segment has no special formatting */ + /** A basic segment has no special formatting. */ basic: PropTypes.bool, /** Primary content. */ children: PropTypes.node, - /** A segment can be circular */ + /** A segment can be circular. */ circular: PropTypes.bool, /** Additional classes. */ className: PropTypes.string, - /** A segment can clear floated content */ + /** A segment can clear floated content. */ clearing: PropTypes.bool, - /** Segment can be colored */ - color: PropTypes.oneOf(Segment._meta.props.color), + /** Segment can be colored. */ + color: PropTypes.oneOf(SUI.COLORS), - /** A segment may take up only as much space as is necessary */ + /** A segment may take up only as much space as is necessary. */ compact: PropTypes.bool, - /** A segment may show its content is disabled */ + /** A segment may show its content is disabled. */ disabled: PropTypes.bool, - /** Segment content can be floated to the left or right */ - floated: PropTypes.oneOf(Segment._meta.props.floated), + /** Segment content can be floated to the left or right. */ + floated: PropTypes.oneOf(SUI.FLOATS), - /** A segment can have its colors inverted for contrast */ + /** A segment can have its colors inverted for contrast. */ inverted: PropTypes.bool, - /** A segment may show its content is being loaded */ + /** A segment may show its content is being loaded. */ loading: PropTypes.bool, - /** A segment can increase its padding */ + /** A segment can increase its padding. */ padded: PropTypes.oneOfType([ PropTypes.bool, - PropTypes.oneOf(Segment._meta.props.padded), + PropTypes.oneOf(['very']), ]), /** Formatted to look like a pile of pages. */ @@ -143,22 +135,22 @@ Segment.propTypes = { /** A segment may be formatted to raise above the page. */ raised: PropTypes.bool, - /** A segment can be formatted to appear less noticeable */ + /** A segment can be formatted to appear less noticeable. */ secondary: PropTypes.bool, /** A segment can have different sizes. */ - size: PropTypes.oneOf(Segment._meta.props.size), + size: PropTypes.oneOf(_.without(SUI.SIZES, 'medium')), /** Formatted to show it contains multiple pages. */ stacked: PropTypes.bool, - /** A segment can be formatted to appear even less noticeable */ + /** A segment can be formatted to appear even less noticeable. */ tertiary: PropTypes.bool, /** Formats content to be aligned as part of a vertical group. */ - textAlign: PropTypes.oneOf(Segment._meta.props.textAlign), + textAlign: PropTypes.oneOf(SUI.TEXT_ALIGNMENTS), - /** Formats content to be aligned vertically */ + /** Formats content to be aligned vertically. */ vertical: PropTypes.bool, } diff --git a/src/elements/Segment/SegmentGroup.js b/src/elements/Segment/SegmentGroup.js index b0cf3c3d05..c626e8ae54 100644 --- a/src/elements/Segment/SegmentGroup.js +++ b/src/elements/Segment/SegmentGroup.js @@ -15,17 +15,27 @@ import { * A group of segments can be formatted to appear together. */ function SegmentGroup(props) { - const { children, className, compact, horizontal, piled, raised, size, stacked } = props + const { + children, + className, + compact, + horizontal, + piled, + raised, + size, + stacked, + } = props + const classes = cx( 'ui', size, - useKeyOnly(horizontal, 'horizontal'), useKeyOnly(compact, 'compact'), + useKeyOnly(horizontal, 'horizontal'), useKeyOnly(piled, 'piled'), useKeyOnly(raised, 'raised'), useKeyOnly(stacked, 'stacked'), - className, 'segments', + className, ) const rest = getUnhandledProps(SegmentGroup, props) const ElementType = getElementType(SegmentGroup, props) @@ -37,25 +47,22 @@ SegmentGroup._meta = { name: 'SegmentGroup', parent: 'Segment', type: META.TYPES.ELEMENT, - props: { - size: _.without(SUI.SIZES, 'medium'), - }, } SegmentGroup.propTypes = { /** An element type to render as (string or function). */ as: customPropTypes.as, - /** Additional classes. */ - className: PropTypes.string, - /** Primary content. */ children: PropTypes.node, - /** A segment may take up only as much space as is necessary */ + /** Additional classes. */ + className: PropTypes.string, + + /** A segment may take up only as much space as is necessary. */ compact: PropTypes.bool, - /** Formats content to be aligned horizontally */ + /** Formats content to be aligned horizontally. */ horizontal: PropTypes.bool, /** Formatted to look like a pile of pages. */ @@ -65,7 +72,7 @@ SegmentGroup.propTypes = { raised: PropTypes.bool, /** A segment group can have different sizes. */ - size: PropTypes.oneOf(SegmentGroup._meta.props.size), + size: PropTypes.oneOf(_.without(SUI.SIZES, 'medium')), /** Formatted to show it contains multiple pages. */ stacked: PropTypes.bool, diff --git a/src/elements/Segment/index.d.ts b/src/elements/Segment/index.d.ts index 2caa869a30..ec5318a984 100644 --- a/src/elements/Segment/index.d.ts +++ b/src/elements/Segment/index.d.ts @@ -1,49 +1,56 @@ -import { SemanticCOLORS, SemanticFLOATS, SemanticSIZES, SemanticSOCIAL, SemanticTEXTALIGNMENTS } from '../..'; import * as React from 'react'; +import { + SemanticCOLORS, + SemanticFLOATS, + SemanticTEXTALIGNMENTS +} from '../..'; + +type SEGMENT_SIZES = 'mini' | 'tiny' | 'small' | 'large' | 'big' | 'huge' | 'massive' interface SegmentProps { - + [key: string]: any; + /** An element type to render as (string or function). */ as?: any; - /** Attach segment to other content, like a header */ - attached?: any; + /** Attach segment to other content, like a header. */ + attached?: boolean | 'top' | 'bottom'; - /** A basic segment has no special formatting */ + /** A basic segment has no special formatting. */ basic?: boolean; /** Primary content. */ children?: React.ReactNode; - /** A segment can be circular */ + /** A segment can be circular. */ circular?: boolean; /** Additional classes. */ className?: string; - /** A segment can clear floated content */ + /** A segment can clear floated content. */ clearing?: boolean; - /** Segment can be colored */ - color?: SemanticCOLORS | SemanticSOCIAL; + /** Segment can be colored. */ + color?: SemanticCOLORS; - /** A segment may take up only as much space as is necessary */ + /** A segment may take up only as much space as is necessary. */ compact?: boolean; - /** A segment may show its content is disabled */ + /** A segment may show its content is disabled. */ disabled?: boolean; - /** Segment content can be floated to the left or right */ + /** Segment content can be floated to the left or right. */ floated?: SemanticFLOATS; - /** A segment can have its colors inverted for contrast */ + /** A segment can have its colors inverted for contrast. */ inverted?: boolean; - /** A segment may show its content is being loaded */ + /** A segment may show its content is being loaded. */ loading?: boolean; - /** A segment can increase its padding */ - padded?: boolean; + /** A segment can increase its padding. */ + padded?: boolean | 'very'; /** Formatted to look like a pile of pages. */ piled?: boolean; @@ -51,33 +58,34 @@ interface SegmentProps { /** A segment may be formatted to raise above the page. */ raised?: boolean; - /** A segment can be formatted to appear less noticeable */ + /** A segment can be formatted to appear less noticeable. */ secondary?: boolean; /** A segment can have different sizes. */ - size?: SemanticSIZES; + size?: SEGMENT_SIZES; /** Formatted to show it contains multiple pages. */ stacked?: boolean; - /** A segment can be formatted to appear even less noticeable */ + /** A segment can be formatted to appear even less noticeable. */ tertiary?: boolean; /** Formats content to be aligned as part of a vertical group. */ textAlign?: SemanticTEXTALIGNMENTS; - /** Formats content to be aligned vertically */ + /** Formats content to be aligned vertically. */ vertical?: boolean; } -interface SegmentClass extends React.ComponentClass { +interface SegmentClass extends React.StatelessComponent { Group: typeof SegmentGroup; } export const Segment: SegmentClass; interface SegmentGroupProps { - + [key: string]: any; + /** An element type to render as (string or function). */ as?: any; @@ -87,10 +95,10 @@ interface SegmentGroupProps { /** Additional classes. */ className?: string; - /** A segment may take up only as much space as is necessary */ + /** A segment may take up only as much space as is necessary. */ compact?: boolean; - /** Formats content to be aligned horizontally */ + /** Formats content to be aligned horizontally. */ horizontal?: boolean; /** Formatted to look like a pile of pages. */ @@ -100,10 +108,10 @@ interface SegmentGroupProps { raised?: boolean; /** A segment group can have different sizes. */ - size?: SemanticSIZES; + size?: SEGMENT_SIZES; /** Formatted to show it contains multiple pages. */ stacked?: boolean; } -export const SegmentGroup: React.ComponentClass; +export const SegmentGroup: React.StatelessComponent; diff --git a/test/specs/commonTests.js b/test/specs/commonTests.js index 84c1429445..4ac5514300 100644 --- a/test/specs/commonTests.js +++ b/test/specs/commonTests.js @@ -4,7 +4,12 @@ import path from 'path' import React, { createElement, isValidElement } from 'react' import ReactDOMServer from 'react-dom/server' -import { createShorthand, META, numberToWord } from 'src/lib' +import { + createShorthand, + META, + numberToWord, + SUI, +} from 'src/lib' import { consoleUtil, sandbox, syntheticEvent } from 'test/utils' import * as semanticUIReact from 'semantic-ui-react' @@ -854,10 +859,11 @@ export const implementsImageProp = (Component, options = {}) => { /** * Assert that a Component correctly implements the "textAlign" prop. * @param {React.Component|Function} Component The component to test. + * @param {array} [alignments] Array of possible alignment positions. * @param {Object} [options={}] * @param {Object} [options.requiredProps={}] Props required to render the component. */ -export const implementsTextAlignProp = (Component, options = {}) => { +export const implementsTextAlignProp = (Component, alignments = SUI.TEXT_ALIGNMENTS, options = {}) => { const { requiredProps = {} } = options const { assertRequired } = commonTestHelpers('implementsTextAlignProp', Component) @@ -867,18 +873,18 @@ export const implementsTextAlignProp = (Component, options = {}) => { _noDefaultClassNameFromProp(Component, 'textAlign', options) _noClassNameFromBoolProps(Component, 'textAlign', options) - _.each(Component._meta.props.aligned, (propVal) => { + _.each(alignments, propVal => { if (propVal === 'justified') { it('adds "justified" without "aligned" to className', () => { - shallow() + shallow() .should.have.className('justified') - shallow() + shallow() .should.not.have.className('aligned') }) } else { it(`adds "${propVal} aligned" to className`, () => { - shallow() + shallow() .should.have.className(`${propVal} ${'aligned'}`) }) }