react-native-reanimated#interpolateColors TypeScript Examples

The following examples show how to use react-native-reanimated#interpolateColors. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From react-native-floating-label-input with MIT License 4 votes vote down vote up
FloatingLabelInput: React.ForwardRefRenderFunction<InputRef, Props> = (
  {
    label,
    labelProps,
    mask,
    isPassword,
    maxLength,
    inputStyles,
    showCountdown,
    showCountdownStyles,
    labelStyles,
    darkTheme,
    countdownLabel,
    currencyDivider,
    currency,
    maskType,
    onChangeText,
    customHidePasswordComponent,
    customShowPasswordComponent,
    isFocused,
    onBlur,
    onFocus,
    onTogglePassword,
    togglePassword,
    leftComponent,
    rightComponent,
    customHidePasswordImage,
    customLabelStyles = {},
    staticLabel = false,
    hint,
    hintTextColor,
    onSubmit,
    containerStyles,
    customShowPasswordImage,
    showPasswordContainerStyles,
    maxDecimalPlaces,
    multiline,
    showPasswordImageStyles,
    value = '',
    animationDuration,
    ...rest
  }: Props,
  ref: any,
) => {
  const [halfTop, setHalfTop] = useState(0);
  const [isFocusedState, setIsFocused] = useState(false);
  const [secureText, setSecureText] = useState(true);
  const inputRef = useRef<any>(null);

  customLabelStyles = {
    fontSizeFocused: 10,
    fontSizeBlurred: 14,
    colorFocused: '#49658c',
    colorBlurred: '#49658c',
    ...setGlobalStyles?.customLabelStyles,
    ...customLabelStyles,
  };

  const [fontColorAnimated] = useState(new Animated.Value(0));

  const [fontSizeAnimated] = useState(
    new Animated.Value(
      isFocused
        ? customLabelStyles.fontSizeFocused
          ? customLabelStyles.fontSizeFocused
          : 10
        : customLabelStyles.fontSizeBlurred
        ? customLabelStyles.fontSizeBlurred
        : 14,
    ),
  );

  const [leftAnimated] = useState(
    new Animated.Value(
      staticLabel
        ? customLabelStyles?.leftFocused !== undefined
          ? customLabelStyles.leftFocused
          : 15
        : customLabelStyles != undefined &&
          customLabelStyles.leftBlurred !== undefined
        ? customLabelStyles.leftBlurred
        : 0,
    ),
  );

  const [topAnimated] = useState(
    new Animated.Value(
      staticLabel
        ? customLabelStyles?.topFocused !== undefined
          ? customLabelStyles.topFocused
          : 0
        : customLabelStyles.topBlurred
        ? customLabelStyles.topBlurred
        : 0,
    ),
  );

  useEffect(() => {
    if (isFocused === undefined) {
      if (value !== '' || isFocusedState) {
        setIsFocused(true);
      } else if (value === '' || value === null) {
        setIsFocused(false);
      }
    }
  }, [value]);

  useEffect(() => {
    if (isFocused !== undefined) {
      if (value !== '' || isFocused) {
        setIsFocused(true);
      } else {
        setIsFocused(false);
      }
    }
  }, [isFocused, value]);

  useEffect(() => {
    if (togglePassword !== undefined) {
      _toggleVisibility(togglePassword);
    }
  }, [togglePassword]);

  useEffect(() => {
    if (isFocusedState || value !== '') {
      if (halfTop !== 0) {
        animateFocus();
      }
    } else {
      animateBlur();
    }
  }, [isFocusedState, halfTop]);

  useImperativeHandle(ref, () => ({
    focus() {
      inputRef.current.focus();
    },
    blur() {
      inputRef.current.blur();
    },
  }));

  useEffect(() => {
    if (
      !staticLabel &&
      customLabelStyles.topFocused === undefined &&
      isFocusedState
    ) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftFocused
            ? customLabelStyles.leftFocused
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeFocused
            ? customLabelStyles.fontSizeFocused
            : 10,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topFocused
            ? customLabelStyles.topFocused
            : -halfTop +
              (isFocusedState
                ? customLabelStyles.fontSizeFocused
                  ? customLabelStyles.fontSizeFocused
                  : 10
                : customLabelStyles.fontSizeBlurred
                ? customLabelStyles.fontSizeBlurred
                : 14),
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 1,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else if (staticLabel && isFocusedState) {
      Animated.timing(fontColorAnimated, {
        toValue: 1,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }, [halfTop]);

  function animateFocus() {
    if (!staticLabel) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftFocused
            ? customLabelStyles.leftFocused
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeFocused
            ? customLabelStyles.fontSizeFocused
            : 10,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topFocused
            ? customLabelStyles.topFocused
            : -halfTop +
              (isFocusedState
                ? customLabelStyles.fontSizeFocused
                  ? customLabelStyles.fontSizeFocused
                  : 10
                : customLabelStyles.fontSizeBlurred
                ? customLabelStyles.fontSizeBlurred
                : 14),
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 1,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else {
      Animated.timing(fontColorAnimated, {
        toValue: 1,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }

  function animateBlur() {
    if (!staticLabel) {
      ReactAnimated.parallel([
        timing(leftAnimated, {
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
          toValue: customLabelStyles.leftBlurred
            ? customLabelStyles.leftBlurred
            : 0,
        }),
        timing(fontSizeAnimated, {
          toValue: customLabelStyles.fontSizeBlurred
            ? customLabelStyles.fontSizeBlurred
            : 14,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        timing(topAnimated, {
          toValue: customLabelStyles.topBlurred
            ? customLabelStyles.topBlurred
            : 0,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
        // @ts-ignore
        timing(fontColorAnimated, {
          toValue: 0,
          duration: animationDuration ? animationDuration : 300,
          easing: EasingNode.linear,
        }),
      ]).start();
    } else {
      Animated.timing(fontColorAnimated, {
        toValue: 0,
        duration: animationDuration ? animationDuration : 300,
        easing: EasingNode.linear,
      }).start();
    }
  }

  function handleFocus() {
    setIsFocused(true);
  }

  function handleBlur() {
    if (value === '') {
      setIsFocused(false);
    }
  }

  function setFocus() {
    inputRef.current?.focus();
  }

  function setBlur() {
    inputRef.current?.blur();
  }

  function _toggleVisibility(toggle?: boolean) {
    if (toggle === undefined) {
      if (onTogglePassword) {
        onTogglePassword(!secureText);
      }
      setSecureText(!secureText);
      secureText ? setFocus() : setBlur();
    } else {
      if (!((secureText && !toggle) || (!secureText && toggle))) {
        if (onTogglePassword) {
          onTogglePassword(!toggle);
        }
        setSecureText(!toggle);
        toggle ? setFocus() : setBlur();
      }
    }
  }

  function onSubmitEditing() {
    if (onSubmit !== undefined) {
      onSubmit();
    }
  }

  const imgSource = darkTheme
    ? secureText
      ? customShowPasswordImage || makeVisibleBlack
      : customHidePasswordImage || makeInvisibleBlack
    : secureText
    ? customShowPasswordImage || makeVisibleWhite
    : customHidePasswordImage || makeInvisibleWhite;

  const style: TextStyle = {
    ...setGlobalStyles?.labelStyles,
    ...labelStyles,
    left: labelStyles?.left !== undefined ? labelStyles?.left : 5,
    fontSize: staticLabel
      ? customLabelStyles?.fontSizeFocused !== undefined
        ? customLabelStyles.fontSizeFocused
        : 10
      : !isFocusedState
      ? customLabelStyles.fontSizeBlurred
      : customLabelStyles.fontSizeFocused,
    // @ts-ignore
    color: interpolateColors(fontColorAnimated, {
      inputRange: [0, 1],
      outputColorRange: [
        // @ts-ignore
        customLabelStyles.colorBlurred,
        // @ts-ignore
        customLabelStyles.colorFocused,
      ],
    }),
    alignSelf: 'center',
    position: 'absolute',
    flex: 1,
    zIndex: 999,
  };

  let input: TextStyle =
    inputStyles !== undefined
      ? inputStyles
      : setGlobalStyles?.inputStyles !== undefined
      ? setGlobalStyles.inputStyles
      : styles.input;

  input = {
    ...input,
    flex: 1,
    color:
      input.color !== undefined ? input.color : customLabelStyles.colorFocused,
    zIndex: style?.zIndex !== undefined ? style.zIndex - 2 : 0,
  };

  containerStyles =
    containerStyles !== undefined
      ? containerStyles
      : setGlobalStyles?.containerStyles !== undefined
      ? setGlobalStyles?.containerStyles
      : styles.container;

  containerStyles = {
    ...containerStyles,
    alignItems: 'center',
    flexDirection: 'row',
    flex: 1,
    zIndex: style?.zIndex !== undefined ? style.zIndex - 6 : 0,
  };

  let toggleButton =
    showPasswordContainerStyles !== undefined
      ? showPasswordContainerStyles
      : setGlobalStyles?.showPasswordContainerStyles !== undefined
      ? setGlobalStyles.showPasswordContainerStyles
      : styles.toggleButton;

  toggleButton = {
    ...toggleButton,
    alignSelf: 'center',
  };

  let img =
    showPasswordImageStyles !== undefined
      ? showPasswordImageStyles
      : setGlobalStyles?.showPasswordImageStyles !== undefined
      ? setGlobalStyles.showPasswordImageStyles
      : styles.img;

  img = {
    height: 25,
    width: 25,
    ...img,
  };

  const countdown = {
    ...styles.countdown,
    ...setGlobalStyles?.showCountdownStyles,
    ...showCountdownStyles,
  };

  function onChangeTextCallback(val: string): void | undefined {
    if (onChangeText === undefined) return undefined;

    if (maskType === undefined && mask === undefined) return onChangeText(val);

    let newValue: string | undefined;

    if (maskType !== 'currency' && mask !== undefined) {
      newValue = getValueWithNonCurrencyMask({ value: val, mask });
    }

    if (maskType === 'currency') {
      if (
        currency !== undefined &&
        !/^[0-9]+$/g.test(val.replace(/[.,]/g, '').replace(currency, '')) &&
        val.replace(/[.,]/g, '').replace(currency, '') !== ''
      ) {
        return undefined;
      } else if (
        currency === undefined &&
        !/^[0-9]+$/g.test(val.replace(/[.,]/g, '')) &&
        val.replace(/[.,]/g, '') !== ''
      ) {
        return undefined;
      }

      newValue = getValueWithCurrencyMask({
        value: currency !== undefined ? value.replace(currency, '') : value,
        newValue: currency !== undefined ? val.replace(currency, '') : val,
        currencyDivider,
        maxDecimalPlaces,
      });
    }

    if (newValue !== undefined) {
      return onChangeText((currency !== undefined ? currency : '') + newValue);
    }
  }

  function onLayout(event: LayoutChangeEvent) {
    const { height } = event.nativeEvent.layout;
    setHalfTop(height / 2);
  }

  return (
    <TouchableWithoutFeedback onPress={setFocus} onLayout={onLayout}>
      <View style={{ flexDirection: 'row' }}>
        {staticLabel && (
          <AnimatedText
            {...labelProps}
            onPress={setFocus}
            style={[
              style,
              {
                left: labelStyles?.left
                  ? labelStyles?.left
                  : customLabelStyles.leftFocused
                  ? customLabelStyles.leftFocused
                  : 20,
                top: -(style?.fontSize ? style?.fontSize : 10) / 2,
              },
            ]}
          >
            {label}
          </AnimatedText>
        )}
        <View style={containerStyles}>
          {leftComponent && leftComponent}
          <View style={{ flex: 1, flexDirection: 'row' }}>
            {!staticLabel && (
              <AnimatedText
                {...labelProps}
                onPress={setFocus}
                style={[
                  style,
                  // @ts-ignore
                  {
                    fontSize: fontSizeAnimated,
                    transform: [
                      { translateX: leftAnimated },
                      { translateY: topAnimated },
                    ],
                  },
                ]}
              >
                {label}
              </AnimatedText>
            )}
            <TextInput
              value={value}
              onSubmitEditing={onSubmitEditing}
              secureTextEntry={
                isPassword !== undefined ? isPassword && secureText : false
              }
              onFocus={onFocus !== undefined ? onFocus : handleFocus}
              onBlur={onBlur !== undefined ? onBlur : handleBlur}
              ref={inputRef}
              {...rest}
              maxLength={
                mask !== undefined
                  ? mask.length
                  : maxLength !== undefined
                  ? maxLength
                  : undefined
              }
              placeholderTextColor={hintTextColor}
              placeholder={(staticLabel || isFocusedState) && hint ? hint : ''}
              multiline={multiline}
              onChangeText={onChangeTextCallback}
              style={input}
            />
            {rightComponent && rightComponent}
            {isPassword && (
              <TouchableOpacity
                style={toggleButton}
                onPress={() => _toggleVisibility()}
              >
                {secureText && customShowPasswordComponent !== undefined ? (
                  customShowPasswordComponent
                ) : !secureText && customHidePasswordComponent !== undefined ? (
                  customHidePasswordComponent
                ) : (
                  <Image source={imgSource} resizeMode="contain" style={img} />
                )}
              </TouchableOpacity>
            )}
          </View>
          {showCountdown && maxLength && (
            <Text style={countdown}>
              {maxLength - (value ? value.length : 0)} {countdownLabel}
            </Text>
          )}
        </View>
      </View>
    </TouchableWithoutFeedback>
  );
}