diff --git a/src/TextField/TextCharCount.jsx b/src/TextField/TextCharCount.jsx new file mode 100644 index 00000000000000..abbaf6af9514fe --- /dev/null +++ b/src/TextField/TextCharCount.jsx @@ -0,0 +1,82 @@ +import React from 'react'; +const propTypes = { + /** + * True if current count exceeds maximum count. + */ + countError: React.PropTypes.bool, + + /** + * Current number of character in the Textfield. + */ + currentChar: React.PropTypes.number, + + /** + * Override the inline-styles of the error element. + */ + errorStyle: React.PropTypes.object, + + /** + * Maximum number of character in the Textfield. + */ + maxChar: React.PropTypes.number, + + /** + * @ignore + * The material-ui theme applied to this component. + */ + muiTheme: React.PropTypes.object.isRequired, + + /** + * Override the inline-styles of the root element. + */ + style: React.PropTypes.object, +}; + +const defaultProps = { +}; + +const TextCharCount = (props) => { + const { + countError, + currentChar, + maxChar, + muiTheme, + style, + errorStyle, + } = props; + + const { + prepareStyles, + textField: { + hintColor, + errorColor, + }, + } = muiTheme; + + const styles = { + root: { + position: 'relative', + color: hintColor, + float: 'right', + fontSize: '12px', + bottom: 8, + }, + error: { + color: errorColor, + }, + }; + + let regularStyle = Object.assign({}, styles.root, style); + if (countError) regularStyle = Object.assign({}, styles.root, styles.error, errorStyle); + + return ( +
+ {currentChar}/{maxChar} +
+ ); +}; + +TextCharCount.propTypes = propTypes; +TextCharCount.defaultProps = defaultProps; + +export default TextCharCount; diff --git a/src/TextField/TextField.jsx b/src/TextField/TextField.jsx index 2ceb7a709054f3..23f036113f7733 100644 --- a/src/TextField/TextField.jsx +++ b/src/TextField/TextField.jsx @@ -10,6 +10,8 @@ import getMuiTheme from '../styles/getMuiTheme'; import TextFieldHint from './TextFieldHint'; import TextFieldLabel from './TextFieldLabel'; import TextFieldUnderline from './TextFieldUnderline'; +import TextCharCount from './TextCharCount'; + const getStyles = (props, state) => { const { @@ -81,6 +83,10 @@ const getStyles = (props, state) => { styles.floatingLabel.color = ColorManipulator.fade(props.disabled ? disabledTextColor : floatingLabelColor, 0.5); } + if(state.charCountError){ + styles.floatingLabel.color = errorColor; + } + if (props.floatingLabelText) { styles.input.boxSizing = 'border-box'; @@ -115,6 +121,16 @@ function isValid(value) { const TextField = React.createClass({ propTypes: { + /** + * Maximum number of character in the Textfield + */ + charCountMax: React.PropTypes.number, + + /** + * The style object to use to override character count style. + */ + charCountStyle: React.PropTypes.bool, + children: React.PropTypes.node, /** @@ -211,6 +227,10 @@ const TextField = React.createClass({ */ onKeyDown: React.PropTypes.func, + /** + * Callback function fired when key is up. + */ + /** * Number of rows to display when multiLine option is set to true. */ @@ -296,6 +316,8 @@ const TextField = React.createClass({ hasValue: isValid(props.value) || isValid(props.defaultValue) || (props.valueLink && isValid(props.valueLink.value)), muiTheme: this.context.muiTheme || getMuiTheme(), + currentCharCount: (this.props.defaultValue) ? this.props.defaultValue.length : 0, + charCountError: false, }; }, @@ -370,6 +392,12 @@ const TextField = React.createClass({ if (this.props.onKeyDown) this.props.onKeyDown(event); }, + _handleInputKeyUp() { + this.setState({currentCharCount: this.getValue().length}); + if (this.props.charCountMax >= this.getValue().length) this.setState({charCountError: false}); + if (this.props.charCountMax < this.getValue().length) this.setState({charCountError: true}); + }, + _handleTextAreaHeightChange(event, height) { let newHeight = height + 24; if (this.props.floatingLabelText) newHeight += 24; @@ -384,6 +412,8 @@ const TextField = React.createClass({ render() { const { className, + charCountStyle, + charCountMax, disabled, errorStyle, errorText, @@ -424,7 +454,7 @@ const TextField = React.createClass({ const floatingLabelTextElement = floatingLabelText && ( ) : ( ); } @@ -495,7 +528,7 @@ const TextField = React.createClass({ : null } + {(charCountMax && this.state.isFocused) ? + : + null + } {errorTextElement} );