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); }
import * as React from "react";
import { Animated, TextInput as NativeTextInput } from "react-native";
import TextInputOutlined from "./TextInputOutlined";
import { withTheme } from "../../core/theming";
import color from "color";
// import TextInputCard from './TextInputCard';

import { DATE_MMDDYYYY_MASK, isInputValid } from "./helpers";
import formatWithMask from "./formatWithMask";
const BLUR_ANIMATION_DURATION = 180;
const FOCUS_ANIMATION_DURATION = 150;
/**
 * A component to allow users to input text.
 *
 *
 * ## Usage
 * ```js
 * import * as React from 'react';
 * import { TextInput } from 'react-native-paper';
 *
 * const MyComponent = () => {
 *   const [text, setText] = React.useState("");
 *
 *   return (
 *     <TextInput
 *       label="Email"
 *       value={text}
 *       onChangeText={text => setText(text)}
 *     />
 *   );
 * };
 *
 * export default MyComponent;
 * ```
 *
 * @extends TextInput props https://reactnative.dev/docs/textinput#props
 */

const TextInput = /*#__PURE__*/React.forwardRef((_ref, ref) => {
  let {
    dense = false,
    disabled = false,
    error: errorMessage = "Invalid Input",
    multiline = false,
    editable = true,
    render = props => /*#__PURE__*/React.createElement(NativeTextInput, props),
    type = "text",
    validateOnBlur = true,
    validation,
    ...rest
  } = _ref;
  const isControlled = rest.value !== undefined;
  const validInputValue = isControlled ? rest.value : rest.defaultValue;
  const [isInvalid, setIsInvalid] = React.useState(false);
  const {
    current: labeled
  } = React.useRef(new Animated.Value(validInputValue ? 0 : 1));
  const {
    current: error
  } = React.useRef(new Animated.Value(rest.isInvalid ?? isInvalid ? 1 : 0));
  const [focused, setFocused] = React.useState(false);
  const [placeholder, setPlaceholder] = React.useState("");
  const [uncontrolledValue, setUncontrolledValue] = React.useState(validInputValue);
  // Use value from props instead of local state when input is controlled
  const value = isControlled ? rest.value : uncontrolledValue;
  const [labelLayout, setLabelLayout] = React.useState({
    measured: false,
    width: 0,
    height: 0
  });
  const [leftLayout, setLeftLayout] = React.useState({
    width: null,
    height: null
  });
  const [rightLayout, setRightLayout] = React.useState({
    width: null,
    height: null
  });
  const timer = React.useRef();
  const root = React.useRef();
  const {
    scale
  } = rest.theme.animation;
  React.useImperativeHandle(ref, () => ({
    focus: () => {
      var _root$current;
      return (_root$current = root.current) === null || _root$current === void 0 ? void 0 : _root$current.focus();
    },
    clear: () => {
      var _root$current2;
      return (_root$current2 = root.current) === null || _root$current2 === void 0 ? void 0 : _root$current2.clear();
    },
    setNativeProps: args => {
      var _root$current3;
      return (_root$current3 = root.current) === null || _root$current3 === void 0 ? void 0 : _root$current3.setNativeProps(args);
    },
    isFocused: () => {
      var _root$current4;
      return ((_root$current4 = root.current) === null || _root$current4 === void 0 ? void 0 : _root$current4.isFocused()) || false;
    },
    blur: () => {
      var _root$current5;
      return (_root$current5 = root.current) === null || _root$current5 === void 0 ? void 0 : _root$current5.blur();
    },
    forceFocus: () => {
      var _root$current6;
      return (_root$current6 = root.current) === null || _root$current6 === void 0 ? void 0 : _root$current6.focus();
    }
  }));
  React.useEffect(() => {
    // When the input has an error, we wiggle the label and apply error styles
    if (rest.isInvalid ?? isInvalid) {
      // show error
      Animated.timing(error, {
        toValue: 1,
        duration: FOCUS_ANIMATION_DURATION * scale,
        // To prevent this - https://github.com/callstack/react-native-paper/issues/941
        useNativeDriver: true
      }).start();
    } else {
      // hide error

      {
        Animated.timing(error, {
          toValue: 0,
          duration: BLUR_ANIMATION_DURATION * scale,
          // To prevent this - https://github.com/callstack/react-native-paper/issues/941
          useNativeDriver: true
        }).start();
      }
    }
  }, [rest.isInvalid, isInvalid, scale, error]);
  React.useEffect(() => {
    // Show placeholder text only if the input is focused, or there's no label
    // We don't show placeholder if there's a label because the label acts as placeholder
    // When focused, the label moves up, so we can show a placeholder
    if (focused || !rest.label) {
      // Set the placeholder in a delay to offset the label animation
      // If we show it immediately, they'll overlap and look ugly
      timer.current = setTimeout(() => setPlaceholder(type === "date" ? "mm-dd-yyyy" : rest.placeholder), 50);
    } else {
      // hidePlaceholder
      setPlaceholder("");
    }
    return () => {
      if (timer.current) {
        clearTimeout(timer.current);
      }
    };
  }, [focused, rest.label, rest.placeholder]);
  React.useEffect(() => {
    // The label should be minimized if the text input is focused, or has text
    // In minimized mode, the label moves up and becomes small
    // workaround for animated regression for react native > 0.61
    // https://github.com/callstack/react-native-paper/pull/1440

    if (value || focused) {
      // minimize label
      Animated.timing(labeled, {
        toValue: 0,
        duration: BLUR_ANIMATION_DURATION * scale,
        // To prevent this - https://github.com/callstack/react-native-paper/issues/941
        useNativeDriver: true
      }).start();
    } else {
      // restore label
      {
        Animated.timing(labeled, {
          toValue: 1,
          duration: FOCUS_ANIMATION_DURATION * scale,
          // To prevent this - https://github.com/callstack/react-native-paper/issues/941
          useNativeDriver: true
        }).start();
      }
    }
  }, [focused, value, labeled, scale]);
  const onLeftAffixLayoutChange = event => {
    setLeftLayout({
      height: event.nativeEvent.layout.height,
      width: event.nativeEvent.layout.width
    });
  };
  const onRightAffixLayoutChange = event => {
    setRightLayout({
      width: event.nativeEvent.layout.width,
      height: event.nativeEvent.layout.height
    });
  };
  const handleFocus = args => {
    var _rest$onFocus;
    if (disabled || !editable) {
      return;
    }
    setFocused(true);
    rest.isInvalid === undefined && setIsInvalid(false); //Don't do anything if isInvalid is being passed by props. That means state is being handled outside the component.

    (_rest$onFocus = rest.onFocus) === null || _rest$onFocus === void 0 ? void 0 : _rest$onFocus.call(rest, args);
  };
  const handleBlur = args => {
    var _rest$onBlur;
    if (!editable) {
      return;
    }
    if (validateOnBlur && rest.isInvalid === undefined) {
      //Don't do anything if isInvalid is being passed by props. That means state is being handled outside the component.
      const isValid = isInputValid(value, validation);
      setIsInvalid(!isValid);
    }
    setFocused(false);
    (_rest$onBlur = rest.onBlur) === null || _rest$onBlur === void 0 ? void 0 : _rest$onBlur.call(rest, args);
  };
  const handleChangeText = value => {
    var _rest$onChangeText;
    let filteredValue = value;
    if (!editable || disabled) {
      return;
    }
    if (type === "date") {
      filteredValue = formatWithMask({
        text: value,
        mask: DATE_MMDDYYYY_MASK
      }).masked;
    }
    if (!isControlled) {
      // Keep track of value in local state when input is not controlled
      setUncontrolledValue(filteredValue);
    }
    (_rest$onChangeText = rest.onChangeText) === null || _rest$onChangeText === void 0 ? void 0 : _rest$onChangeText.call(rest, filteredValue);
  };
  const handleLayoutAnimatedText = e => {
    setLabelLayout({
      width: e.nativeEvent.layout.width,
      height: e.nativeEvent.layout.height,
      measured: true
    });
  };
  const forceFocus = () => {
    var _root$current7;
    return (_root$current7 = root.current) === null || _root$current7 === void 0 ? void 0 : _root$current7.focus();
  };
  const {
    maxFontSizeMultiplier = 1.5
  } = rest;
  return /*#__PURE__*/React.createElement(TextInputOutlined, _extends({
    outlineColor: color("#000").alpha(0).rgb().string(),
    dense: dense,
    disabled: disabled,
    error: rest.isInvalid ?? isInvalid,
    errorMessage: errorMessage,
    multiline: multiline,
    editable: editable,
    render: render
  }, rest, {
    value: value,
    parentState: {
      labeled,
      error,
      focused,
      placeholder,
      value,
      labelLayout,
      leftLayout,
      rightLayout
    },
    innerRef: ref => {
      root.current = ref;
    },
    onFocus: handleFocus,
    forceFocus: forceFocus,
    onBlur: handleBlur,
    onChangeText: handleChangeText,
    onLayoutAnimatedText: handleLayoutAnimatedText,
    onLeftAffixLayoutChange: onLeftAffixLayoutChange,
    onRightAffixLayoutChange: onRightAffixLayoutChange,
    maxFontSizeMultiplier: maxFontSizeMultiplier,
    style: [{
      fontWeight: "600"
    }, rest.style]
  }));
});
export default withTheme(TextInput);
//# sourceMappingURL=TextInput.js.map