UNPKG

@wordpress/components

Version:
236 lines (209 loc) 6.02 kB
import { createElement } from "@wordpress/element"; /** * External dependencies */ import { AccessibilityInfo, View, TextInput, PixelRatio, AppState, Platform, Text, TouchableWithoutFeedback } from 'react-native'; /** * WordPress dependencies */ import { Component } from '@wordpress/element'; import { withPreferredColorScheme } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies */ import { toFixed, removeNonDigit } from '../utils'; import styles from './styles.scss'; import borderStyles from './borderStyles.scss'; const isIOS = Platform.OS === 'ios'; class RangeTextInput extends Component { constructor(props) { super(props); this.announceCurrentValue = this.announceCurrentValue.bind(this); this.onInputFocus = this.onInputFocus.bind(this); this.onInputBlur = this.onInputBlur.bind(this); this.handleChangePixelRatio = this.handleChangePixelRatio.bind(this); this.onSubmitEditing = this.onSubmitEditing.bind(this); this.onChangeText = this.onChangeText.bind(this); const { value, defaultValue, min, decimalNum } = props; const initialValue = toFixed(value || defaultValue || min, decimalNum); const fontScale = this.getFontScale(); this.state = { fontScale, inputValue: initialValue, controlValue: initialValue, hasFocus: false }; } componentDidMount() { AppState.addEventListener('change', this.handleChangePixelRatio); } componentWillUnmount() { AppState.removeEventListener('change', this.handleChangePixelRatio); clearTimeout(this.timeoutAnnounceValue); } componentDidUpdate(prevProps, prevState) { const { value } = this.props; const { hasFocus, inputValue } = this.state; if (prevProps.value !== value) { this.setState({ inputValue: value }); } if (prevState.hasFocus !== hasFocus) { const validValue = this.validateInput(inputValue); this.setState({ inputValue: validValue }); } if (!prevState.hasFocus && hasFocus) { this._valueTextInput.focus(); } } getFontScale() { return PixelRatio.getFontScale() < 1 ? 1 : PixelRatio.getFontScale(); } handleChangePixelRatio(nextAppState) { if (nextAppState === 'active') { this.setState({ fontScale: this.getFontScale() }); } } onInputFocus() { this.setState({ hasFocus: true }); } onInputBlur() { const { inputValue } = this.state; this.onChangeText(`${inputValue}`); this.setState({ hasFocus: false }); } validateInput(text) { const { min, max, decimalNum } = this.props; let result = min; if (!text) { return min; } if (typeof text === 'number') { result = Math.max(text, min); return max ? Math.min(result, max) : result; } result = Math.max(removeNonDigit(text, decimalNum), min); return max ? Math.min(result, max) : result; } updateValue(value) { const { onChange } = this.props; const validValue = this.validateInput(value); this.announceCurrentValue(`${validValue}`); onChange(validValue); } onChangeText(textValue) { const { decimalNum } = this.props; const inputValue = removeNonDigit(textValue, decimalNum); textValue = inputValue.replace(',', '.'); textValue = toFixed(textValue, decimalNum); const value = this.validateInput(textValue); this.setState({ inputValue, controlValue: value }); this.updateValue(value); } onSubmitEditing({ nativeEvent: { text } }) { const { decimalNum } = this.props; const { inputValue } = this.state; if (!isNaN(Number(text))) { text = toFixed(text.replace(',', '.'), decimalNum); const validValue = this.validateInput(text); if (inputValue !== validValue) { this.setState({ inputValue: validValue }); this.announceCurrentValue(`${validValue}`); this.props.onChange(validValue); } } } announceCurrentValue(value) { /* translators: %s: current cell value. */ const announcement = sprintf(__('Current value is %s'), value); AccessibilityInfo.announceForAccessibility(announcement); } render() { const { getStylesFromColorScheme, children, label } = this.props; const { fontScale, inputValue, hasFocus } = this.state; const textInputStyle = getStylesFromColorScheme(styles.textInput, styles.textInputDark); const verticalBorderStyle = getStylesFromColorScheme(styles.verticalBorder, styles.verticalBorderDark); const inputBorderStyles = [textInputStyle, borderStyles.borderStyle, hasFocus && borderStyles.isSelected]; const valueFinalStyle = [!isIOS ? inputBorderStyles : verticalBorderStyle, { width: 50 * fontScale }]; return createElement(TouchableWithoutFeedback, { onPress: this.onInputFocus, accessible: false }, createElement(View, { style: [styles.textInputContainer, isIOS && inputBorderStyles], accessible: false }, isIOS || hasFocus ? createElement(TextInput, { accessibilityLabel: label, ref: c => this._valueTextInput = c, style: valueFinalStyle, onChangeText: this.onChangeText, onSubmitEditing: this.onSubmitEditing, onFocus: this.onInputFocus, onBlur: this.onInputBlur, keyboardType: "numeric", returnKeyType: "done", numberOfLines: 1, defaultValue: `${inputValue}`, value: inputValue.toString(), pointerEvents: hasFocus ? 'auto' : 'none' }) : createElement(Text, { style: valueFinalStyle, numberOfLines: 1, ellipsizeMode: "clip" }, inputValue), children)); } } export default withPreferredColorScheme(RangeTextInput); //# sourceMappingURL=range-text-input.native.js.map