sriram10/react-native-material-textfield-new

View on GitHub
src/components/label/index.js

Summary

Maintainability
A
0 mins
Test Coverage
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import { Animated } from 'react-native';

import styles from './styles';

export default class Label extends PureComponent {
  static defaultProps = {
    numberOfLines: 1,
    disabled: false,
    restricted: false,
  };

  static propTypes = {
    numberOfLines: PropTypes.number,

    disabled: PropTypes.bool,
    restricted: PropTypes.bool,

    fontSize: PropTypes.number.isRequired,
    activeFontSize: PropTypes.number.isRequired,

    baseColor: PropTypes.string.isRequired,
    tintColor: PropTypes.string.isRequired,
    errorColor: PropTypes.string.isRequired,

    focusAnimation: PropTypes
      .instanceOf(Animated.Value)
      .isRequired,

    labelAnimation: PropTypes
      .instanceOf(Animated.Value)
      .isRequired,

    contentInset: PropTypes.shape({
      label: PropTypes.number,
    }),

    offset: PropTypes.shape({
      x0: PropTypes.number,
      y0: PropTypes.number,
      x1: PropTypes.number,
      y1: PropTypes.number,
    }),

    style: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
    label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
  };

  render() {
    let {
      label,
      offset = {},
      disabled,
      restricted,
      fontSize,
      activeFontSize,
      contentInset,
      errorColor,
      baseColor,
      tintColor,
      style,
      focusAnimation,
      labelAnimation,
      ...props
    } = this.props;

    if (null == label) {
      return null;
    }

    let color = disabled?
      baseColor:
      restricted?
        errorColor:
        focusAnimation.interpolate({
          inputRange: [-1, 0, 1],
          outputRange: [errorColor, baseColor, tintColor],
        });

    let textStyle = {
      lineHeight: fontSize,
      fontSize,
      color,
    };

    let { x0 = 0, y0 = 0, x1 = 0, y1 = 0 } = offset;

    y0 += activeFontSize;
    y0 += contentInset.label;
    y0 += fontSize * 0.25;

    let xScaleCompensation = this.state?.layout?.width ?
      ((this.state.layout.width - this.state.layout.width * activeFontSize / fontSize) / 2) : 0;

    let containerStyle = {
      transform: [{
        translateX: labelAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: [x0, -(xScaleCompensation - x1)],
        }),
      }, {
        scale: labelAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: [1, activeFontSize / fontSize],
        }),
      }, {
        translateY: labelAnimation.interpolate({
          inputRange: [0, 1],
          outputRange: [y0, y1],
        }),
      }],
    };

    return (
      <Animated.View onLayout={(e) => { this.setState({ layout: e.nativeEvent.layout }) }} style={[styles.container, containerStyle]}>
        <Animated.Text style={[styles.text, textStyle, style]} {...props}>
          {label}
        </Animated.Text>
      </Animated.View>
    );
  }
}