575 lines
18 KiB
JavaScript
575 lines
18 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _extends2 = require('babel-runtime/helpers/extends');
|
|
|
|
var _extends3 = _interopRequireDefault(_extends2);
|
|
|
|
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
|
|
|
|
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
|
|
|
|
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
|
|
|
|
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
|
|
|
|
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
|
|
|
|
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
|
|
|
|
var _createClass2 = require('babel-runtime/helpers/createClass');
|
|
|
|
var _createClass3 = _interopRequireDefault(_createClass2);
|
|
|
|
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
|
|
|
|
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
|
|
|
|
var _inherits2 = require('babel-runtime/helpers/inherits');
|
|
|
|
var _inherits3 = _interopRequireDefault(_inherits2);
|
|
|
|
var _simpleAssign = require('simple-assign');
|
|
|
|
var _simpleAssign2 = _interopRequireDefault(_simpleAssign);
|
|
|
|
var _react = require('react');
|
|
|
|
var _react2 = _interopRequireDefault(_react);
|
|
|
|
var _reactDom = require('react-dom');
|
|
|
|
var _reactDom2 = _interopRequireDefault(_reactDom);
|
|
|
|
var _shallowEqual = require('recompose/shallowEqual');
|
|
|
|
var _shallowEqual2 = _interopRequireDefault(_shallowEqual);
|
|
|
|
var _transitions = require('../styles/transitions');
|
|
|
|
var _transitions2 = _interopRequireDefault(_transitions);
|
|
|
|
var _EnhancedTextarea = require('./EnhancedTextarea');
|
|
|
|
var _EnhancedTextarea2 = _interopRequireDefault(_EnhancedTextarea);
|
|
|
|
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 }; }
|
|
|
|
var getStyles = function getStyles(props, context, state) {
|
|
var _context$muiTheme = context.muiTheme,
|
|
baseTheme = _context$muiTheme.baseTheme,
|
|
_context$muiTheme$tex = _context$muiTheme.textField,
|
|
floatingLabelColor = _context$muiTheme$tex.floatingLabelColor,
|
|
focusColor = _context$muiTheme$tex.focusColor,
|
|
textColor = _context$muiTheme$tex.textColor,
|
|
disabledTextColor = _context$muiTheme$tex.disabledTextColor,
|
|
backgroundColor = _context$muiTheme$tex.backgroundColor,
|
|
errorColor = _context$muiTheme$tex.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: baseTheme.fontFamily,
|
|
transition: _transitions2.default.easeOut('200ms', 'height'),
|
|
cursor: props.disabled ? 'not-allowed' : 'auto'
|
|
},
|
|
error: {
|
|
position: 'relative',
|
|
bottom: 2,
|
|
fontSize: 12,
|
|
lineHeight: '12px',
|
|
color: errorColor,
|
|
transition: _transitions2.default.easeOut()
|
|
},
|
|
floatingLabel: {
|
|
color: props.disabled ? disabledTextColor : floatingLabelColor,
|
|
pointerEvents: 'none'
|
|
},
|
|
input: {
|
|
padding: 0,
|
|
position: 'relative',
|
|
width: '100%',
|
|
border: 'none',
|
|
outline: 'none',
|
|
backgroundColor: 'rgba(0,0,0,0)',
|
|
color: props.disabled ? disabledTextColor : textColor,
|
|
cursor: 'inherit',
|
|
font: 'inherit',
|
|
WebkitTapHighlightColor: 'rgba(0,0,0,0)' },
|
|
inputNative: {
|
|
appearance: 'textfield' }
|
|
};
|
|
|
|
styles.textarea = (0, _simpleAssign2.default)({}, styles.input, {
|
|
marginTop: props.floatingLabelText ? 36 : 12,
|
|
marginBottom: props.floatingLabelText ? -36 : -12,
|
|
boxSizing: 'border-box',
|
|
font: 'inherit'
|
|
});
|
|
|
|
// Do not assign a height to the textarea as he handles it on his own.
|
|
styles.input.height = '100%';
|
|
|
|
if (state.isFocused) {
|
|
styles.floatingLabel.color = focusColor;
|
|
}
|
|
|
|
if (props.floatingLabelText) {
|
|
styles.input.boxSizing = 'border-box';
|
|
|
|
if (!props.multiLine) {
|
|
styles.input.marginTop = 14;
|
|
}
|
|
|
|
if (state.errorText) {
|
|
styles.error.bottom = !props.multiLine ? styles.error.fontSize + 3 : 3;
|
|
}
|
|
}
|
|
|
|
if (state.errorText) {
|
|
if (state.isFocused) {
|
|
styles.floatingLabel.color = styles.error.color;
|
|
}
|
|
}
|
|
|
|
return styles;
|
|
};
|
|
|
|
/**
|
|
* 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 value !== '' && value !== undefined && value !== null;
|
|
}
|
|
|
|
var TextField = function (_Component) {
|
|
(0, _inherits3.default)(TextField, _Component);
|
|
|
|
function TextField() {
|
|
var _ref;
|
|
|
|
var _temp, _this, _ret;
|
|
|
|
(0, _classCallCheck3.default)(this, TextField);
|
|
|
|
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
|
args[_key] = arguments[_key];
|
|
}
|
|
|
|
return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = TextField.__proto__ || (0, _getPrototypeOf2.default)(TextField)).call.apply(_ref, [this].concat(args))), _this), _this.state = {
|
|
isFocused: false,
|
|
errorText: undefined,
|
|
hasValue: false
|
|
}, _this.handleInputBlur = function (event) {
|
|
_this.setState({ isFocused: false });
|
|
if (_this.props.onBlur) {
|
|
_this.props.onBlur(event);
|
|
}
|
|
}, _this.handleInputChange = function (event) {
|
|
_this.setState({ hasValue: isValid(event.target.value) });
|
|
if (_this.props.onChange) {
|
|
_this.props.onChange(event, event.target.value);
|
|
}
|
|
}, _this.handleInputFocus = function (event) {
|
|
if (_this.props.disabled) {
|
|
return;
|
|
}
|
|
_this.setState({ isFocused: true });
|
|
if (_this.props.onFocus) {
|
|
_this.props.onFocus(event);
|
|
}
|
|
}, _this.handleHeightChange = function (event, height) {
|
|
var newHeight = height + 24;
|
|
if (_this.props.floatingLabelText) {
|
|
newHeight += 24;
|
|
}
|
|
_reactDom2.default.findDOMNode(_this).style.height = newHeight + 'px';
|
|
}, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret);
|
|
}
|
|
|
|
(0, _createClass3.default)(TextField, [{
|
|
key: 'componentWillMount',
|
|
value: function componentWillMount() {
|
|
var _props = this.props,
|
|
children = _props.children,
|
|
name = _props.name,
|
|
hintText = _props.hintText,
|
|
floatingLabelText = _props.floatingLabelText,
|
|
id = _props.id;
|
|
|
|
|
|
var propsLeaf = children ? children.props : this.props;
|
|
|
|
this.setState({
|
|
errorText: this.props.errorText,
|
|
hasValue: isValid(propsLeaf.value) || isValid(propsLeaf.defaultValue)
|
|
});
|
|
|
|
process.env.NODE_ENV !== "production" ? (0, _warning2.default)(name || hintText || floatingLabelText || id, 'Material-UI: We don\'t have enough information\n to build a robust unique id for the TextField component. Please provide an id or a name.') : void 0;
|
|
|
|
var uniqueId = name + '-' + hintText + '-' + floatingLabelText + '-' + Math.floor(Math.random() * 0xFFFF);
|
|
this.uniqueId = uniqueId.replace(/[^A-Za-z0-9-]/gi, '');
|
|
}
|
|
}, {
|
|
key: 'componentWillReceiveProps',
|
|
value: function componentWillReceiveProps(nextProps) {
|
|
if (nextProps.errorText !== this.props.errorText) {
|
|
this.setState({
|
|
errorText: nextProps.errorText
|
|
});
|
|
}
|
|
|
|
if (nextProps.children && nextProps.children.props) {
|
|
nextProps = nextProps.children.props;
|
|
}
|
|
|
|
if (nextProps.hasOwnProperty('value')) {
|
|
var hasValue = isValid(nextProps.value);
|
|
|
|
this.setState({
|
|
hasValue: hasValue
|
|
});
|
|
}
|
|
}
|
|
}, {
|
|
key: 'shouldComponentUpdate',
|
|
value: function shouldComponentUpdate(nextProps, nextState, nextContext) {
|
|
return !(0, _shallowEqual2.default)(this.props, nextProps) || !(0, _shallowEqual2.default)(this.state, nextState) || !(0, _shallowEqual2.default)(this.context, nextContext);
|
|
}
|
|
}, {
|
|
key: 'blur',
|
|
value: function blur() {
|
|
if (this.input) {
|
|
this.getInputNode().blur();
|
|
}
|
|
}
|
|
}, {
|
|
key: 'focus',
|
|
value: function focus() {
|
|
if (this.input) {
|
|
this.getInputNode().focus();
|
|
}
|
|
}
|
|
}, {
|
|
key: 'select',
|
|
value: function select() {
|
|
if (this.input) {
|
|
this.getInputNode().select();
|
|
}
|
|
}
|
|
}, {
|
|
key: 'getValue',
|
|
value: function getValue() {
|
|
return this.input ? this.getInputNode().value : undefined;
|
|
}
|
|
}, {
|
|
key: 'getInputNode',
|
|
value: function getInputNode() {
|
|
return this.props.children || this.props.multiLine ? this.input.getInputNode() : _reactDom2.default.findDOMNode(this.input);
|
|
}
|
|
}, {
|
|
key: '_isControlled',
|
|
value: function _isControlled() {
|
|
return this.props.hasOwnProperty('value');
|
|
}
|
|
}, {
|
|
key: 'render',
|
|
value: function render() {
|
|
var _this2 = this;
|
|
|
|
var _props2 = this.props,
|
|
children = _props2.children,
|
|
className = _props2.className,
|
|
disabled = _props2.disabled,
|
|
errorStyle = _props2.errorStyle,
|
|
errorText = _props2.errorText,
|
|
floatingLabelFixed = _props2.floatingLabelFixed,
|
|
floatingLabelFocusStyle = _props2.floatingLabelFocusStyle,
|
|
floatingLabelShrinkStyle = _props2.floatingLabelShrinkStyle,
|
|
floatingLabelStyle = _props2.floatingLabelStyle,
|
|
floatingLabelText = _props2.floatingLabelText,
|
|
fullWidth = _props2.fullWidth,
|
|
hintText = _props2.hintText,
|
|
hintStyle = _props2.hintStyle,
|
|
id = _props2.id,
|
|
inputStyle = _props2.inputStyle,
|
|
multiLine = _props2.multiLine,
|
|
onBlur = _props2.onBlur,
|
|
onChange = _props2.onChange,
|
|
onFocus = _props2.onFocus,
|
|
style = _props2.style,
|
|
type = _props2.type,
|
|
underlineDisabledStyle = _props2.underlineDisabledStyle,
|
|
underlineFocusStyle = _props2.underlineFocusStyle,
|
|
underlineShow = _props2.underlineShow,
|
|
underlineStyle = _props2.underlineStyle,
|
|
rows = _props2.rows,
|
|
rowsMax = _props2.rowsMax,
|
|
textareaStyle = _props2.textareaStyle,
|
|
other = (0, _objectWithoutProperties3.default)(_props2, ['children', 'className', 'disabled', 'errorStyle', 'errorText', 'floatingLabelFixed', 'floatingLabelFocusStyle', 'floatingLabelShrinkStyle', 'floatingLabelStyle', 'floatingLabelText', 'fullWidth', 'hintText', 'hintStyle', 'id', 'inputStyle', 'multiLine', 'onBlur', 'onChange', 'onFocus', 'style', 'type', 'underlineDisabledStyle', 'underlineFocusStyle', 'underlineShow', 'underlineStyle', 'rows', 'rowsMax', 'textareaStyle']);
|
|
var prepareStyles = this.context.muiTheme.prepareStyles;
|
|
|
|
var styles = getStyles(this.props, this.context, this.state);
|
|
var inputId = id || this.uniqueId;
|
|
|
|
var errorTextElement = this.state.errorText && _react2.default.createElement(
|
|
'div',
|
|
{ style: prepareStyles((0, _simpleAssign2.default)(styles.error, errorStyle)) },
|
|
this.state.errorText
|
|
);
|
|
|
|
var floatingLabelTextElement = floatingLabelText && _react2.default.createElement(
|
|
_TextFieldLabel2.default,
|
|
{
|
|
muiTheme: this.context.muiTheme,
|
|
style: (0, _simpleAssign2.default)(styles.floatingLabel, floatingLabelStyle, this.state.isFocused ? floatingLabelFocusStyle : null),
|
|
shrinkStyle: floatingLabelShrinkStyle,
|
|
htmlFor: inputId,
|
|
shrink: this.state.hasValue || this.state.isFocused || floatingLabelFixed,
|
|
disabled: disabled
|
|
},
|
|
floatingLabelText
|
|
);
|
|
|
|
var inputProps = {
|
|
id: inputId,
|
|
ref: function ref(elem) {
|
|
return _this2.input = elem;
|
|
},
|
|
disabled: this.props.disabled,
|
|
onBlur: this.handleInputBlur,
|
|
onChange: this.handleInputChange,
|
|
onFocus: this.handleInputFocus
|
|
};
|
|
|
|
var childStyleMerged = (0, _simpleAssign2.default)(styles.input, inputStyle);
|
|
|
|
var inputElement = void 0;
|
|
if (children) {
|
|
inputElement = _react2.default.cloneElement(children, (0, _extends3.default)({}, inputProps, children.props, {
|
|
style: (0, _simpleAssign2.default)(childStyleMerged, children.props.style)
|
|
}));
|
|
} else {
|
|
inputElement = multiLine ? _react2.default.createElement(_EnhancedTextarea2.default, (0, _extends3.default)({
|
|
style: childStyleMerged,
|
|
textareaStyle: (0, _simpleAssign2.default)(styles.textarea, styles.inputNative, textareaStyle),
|
|
rows: rows,
|
|
rowsMax: rowsMax
|
|
}, other, inputProps, {
|
|
onHeightChange: this.handleHeightChange
|
|
})) : _react2.default.createElement('input', (0, _extends3.default)({
|
|
type: type,
|
|
style: prepareStyles((0, _simpleAssign2.default)(styles.inputNative, childStyleMerged))
|
|
}, other, inputProps));
|
|
}
|
|
|
|
var rootProps = {};
|
|
|
|
if (children) {
|
|
rootProps = other;
|
|
}
|
|
|
|
return _react2.default.createElement(
|
|
'div',
|
|
(0, _extends3.default)({}, rootProps, {
|
|
className: className,
|
|
style: prepareStyles((0, _simpleAssign2.default)(styles.root, style))
|
|
}),
|
|
floatingLabelTextElement,
|
|
hintText ? _react2.default.createElement(_TextFieldHint2.default, {
|
|
muiTheme: this.context.muiTheme,
|
|
show: !(this.state.hasValue || floatingLabelText && !this.state.isFocused) || !this.state.hasValue && floatingLabelText && floatingLabelFixed && !this.state.isFocused,
|
|
style: hintStyle,
|
|
text: hintText
|
|
}) : null,
|
|
inputElement,
|
|
underlineShow ? _react2.default.createElement(_TextFieldUnderline2.default, {
|
|
disabled: disabled,
|
|
disabledStyle: underlineDisabledStyle,
|
|
error: !!this.state.errorText,
|
|
errorStyle: errorStyle,
|
|
focus: this.state.isFocused,
|
|
focusStyle: underlineFocusStyle,
|
|
muiTheme: this.context.muiTheme,
|
|
style: underlineStyle
|
|
}) : null,
|
|
errorTextElement
|
|
);
|
|
}
|
|
}]);
|
|
return TextField;
|
|
}(_react.Component);
|
|
|
|
TextField.defaultProps = {
|
|
disabled: false,
|
|
floatingLabelFixed: false,
|
|
multiLine: false,
|
|
fullWidth: false,
|
|
type: 'text',
|
|
underlineShow: true,
|
|
rows: 1
|
|
};
|
|
TextField.contextTypes = {
|
|
muiTheme: _react.PropTypes.object.isRequired
|
|
};
|
|
process.env.NODE_ENV !== "production" ? TextField.propTypes = {
|
|
children: _react.PropTypes.node,
|
|
/**
|
|
* The css class name of the root element.
|
|
*/
|
|
className: _react.PropTypes.string,
|
|
/**
|
|
* The text string to use for the default value.
|
|
*/
|
|
defaultValue: _react.PropTypes.any,
|
|
/**
|
|
* Disables the text field if set to true.
|
|
*/
|
|
disabled: _react.PropTypes.bool,
|
|
/**
|
|
* The style object to use to override error styles.
|
|
*/
|
|
errorStyle: _react.PropTypes.object,
|
|
/**
|
|
* The error content to display.
|
|
*/
|
|
errorText: _react.PropTypes.node,
|
|
/**
|
|
* If true, the floating label will float even when there is no value.
|
|
*/
|
|
floatingLabelFixed: _react.PropTypes.bool,
|
|
/**
|
|
* The style object to use to override floating label styles when focused.
|
|
*/
|
|
floatingLabelFocusStyle: _react.PropTypes.object,
|
|
/**
|
|
* The style object to use to override floating label styles when shrunk.
|
|
*/
|
|
floatingLabelShrinkStyle: _react.PropTypes.object,
|
|
/**
|
|
* The style object to use to override floating label styles.
|
|
*/
|
|
floatingLabelStyle: _react.PropTypes.object,
|
|
/**
|
|
* The content to use for the floating label element.
|
|
*/
|
|
floatingLabelText: _react.PropTypes.node,
|
|
/**
|
|
* If true, the field receives the property width 100%.
|
|
*/
|
|
fullWidth: _react.PropTypes.bool,
|
|
/**
|
|
* Override the inline-styles of the TextField's hint text element.
|
|
*/
|
|
hintStyle: _react.PropTypes.object,
|
|
/**
|
|
* The hint content to display.
|
|
*/
|
|
hintText: _react.PropTypes.node,
|
|
/**
|
|
* The id prop for the text field.
|
|
*/
|
|
id: _react.PropTypes.string,
|
|
/**
|
|
* Override the inline-styles of the TextField's input element.
|
|
* When multiLine is false: define the style of the input element.
|
|
* When multiLine is true: define the style of the container of the textarea.
|
|
*/
|
|
inputStyle: _react.PropTypes.object,
|
|
/**
|
|
* If true, a textarea element will be rendered.
|
|
* The textarea also grows and shrinks according to the number of lines.
|
|
*/
|
|
multiLine: _react.PropTypes.bool,
|
|
/**
|
|
* Name applied to the input.
|
|
*/
|
|
name: _react.PropTypes.string,
|
|
/** @ignore */
|
|
onBlur: _react.PropTypes.func,
|
|
/**
|
|
* Callback function that is fired when the textfield's value changes.
|
|
*
|
|
* @param {object} event Change event targeting the text field.
|
|
* @param {string} newValue The new value of the text field.
|
|
*/
|
|
onChange: _react.PropTypes.func,
|
|
/** @ignore */
|
|
onFocus: _react.PropTypes.func,
|
|
/**
|
|
* Number of rows to display when multiLine option is set to true.
|
|
*/
|
|
rows: _react.PropTypes.number,
|
|
/**
|
|
* Maximum number of rows to display when
|
|
* multiLine option is set to true.
|
|
*/
|
|
rowsMax: _react.PropTypes.number,
|
|
/**
|
|
* Override the inline-styles of the root element.
|
|
*/
|
|
style: _react.PropTypes.object,
|
|
/**
|
|
* Override the inline-styles of the TextField's textarea element.
|
|
* The TextField use either a textarea or an input,
|
|
* this property has effects only when multiLine is true.
|
|
*/
|
|
textareaStyle: _react.PropTypes.object,
|
|
/**
|
|
* Specifies the type of input to display
|
|
* such as "password" or "text".
|
|
*/
|
|
type: _react.PropTypes.string,
|
|
/**
|
|
* Override the inline-styles of the
|
|
* TextField's underline element when disabled.
|
|
*/
|
|
underlineDisabledStyle: _react.PropTypes.object,
|
|
/**
|
|
* Override the inline-styles of the TextField's
|
|
* underline element when focussed.
|
|
*/
|
|
underlineFocusStyle: _react.PropTypes.object,
|
|
/**
|
|
* If true, shows the underline for the text field.
|
|
*/
|
|
underlineShow: _react.PropTypes.bool,
|
|
/**
|
|
* Override the inline-styles of the TextField's underline element.
|
|
*/
|
|
underlineStyle: _react.PropTypes.object,
|
|
/**
|
|
* The value of the text field.
|
|
*/
|
|
value: _react.PropTypes.any
|
|
} : void 0;
|
|
exports.default = TextField; |