UNPKG

d2-ui

Version:
560 lines (463 loc) 17.8 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _colorManipulator = require('../utils/color-manipulator'); var _colorManipulator2 = _interopRequireDefault(_colorManipulator); var _stylePropable = require('../mixins/style-propable'); var _stylePropable2 = _interopRequireDefault(_stylePropable); var _transitions = require('../styles/transitions'); var _transitions2 = _interopRequireDefault(_transitions); var _uniqueId = require('../utils/unique-id'); var _uniqueId2 = _interopRequireDefault(_uniqueId); var _enhancedTextarea = require('../enhanced-textarea'); var _enhancedTextarea2 = _interopRequireDefault(_enhancedTextarea); var _getMuiTheme = require('../styles/getMuiTheme'); var _getMuiTheme2 = _interopRequireDefault(_getMuiTheme); var _contextPure = require('../mixins/context-pure'); var _contextPure2 = _interopRequireDefault(_contextPure); var _TextFieldHint = require('./TextFieldHint'); var _TextFieldHint2 = _interopRequireDefault(_TextFieldHint); var _TextFieldLabel = require('./TextFieldLabel'); var _TextFieldLabel2 = _interopRequireDefault(_TextFieldLabel); var _TextFieldUnderline = require('./TextFieldUnderline'); var _TextFieldUnderline2 = _interopRequireDefault(_TextFieldUnderline); var _warning = require('warning'); var _warning2 = _interopRequireDefault(_warning); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** * Check if a value is valid to be displayed inside an input. * * @param The value to check. * @returns True if the string provided is valid, false otherwise. */ function isValid(value) { return Boolean(value || value === 0); } var TextField = _react2.default.createClass({ displayName: 'TextField', propTypes: { children: _react2.default.PropTypes.node, /** * The css class name of the root element. */ className: _react2.default.PropTypes.string, /** * The text string to use for the default value. */ defaultValue: _react2.default.PropTypes.any, /** * Disables the text field if set to true. */ disabled: _react2.default.PropTypes.bool, /** * The style object to use to override error styles. */ errorStyle: _react2.default.PropTypes.object, /** * The error content to display. */ errorText: _react2.default.PropTypes.node, /** * The style object to use to override floating label styles. */ floatingLabelStyle: _react2.default.PropTypes.object, /** * The content to use for the floating label element. */ floatingLabelText: _react2.default.PropTypes.node, /** * If true, the field receives the property width 100%. */ fullWidth: _react2.default.PropTypes.bool, /** * Override the inline-styles of the TextField's hint text element. */ hintStyle: _react2.default.PropTypes.object, /** * The hint content to display. */ hintText: _react2.default.PropTypes.node, /** * The id prop for the text field. */ id: _react2.default.PropTypes.string, /** * Override the inline-styles of the TextField's input element. */ inputStyle: _react2.default.PropTypes.object, /** * If true, a textarea element will be rendered. * The textarea also grows and shrinks according to the number of lines. */ multiLine: _react2.default.PropTypes.bool, /** * Callback function that is fired when the textfield loses focus. */ onBlur: _react2.default.PropTypes.func, /** * Callback function that is fired when the textfield's value changes. */ onChange: _react2.default.PropTypes.func, /** * The function to call when the user presses the Enter key. */ onEnterKeyDown: _react2.default.PropTypes.func, /** * Callback function that is fired when the textfield gains focus. */ onFocus: _react2.default.PropTypes.func, /** * Callback function fired when key is pressed down. */ onKeyDown: _react2.default.PropTypes.func, /** * Number of rows to display when multiLine option is set to true. */ rows: _react2.default.PropTypes.number, /** * Maximum number of rows to display when * multiLine option is set to true. */ rowsMax: _react2.default.PropTypes.number, /** * Override the inline-styles of the root element. */ style: _react2.default.PropTypes.object, /** * Specifies the type of input to display * such as "password" or "text". */ type: _react2.default.PropTypes.string, /** * Override the inline-styles of the * TextField's underline element when disabled. */ underlineDisabledStyle: _react2.default.PropTypes.object, /** * Override the inline-styles of the TextField's * underline element when focussed. */ underlineFocusStyle: _react2.default.PropTypes.object, /** * If true, shows the underline for the text field. */ underlineShow: _react2.default.PropTypes.bool, /** * Override the inline-styles of the TextField's underline element. */ underlineStyle: _react2.default.PropTypes.object, /** * The value of the text field. */ value: _react2.default.PropTypes.any }, contextTypes: { muiTheme: _react2.default.PropTypes.object }, //for passing default theme context to children childContextTypes: { muiTheme: _react2.default.PropTypes.object }, mixins: [_contextPure2.default, _stylePropable2.default], statics: { getRelevantContextKeys: function getRelevantContextKeys(muiTheme) { var textFieldTheme = muiTheme.textField; return { floatingLabelColor: textFieldTheme.floatingLabelColor, focusColor: textFieldTheme.focusColor, textColor: textFieldTheme.textColor, disabledTextColor: textFieldTheme.disabledTextColor, backgroundColor: textFieldTheme.backgroundColor, hintColor: textFieldTheme.hintColor, errorColor: textFieldTheme.errorColor }; }, getChildrenClasses: function getChildrenClasses() { return [_enhancedTextarea2.default]; } }, getDefaultProps: function getDefaultProps() { return { disabled: false, multiLine: false, fullWidth: false, type: 'text', underlineShow: true, rows: 1 }; }, getInitialState: function getInitialState() { var props = this.props.children ? this.props.children.props : this.props; return { isFocused: false, errorText: this.props.errorText, hasValue: isValid(props.value) || isValid(props.defaultValue) || props.valueLink && isValid(props.valueLink.value), muiTheme: this.context.muiTheme || (0, _getMuiTheme2.default)() }; }, getChildContext: function getChildContext() { return { muiTheme: this.state.muiTheme }; }, componentDidMount: function componentDidMount() { this._uniqueId = _uniqueId2.default.generate(); }, componentWillReceiveProps: function componentWillReceiveProps(nextProps, nextContext) { var newState = {}; newState.muiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; newState.errorText = nextProps.errorText; if (nextProps.children && nextProps.children.props) { nextProps = nextProps.children.props; } var hasValueLinkProp = nextProps.hasOwnProperty('valueLink'); var hasValueProp = nextProps.hasOwnProperty('value'); var hasNewDefaultValue = nextProps.defaultValue !== this.props.defaultValue; if (hasValueLinkProp) { newState.hasValue = isValid(nextProps.valueLink.value); } else if (hasValueProp) { newState.hasValue = isValid(nextProps.value); } else if (hasNewDefaultValue) { newState.hasValue = isValid(nextProps.defaultValue); } if (newState) this.setState(newState); }, getStyles: function getStyles() { var props = this.props; var _constructor$getRelev = this.constructor.getRelevantContextKeys(this.state.muiTheme); var floatingLabelColor = _constructor$getRelev.floatingLabelColor; var focusColor = _constructor$getRelev.focusColor; var textColor = _constructor$getRelev.textColor; var disabledTextColor = _constructor$getRelev.disabledTextColor; var backgroundColor = _constructor$getRelev.backgroundColor; var hintColor = _constructor$getRelev.hintColor; var errorColor = _constructor$getRelev.errorColor; var styles = { root: { fontSize: 16, lineHeight: '24px', width: props.fullWidth ? '100%' : 256, height: (props.rows - 1) * 24 + (props.floatingLabelText ? 72 : 48), display: 'inline-block', position: 'relative', backgroundColor: backgroundColor, fontFamily: this.state.muiTheme.rawTheme.fontFamily, transition: _transitions2.default.easeOut('200ms', 'height') }, error: { position: 'relative', bottom: 2, fontSize: 12, lineHeight: '12px', color: errorColor, transition: _transitions2.default.easeOut() }, floatingLabel: { color: hintColor }, input: { tapHighlightColor: 'rgba(0,0,0,0)', padding: 0, position: 'relative', width: '100%', height: '100%', border: 'none', outline: 'none', backgroundColor: 'transparent', color: props.disabled ? disabledTextColor : textColor, font: 'inherit' } }; styles.error = this.mergeStyles(styles.error, props.errorStyle); styles.textarea = this.mergeStyles(styles.input, { marginTop: props.floatingLabelText ? 36 : 12, marginBottom: props.floatingLabelText ? -36 : -12, boxSizing: 'border-box', font: 'inherit' }); if (this.state.isFocused) { styles.floatingLabel.color = focusColor; } if (this.state.hasValue) { styles.floatingLabel.color = _colorManipulator2.default.fade(props.disabled ? disabledTextColor : floatingLabelColor, 0.5); } if (props.floatingLabelText) { styles.input.boxSizing = 'border-box'; if (!props.multiLine) { styles.input.marginTop = 14; } if (this.state.errorText) { styles.error.bottom = !props.multiLine ? styles.error.fontSize + 3 : 3; } } if (this.state.errorText) { if (this.state.isFocused) { styles.floatingLabel.color = styles.error.color; } } return styles; }, blur: function blur() { if (this.isMounted()) this._getInputNode().blur(); }, clearValue: function clearValue() { this.setValue(''); }, focus: function focus() { if (this.isMounted()) this._getInputNode().focus(); }, getValue: function getValue() { return this.isMounted() ? this._getInputNode().value : undefined; }, setErrorText: function setErrorText(newErrorText) { process.env.NODE_ENV !== "production" ? (0, _warning2.default)(false, 'setErrorText() method is deprecated. Use the errorText property instead.') : undefined; if (this.isMounted()) { this.setState({ errorText: newErrorText }); } }, setValue: function setValue(newValue) { process.env.NODE_ENV !== "production" ? (0, _warning2.default)(false, 'setValue() method is deprecated. Use the defaultValue property instead.\n Or use the TextField as a controlled component with the value property.') : undefined; if (this.isMounted()) { if (this.props.multiLine) { this.refs.input.setValue(newValue); } else { this._getInputNode().value = newValue; } this.setState({ hasValue: isValid(newValue) }); } }, _getInputNode: function _getInputNode() { return this.props.children || this.props.multiLine ? this.refs.input.getInputNode() : _reactDom2.default.findDOMNode(this.refs.input); }, _handleInputBlur: function _handleInputBlur(e) { this.setState({ isFocused: false }); if (this.props.onBlur) this.props.onBlur(e); }, _handleInputChange: function _handleInputChange(e) { this.setState({ hasValue: isValid(e.target.value) }); if (this.props.onChange) this.props.onChange(e); }, _handleInputFocus: function _handleInputFocus(e) { if (this.props.disabled) return; this.setState({ isFocused: true }); if (this.props.onFocus) this.props.onFocus(e); }, _handleInputKeyDown: function _handleInputKeyDown(e) { if (e.keyCode === 13 && this.props.onEnterKeyDown) this.props.onEnterKeyDown(e); if (this.props.onKeyDown) this.props.onKeyDown(e); }, _handleTextAreaHeightChange: function _handleTextAreaHeightChange(e, height) { var newHeight = height + 24; if (this.props.floatingLabelText) newHeight += 24; _reactDom2.default.findDOMNode(this).style.height = newHeight + 'px'; }, _isControlled: function _isControlled() { return this.props.hasOwnProperty('value') || this.props.hasOwnProperty('valueLink'); }, render: function render() { var _props = this.props; var className = _props.className; var disabled = _props.disabled; var errorStyle = _props.errorStyle; var errorText = _props.errorText; var floatingLabelText = _props.floatingLabelText; var fullWidth = _props.fullWidth; var hintText = _props.hintText; var hintStyle = _props.hintStyle; var id = _props.id; var multiLine = _props.multiLine; var onBlur = _props.onBlur; var onChange = _props.onChange; var onFocus = _props.onFocus; var style = _props.style; var type = _props.type; var underlineDisabledStyle = _props.underlineDisabledStyle; var underlineFocusStyle = _props.underlineFocusStyle; var underlineShow = _props.underlineShow; var underlineStyle = _props.underlineStyle; var rows = _props.rows; var rowsMax = _props.rowsMax; var other = _objectWithoutProperties(_props, ['className', 'disabled', 'errorStyle', 'errorText', 'floatingLabelText', 'fullWidth', 'hintText', 'hintStyle', 'id', 'multiLine', 'onBlur', 'onChange', 'onFocus', 'style', 'type', 'underlineDisabledStyle', 'underlineFocusStyle', 'underlineShow', 'underlineStyle', 'rows', 'rowsMax']); var styles = this.getStyles(); var inputId = id || this._uniqueId; var errorTextElement = this.state.errorText ? _react2.default.createElement( 'div', { style: this.prepareStyles(styles.error) }, this.state.errorText ) : null; var floatingLabelTextElement = floatingLabelText ? _react2.default.createElement( _TextFieldLabel2.default, { muiTheme: this.state.muiTheme, style: this.mergeStyles(styles.floatingLabel, this.props.floatingLabelStyle), htmlFor: inputId, shrink: this.state.hasValue || this.state.isFocused, disabled: disabled, onTouchTap: this.focus }, floatingLabelText ) : null; var inputProps = undefined; var inputElement = undefined; inputProps = { id: inputId, ref: 'input', onBlur: this._handleInputBlur, onFocus: this._handleInputFocus, disabled: this.props.disabled, onKeyDown: this._handleInputKeyDown }; var inputStyle = this.mergeStyles(styles.input, this.props.inputStyle); if (!this.props.hasOwnProperty('valueLink')) { inputProps.onChange = this._handleInputChange; } if (this.props.children) { inputElement = _react2.default.cloneElement(this.props.children, _extends({}, inputProps, this.props.children.props, { style: this.mergeStyles(inputStyle, this.props.children.props.style) })); } else { inputElement = multiLine ? _react2.default.createElement(_enhancedTextarea2.default, _extends({}, other, inputProps, { style: inputStyle, rows: rows, rowsMax: rowsMax, onHeightChange: this._handleTextAreaHeightChange, textareaStyle: styles.textarea })) : _react2.default.createElement('input', _extends({}, other, inputProps, { style: this.prepareStyles(inputStyle), type: type })); } return _react2.default.createElement( 'div', { className: className, style: this.prepareStyles(styles.root, this.props.style) }, floatingLabelTextElement, hintText ? _react2.default.createElement(_TextFieldHint2.default, { muiTheme: this.state.muiTheme, show: !(this.state.hasValue || floatingLabelText && !this.state.isFocused), style: hintStyle, text: hintText }) : null, inputElement, underlineShow ? _react2.default.createElement(_TextFieldUnderline2.default, { disabled: disabled, disabledStyle: underlineDisabledStyle, error: this.state.errorText ? true : false, errorStyle: errorStyle, focus: this.state.isFocused, focusStyle: underlineFocusStyle, muiTheme: this.state.muiTheme, style: underlineStyle }) : null, errorTextElement ); } }); exports.default = TextField; module.exports = exports['default'];