From fa3a9dbce98ba768f5c22862321cab758f64597a Mon Sep 17 00:00:00 2001 From: Alexander Fedyashov Date: Wed, 1 Feb 2017 21:58:53 +0200 Subject: [PATCH] style(Progress): refactor, update typings and remove propTypes --- src/modules/Progress/Progress.js | 315 ++++++++++--------- src/modules/Progress/index.d.ts | 21 +- test/specs/modules/Progress/Progress-test.js | 6 +- 3 files changed, 181 insertions(+), 161 deletions(-) diff --git a/src/modules/Progress/Progress.js b/src/modules/Progress/Progress.js index 1cdb82c471..5af5fec978 100644 --- a/src/modules/Progress/Progress.js +++ b/src/modules/Progress/Progress.js @@ -1,6 +1,6 @@ -import _ from 'lodash' import cx from 'classnames' -import React, { PropTypes } from 'react' +import _ from 'lodash' +import React, { Component, PropTypes } from 'react' import { customPropTypes, @@ -12,173 +12,192 @@ import { useValueAndKey, } from '../../lib' -function Progress(props) { - const { - active, attached, autoSuccess, color, children, className, disabled, error, indicating, - inverted, label, percent, precision, progress, size, success, total, value, warning, - } = props +/** + * A progress bar shows the progression of a task. + */ +class Progress extends Component { + static propTypes = { + /** An element type to render as (string or function). */ + as: customPropTypes.as, - const isAutoSuccess = autoSuccess && (percent >= 100 || value >= total) + /** A progress bar can show activity. */ + active: PropTypes.bool, - const showProgress = progress - || label - || !_.isUndefined(precision) - || !(_.every([total, value], _.isUndefined)) + /** A progress bar can attach to and show the progress of an element (i.e. Card or Segment). */ + attached: PropTypes.oneOf(['top', 'bottom']), - let _percent - if (!_.isUndefined(percent)) { - _percent = percent - } else if (!_.isUndefined(total) && !_.isUndefined(value)) { - _percent = value / total * 100 - } + /** Whether success state should automatically trigger when progress completes. */ + autoSuccess: PropTypes.bool, - _percent = _.clamp(_percent, 0, 100) + /** Primary content. */ + children: PropTypes.node, - if (!_.isUndefined(precision)) { - _percent = _.round(_percent, precision) - } + /** Additional classes. */ + className: PropTypes.string, - let progressText - if (label === 'percent' || label === true || _.isUndefined(label)) { - progressText = `${_percent}%` - } else if (label === 'ratio') { - progressText = `${value}/${total}` - } + /** A progress bar can have different colors. */ + color: PropTypes.oneOf(SUI.COLORS), - const classes = cx( - 'ui', - size, - color, - useKeyOnly(active || indicating, 'active'), - useKeyOnly(isAutoSuccess || success, 'success'), - useKeyOnly(warning, 'warning'), - useKeyOnly(error, 'error'), - useKeyOnly(disabled, 'disabled'), - useKeyOnly(indicating, 'indicating'), - useKeyOnly(inverted, 'inverted'), - useValueAndKey(attached, 'attached'), - className, - 'progress' - ) - const rest = getUnhandledProps(Progress, props) - const ElementType = getElementType(Progress, props) - - return ( - -
- {showProgress &&
{progressText}
} -
- {children &&
{children}
} -
- ) -} + /** A progress bar be disabled. */ + disabled: PropTypes.bool, -Progress._meta = { - name: 'Progress', - type: META.TYPES.MODULE, - props: { - attached: ['top', 'bottom'], - color: SUI.COLORS, - label: ['ratio', 'percent'], - size: _.without(SUI.SIZES, 'mini', 'huge', 'massive'), - }, -} + /** A progress bar can show a error state. */ + error: PropTypes.bool, -Progress.propTypes = { - /** An element type to render as (string or function). */ - as: customPropTypes.as, + /** An indicating progress bar visually indicates the current level of progress of a task. */ + indicating: PropTypes.bool, - /** A progress bar can show activity. */ - active: PropTypes.bool, + /** A progress bar can have its colors inverted. */ + inverted: PropTypes.bool, - /** A progress bar can attach to and show the progress of an element (i.e. Card or Segment). */ - attached: PropTypes.oneOf(Progress._meta.props.attached), + /** Can be set to either to display progress as percent or ratio. */ + label: customPropTypes.every([ + customPropTypes.some([ + customPropTypes.demand(['percent']), + customPropTypes.demand(['total', 'value']), + ]), + PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.oneOf(['ratio', 'percent']), + ]), + ]), - /** Whether success state should automatically trigger when progress completes. */ - autoSuccess: PropTypes.bool, + /** Current percent complete. */ + percent: customPropTypes.every([ + customPropTypes.disallow(['total', 'value']), + PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + ]), - /** A progress bar can have different colors. */ - color: PropTypes.oneOf(Progress._meta.props.color), + /** Decimal point precision for calculated progress. */ + precision: PropTypes.number, + + /** A progress bar can contain a text value indicating current progress. */ + progress: PropTypes.bool, + + /** A progress bar can vary in size. */ + size: PropTypes.oneOf(_.without(SUI.SIZES, 'mini', 'huge', 'massive')), + + /** A progress bar can show a success state. */ + success: PropTypes.bool, + + /** + * For use with value. + * Together, these will calculate the percent. + * Mutually excludes percent. + */ + total: customPropTypes.every([ + customPropTypes.demand(['value']), + customPropTypes.disallow(['percent']), + PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + ]), - /** Primary content. */ - children: PropTypes.node, + /** + * For use with total. Together, these will calculate the percent. Mutually excludes percent. + */ + value: customPropTypes.every([ + customPropTypes.demand(['total']), + customPropTypes.disallow(['percent']), + PropTypes.oneOfType([ + PropTypes.number, + PropTypes.string, + ]), + ]), - /** Additional classes. */ - className: PropTypes.string, + /** A progress bar can show a warning state. */ + warning: PropTypes.bool, + } - /** A progress bar be disabled. */ - disabled: PropTypes.bool, + static _meta = { + name: 'Progress', + type: META.TYPES.MODULE, + } - /** A progress bar can show a error state. */ - error: PropTypes.bool, + calculatePercent = () => { + const { percent, total, value } = this.props - /** An indicating progress bar visually indicates the current level of progress of a task. */ - indicating: PropTypes.bool, + if (!_.isUndefined(percent)) return percent + if (!_.isUndefined(total) && !_.isUndefined(value)) return value / total * 100 + } - /** A progress bar can have its colors inverted. */ - inverted: PropTypes.bool, + getPercent = () => { + const { precision } = this.props + const percent = _.clamp(this.calculatePercent(), 0, 100) - /** Can be set to either to display progress as percent or ratio. */ - label: customPropTypes.every([ - customPropTypes.some([ - customPropTypes.demand(['percent']), - customPropTypes.demand(['total', 'value']), - ]), - PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.oneOf(Progress._meta.props.label), - ]), - ]), - - /** Current percent complete. */ - percent: customPropTypes.every([ - customPropTypes.disallow(['total', 'value']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), - - /** A progress bar can contain a text value indicating current progress. */ - progress: PropTypes.bool, - - /** Decimal point precision for calculated progress. */ - precision: PropTypes.number, - - /** A progress bar can vary in size. */ - size: PropTypes.oneOf(Progress._meta.props.size), - - /** A progress bar can show a success state. */ - success: PropTypes.bool, - - /** - * For use with value. - * Together, these will calculate the percent. - * Mutually excludes percent. - */ - total: customPropTypes.every([ - customPropTypes.demand(['value']), - customPropTypes.disallow(['percent']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), - - /** - * For use with total. Together, these will calculate the percent. Mutually excludes percent. - */ - value: customPropTypes.every([ - customPropTypes.demand(['total']), - customPropTypes.disallow(['percent']), - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), - ]), + if (_.isUndefined(precision)) return percent + return _.round(percent, precision) + } + + isAutoSuccess = () => { + const { autoSuccess, percent, total, value } = this.props - /** A progress bar can show a warning state. */ - warning: PropTypes.bool, + return autoSuccess && (percent >= 100 || value >= total) + } + + showProgress = () => { + const { label, precision, progress, total, value } = this.props + + if (label || progress || !_.isUndefined(precision)) return true + return !(_.every([total, value], _.isUndefined)) + } + + render() { + const { + active, + attached, + children, + className, + color, + disabled, + error, + indicating, + inverted, + label, + size, + success, + total, + value, + warning, + } = this.props + + const classes = cx( + 'ui', + color, + size, + useKeyOnly(active || indicating, 'active'), + useKeyOnly(disabled, 'disabled'), + useKeyOnly(error, 'error'), + useKeyOnly(indicating, 'indicating'), + useKeyOnly(inverted, 'inverted'), + useKeyOnly(success || this.isAutoSuccess(), 'success'), + useKeyOnly(warning, 'warning'), + useValueAndKey(attached, 'attached'), + 'progress', + className, + ) + const rest = getUnhandledProps(Progress, this.props) + const ElementType = getElementType(Progress, this.props) + + const percent = this.getPercent() + + return ( + +
+ {this.showProgress() && ( +
+ { label !== 'ratio' ? `${percent}%` : `${value}/${total}` } +
+ )} +
+ {children &&
{children}
} +
+ ) + } } export default Progress diff --git a/src/modules/Progress/index.d.ts b/src/modules/Progress/index.d.ts index 3990630912..d14318f3ba 100644 --- a/src/modules/Progress/index.d.ts +++ b/src/modules/Progress/index.d.ts @@ -1,13 +1,15 @@ -import { SemanticCOLORS, SemanticSIZES } from '../..'; import * as React from 'react'; +import { SemanticCOLORS } from '../..'; interface ProgressProps { - /** A progress bar can show activity. */ - active?: boolean; + [key: string]: any; /** An element type to render as (string or function). */ as?: any; + /** A progress bar can show activity. */ + active?: boolean; + /** A progress bar can attach to and show the progress of an element (i.e. Card or Segment). */ attached?: 'top' | 'bottom'; @@ -36,10 +38,10 @@ interface ProgressProps { inverted?: string; /** Can be set to either to display progress as percent or ratio. */ - label?: any; + label?: boolean | 'ratio' | 'percent'; /** Current percent complete. */ - percent?: any; + percent?: number | string; /** Decimal point precision for calculated progress. */ precision?: number; @@ -48,7 +50,7 @@ interface ProgressProps { progress?: boolean; /** A progress bar can vary in size. */ - size?: SemanticSIZES; + size?: 'tiny' | 'small' | 'medium' | 'large' | 'big'; /** A progress bar can show a success state. */ success?: boolean; @@ -58,16 +60,15 @@ interface ProgressProps { * Together, these will calculate the percent. * Mutually excludes percent. */ - total?: any; + total?: number | string; /** * For use with total. Together, these will calculate the percent. Mutually excludes percent. */ - value?: any; + value?: number | string; /** A progress bar can show a warning state. */ warning?: boolean; } -export class Progress extends React.Component { -} +export const Progress: React.ComponentClass; diff --git a/test/specs/modules/Progress/Progress-test.js b/test/specs/modules/Progress/Progress-test.js index 79036c9b14..2cf3a8aaa2 100644 --- a/test/specs/modules/Progress/Progress-test.js +++ b/test/specs/modules/Progress/Progress-test.js @@ -12,9 +12,6 @@ describe('Progress', () => { common.propKeyAndValueToClassName(Progress, 'attached') - common.propValueOnlyToClassName(Progress, 'color', SUI.COLORS) - common.propValueOnlyToClassName(Progress, 'size', _.without(SUI.SIZES, 'mini', 'huge', 'massive')) - common.propKeyOnlyToClassName(Progress, 'active') common.propKeyOnlyToClassName(Progress, 'disabled') common.propKeyOnlyToClassName(Progress, 'error') @@ -23,6 +20,9 @@ describe('Progress', () => { common.propKeyOnlyToClassName(Progress, 'success') common.propKeyOnlyToClassName(Progress, 'warning') + common.propValueOnlyToClassName(Progress, 'color', SUI.COLORS) + common.propValueOnlyToClassName(Progress, 'size', _.without(SUI.SIZES, 'mini', 'huge', 'massive')) + it('contains div with className bar', () => { shallow() .should.have.descendants('.bar')