UNPKG

rn-material-ui-textfield

Version:
736 lines (637 loc) 18.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _deprecatedReactNativePropTypes = require("deprecated-react-native-prop-types"); var _line = _interopRequireDefault(require("../line")); var _label = _interopRequireDefault(require("../label")); var _affix = _interopRequireDefault(require("../affix")); var _helper = _interopRequireDefault(require("../helper")); var _counter = _interopRequireDefault(require("../counter")); var _styles = _interopRequireDefault(require("./styles")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign ? Object.assign.bind() : 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; }; return _extends.apply(this, arguments); } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function startAnimation(animation, options, callback) { _reactNative.Animated.timing(animation, options).start(callback); } function labelStateFromProps(props, state) { let { placeholder, defaultValue } = props; let { value, receivedFocus } = state; return !!(placeholder || value || !receivedFocus && defaultValue); } function errorStateFromProps(props, state) { let { error } = props; return !!error; } class TextField extends _react.PureComponent { static getDerivedStateFromProps(_ref, state) { let { error, value } = _ref; let newState = {}; /* Keep last received error in state */ if (error && error !== state.error) { newState.error = error; } if (value !== undefined && value !== state.value) { newState.value = value; } return newState; } constructor(props) { super(props); this.onBlur = this.onBlur.bind(this); this.onFocus = this.onFocus.bind(this); this.onPress = this.focus.bind(this); this.onChange = this.onChange.bind(this); this.onChangeText = this.onChangeText.bind(this); this.onContentSizeChange = this.onContentSizeChange.bind(this); this.onFocusAnimationEnd = this.onFocusAnimationEnd.bind(this); this.createGetter('contentInset'); this.createGetter('labelOffset'); this.inputRef = this.props.inputRef ?? /*#__PURE__*/_react.default.createRef(); this.mounted = false; this.focused = false; let { value, error, fontSize } = this.props; let labelState = labelStateFromProps(this.props, { value }) ? 1 : 0; let focusState = errorStateFromProps(this.props) ? -1 : 0; this.state = { value, error, focusAnimation: new _reactNative.Animated.Value(focusState), labelAnimation: new _reactNative.Animated.Value(labelState), receivedFocus: false, height: fontSize * 1.5 }; } createGetter(name) { this[name] = () => { let { [name]: value } = this.props; let { [name]: defaultValue } = this.constructor; return { ...defaultValue, ...value }; }; } componentDidMount() { this.mounted = true; } componentWillUnmount() { this.mounted = false; } componentDidUpdate(prevProps, prevState) { let errorState = errorStateFromProps(this.props); let prevErrorState = errorStateFromProps(prevProps); if (errorState ^ prevErrorState) { this.startFocusAnimation(); } let labelState = labelStateFromProps(this.props, this.state); let prevLabelState = labelStateFromProps(prevProps, prevState); if (labelState ^ prevLabelState) { this.startLabelAnimation(); } } startFocusAnimation() { let { focusAnimation } = this.state; let { animationDuration: duration } = this.props; let options = { toValue: this.focusState(), duration, useNativeDriver: false }; startAnimation(focusAnimation, options, this.onFocusAnimationEnd); } startLabelAnimation() { let { labelAnimation } = this.state; let { animationDuration: duration } = this.props; let options = { toValue: this.labelState(), useNativeDriver: true, duration }; startAnimation(labelAnimation, options); } setNativeProps(props) { let { current: input } = this.inputRef; input.setNativeProps(props); } focusState() { if (errorStateFromProps(this.props)) { return -1; } return this.focused ? 1 : 0; } labelState() { if (labelStateFromProps(this.props, this.state)) { return 1; } return this.focused ? 1 : 0; } focus() { let { disabled, editable } = this.props; let { current: input } = this.inputRef; if (!disabled && editable) { input.focus(); } } blur() { let { current: input } = this.inputRef; input.blur(); } clear() { let { current: input } = this.inputRef; input.clear(); /* onChangeText is not triggered by .clear() */ this.onChangeText(''); } value() { const { defaultValue } = this.props; const value = this.isDefaultVisible() ? defaultValue : this.state.value; if (value == null) { return ''; } return typeof value === 'string' ? value : String(value); } setValue(value) { this.setState({ value }); } isFocused() { let { current: input } = this.inputRef; return input.isFocused(); } isRestricted() { let { characterRestriction: limit } = this.props; let { length: count } = this.value(); return limit < count; } isErrored() { return errorStateFromProps(this.props); } isDefaultVisible() { let { value, receivedFocus } = this.state; let { defaultValue } = this.props; return !receivedFocus && value == null && defaultValue != null; } isPlaceholderVisible() { let { placeholder } = this.props; return placeholder && !this.focused && !this.value(); } isLabelActive() { return this.labelState() === 1; } onFocus(event) { let { onFocus, clearTextOnFocus } = this.props; let { receivedFocus } = this.state; if (typeof onFocus === 'function') { onFocus(event); } if (clearTextOnFocus) { this.clear(); } this.focused = true; this.startFocusAnimation(); this.startLabelAnimation(); if (!receivedFocus) { this.setState({ receivedFocus: true, value: this.value() }); } } onBlur(event) { let { onBlur } = this.props; if (typeof onBlur === 'function') { onBlur(event); } this.focused = false; this.startFocusAnimation(); this.startLabelAnimation(); } onChange(event) { let { onChange } = this.props; if (typeof onChange === 'function') { onChange(event); } } onChangeText(text) { let { onChangeText, formatText } = this.props; if (typeof formatText === 'function') { text = formatText(text); } this.setState({ value: text }); if (typeof onChangeText === 'function') { onChangeText(text); } } onContentSizeChange(event) { let { onContentSizeChange, fontSize } = this.props; let { height } = event.nativeEvent.contentSize; if (typeof onContentSizeChange === 'function') { onContentSizeChange(event); } this.setState({ height: Math.max(fontSize * 1.5, Math.ceil(height) + _reactNative.Platform.select({ ios: 4, android: 1 })) }); } onFocusAnimationEnd() { let { error } = this.props; let { error: retainedError } = this.state; if (this.mounted && !error && retainedError) { this.setState({ error: null }); } } inputHeight() { let { height: computedHeight } = this.state; let { multiline, fontSize, height = computedHeight } = this.props; return multiline ? height : fontSize * 1.5; } inputContainerHeight() { let { labelFontSize, multiline } = this.props; let contentInset = this.contentInset(); if (_reactNative.Platform.OS === 'web' && multiline) { return 'auto'; } return contentInset.top + labelFontSize + contentInset.label + this.inputHeight() + contentInset.input; } inputProps() { let store = {}; for (let key in _deprecatedReactNativePropTypes.TextInputPropTypes) { if (key === 'defaultValue') { continue; } if (key in this.props) { store[key] = this.props[key]; } } return store; } inputStyle() { let { fontSize, baseColor, textColor, disabled, multiline } = this.props; let color = disabled || this.isDefaultVisible() ? baseColor : textColor; let style = { fontSize, color, height: this.inputHeight() }; if (multiline) { let lineHeight = fontSize * 1.5; let offset = _reactNative.Platform.OS === 'ios' ? 2 : 0; style.height += lineHeight; style.transform = [{ translateY: lineHeight + offset }]; } return style; } renderLabel(props) { let offset = this.labelOffset(); let { label, fontSize, labelFontSize, labelTextStyle } = this.props; return /*#__PURE__*/_react.default.createElement(_label.default, _extends({}, props, { fontSize: fontSize, activeFontSize: labelFontSize, offset: offset, label: label, style: labelTextStyle })); } renderLine(props) { return /*#__PURE__*/_react.default.createElement(_line.default, props); } renderAccessory(prop) { let { [prop]: renderAccessory } = this.props; return typeof renderAccessory === 'function' ? renderAccessory() : null; } renderAffix(type) { let { labelAnimation } = this.state; let { [type]: affix, fontSize, baseColor: color, affixTextStyle: style } = this.props; if (affix == null) { return null; } let props = { type, style, color, fontSize, labelAnimation }; return /*#__PURE__*/_react.default.createElement(_affix.default, props, affix); } renderHelper() { let { focusAnimation, error } = this.state; let { title, disabled, baseColor, errorColor, titleTextStyle: style, characterRestriction: limit } = this.props; let { length: count } = this.value(); let contentInset = this.contentInset(); let containerStyle = { paddingLeft: contentInset.left, paddingRight: contentInset.right, minHeight: contentInset.bottom }; let styleProps = { style, baseColor, errorColor }; let counterProps = { ...styleProps, limit, count }; let helperProps = { ...styleProps, title, error, disabled, focusAnimation }; return /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: [_styles.default.helperContainer, containerStyle] }, /*#__PURE__*/_react.default.createElement(_helper.default, helperProps), /*#__PURE__*/_react.default.createElement(_counter.default, counterProps)); } renderInput() { let { disabled, editable, tintColor, style: inputStyleOverrides } = this.props; let props = this.inputProps(); let inputStyle = this.inputStyle(); return /*#__PURE__*/_react.default.createElement(_reactNative.TextInput, _extends({ selectionColor: tintColor }, props, { style: [_styles.default.input, inputStyle, inputStyleOverrides], editable: !disabled && editable, onChange: this.onChange, onChangeText: this.onChangeText, onContentSizeChange: this.onContentSizeChange, onFocus: this.onFocus, onBlur: this.onBlur, value: this.value(), ref: this.inputRef })); } render() { let { labelAnimation, focusAnimation } = this.state; let { editable, disabled, lineType, disabledLineType, lineWidth, activeLineWidth, disabledLineWidth, tintColor, baseColor, errorColor, containerStyle, inputContainerStyle: inputContainerStyleOverrides } = this.props; let restricted = this.isRestricted(); let contentInset = this.contentInset(); let inputContainerStyle = { paddingTop: contentInset.top, paddingRight: contentInset.right, paddingBottom: contentInset.input, paddingLeft: contentInset.left, height: this.inputContainerHeight() }; let containerProps = { style: containerStyle, onStartShouldSetResponder: () => true, onResponderRelease: this.onPress, pointerEvents: !disabled ? 'auto' : 'none' }; let inputContainerProps = { style: [this.constructor.inputContainerStyle, inputContainerStyle, inputContainerStyleOverrides] }; let styleProps = { disabled, restricted, baseColor, tintColor, errorColor, contentInset, focusAnimation, labelAnimation }; let lineProps = { ...styleProps, lineWidth, activeLineWidth, disabledLineWidth, lineType, disabledLineType }; return /*#__PURE__*/_react.default.createElement(_reactNative.View, containerProps, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, inputContainerProps, this.renderLine(lineProps), this.renderAccessory('renderLeftAccessory'), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: _styles.default.stack, pointerEvents: editable ? 'auto' : 'none' }, this.renderLabel(styleProps), /*#__PURE__*/_react.default.createElement(_reactNative.View, { style: _styles.default.row }, this.renderAffix('prefix'), this.renderInput(), this.renderAffix('suffix'))), this.renderAccessory('renderRightAccessory')), this.renderHelper()); } } exports.default = TextField; _defineProperty(TextField, "defaultProps", { underlineColorAndroid: 'transparent', disableFullscreenUI: true, autoCapitalize: 'sentences', editable: true, animationDuration: 225, fontSize: 16, labelFontSize: 12, tintColor: 'rgb(0, 145, 234)', textColor: 'rgba(0, 0, 0, .87)', baseColor: 'rgba(0, 0, 0, .38)', errorColor: 'rgb(213, 0, 0)', lineWidth: _reactNative.StyleSheet.hairlineWidth, activeLineWidth: 2, disabledLineWidth: 1, lineType: 'solid', disabledLineType: 'dotted', disabled: false }); _defineProperty(TextField, "propTypes", { ..._deprecatedReactNativePropTypes.TextInputPropTypes, animationDuration: _propTypes.default.number, fontSize: _propTypes.default.number, labelFontSize: _propTypes.default.number, contentInset: _propTypes.default.shape({ top: _propTypes.default.number, label: _propTypes.default.number, input: _propTypes.default.number, left: _propTypes.default.number, right: _propTypes.default.number, bottom: _propTypes.default.number }), labelOffset: _label.default.propTypes.offset, labelTextStyle: _deprecatedReactNativePropTypes.TextPropTypes.style, titleTextStyle: _deprecatedReactNativePropTypes.TextPropTypes.style, affixTextStyle: _deprecatedReactNativePropTypes.TextPropTypes.style, tintColor: _propTypes.default.string, textColor: _propTypes.default.string, baseColor: _propTypes.default.string, label: _propTypes.default.string, title: _propTypes.default.string, characterRestriction: _propTypes.default.number, error: _propTypes.default.string, errorColor: _propTypes.default.string, lineWidth: _propTypes.default.number, activeLineWidth: _propTypes.default.number, disabledLineWidth: _propTypes.default.number, lineType: _line.default.propTypes.lineType, disabledLineType: _line.default.propTypes.lineType, disabled: _propTypes.default.bool, formatText: _propTypes.default.func, renderLeftAccessory: _propTypes.default.func, renderRightAccessory: _propTypes.default.func, prefix: _propTypes.default.string, suffix: _propTypes.default.string, containerStyle: _deprecatedReactNativePropTypes.ViewPropTypes.style, inputContainerStyle: _deprecatedReactNativePropTypes.ViewPropTypes.style }); _defineProperty(TextField, "inputContainerStyle", _styles.default.inputContainer); _defineProperty(TextField, "contentInset", { top: 16, label: 4, input: 8, left: 0, right: 0, bottom: 8 }); _defineProperty(TextField, "labelOffset", { x0: 0, y0: 0, x1: 0, y1: 0 }); //# sourceMappingURL=index.js.map