convert to preact js functional component -"class InputElement extends React.Component {
  focused = false
  mounted = false
  previousSelection = null
  selectionDeferId = null
  saveSelectionLoopDeferId = null

  constructor(props) {
    super(props);

    const { mask, maskChar, formatChars, alwaysShowMask, beforeMaskedValueChange } = props;
    let { defaultValue, value } = props;

    this.maskOptions = parseMask(mask, maskChar, formatChars);

    if (defaultValue == null) {
      defaultValue = '';
    }
    if (value == null) {
      value = defaultValue;
    }

    let newValue = getStringValue(value);

    if (this.maskOptions.mask && (alwaysShowMask || newValue)) {
      newValue = formatValue(this.maskOptions, newValue);

      if (isFunction(beforeMaskedValueChange)) {
        let oldValue = props.value;
        if (props.value == null) {
          oldValue = defaultValue;
        }
        oldValue = getStringValue(oldValue);

        const modifiedValue = beforeMaskedValueChange(
          { value: newValue, selection: null },
          { value: oldValue, selection: null },
          null,
          this.getBeforeMaskedValueChangeConfig()
        );

        newValue = modifiedValue.value;
      }
    }

    this.value = newValue;
  }

  componentDidMount() {
    this.mounted = true;

    // workaround for react-test-renderer
    // https://github.com/sanniassin/react-input-mask/issues/147
    if (!this.getInputDOMNode()) {
      return;
    }

    this.isWindowsPhoneBrowser = isWindowsPhoneBrowser();

    if (this.maskOptions.mask && this.getInputValue() !== this.value) {
      this.setInputValue(this.value);
    }
  }

  componentDidUpdate() {
    const { previousSelection } = this;
    const { beforeMaskedValueChange, alwaysShowMask, mask, maskChar, formatChars } = this.props;
    const previousMaskOptions = this.maskOptions;
    const showEmpty = alwaysShowMask || this.isFocused();
    const hasValue = this.props.value != null;
    let newValue = hasValue
      ? getStringValue(this.props.value)
      : this.value;
    let cursorPosition = previousSelection
      ? previousSelection.start
      : null;

    this.maskOptions = parseMask(mask, maskChar, formatChars);

    if (!this.maskOptions.mask) {
      if (previousMaskOptions.mask) {
        this.stopSaveSelectionLoop();

        // render depends on this.maskOptions and this.value,
        // call forceUpdate to keep it in sync
        this.forceUpdate();
      }
      return;
    } else if (!previousMaskOptions.mask && this.isFocused()) {
      this.runSaveSelectionLoop();
    }

    const isMaskChanged = this.maskOptions.mask && this.maskOptions.mask !== previousMaskOptions.mask;

    if (!previousMaskOptions.mask && !hasValue) {
      newValue = this.getInputValue();
    }

    if (isMaskChanged || (this.maskOptions.mask && (newValue || showEmpty))) {
      newValue = formatValue(this.maskOptions, newValue);
    }

    if (isMaskChanged) {
      const filledLength = getFilledLength(this.maskOptions, newValue);
      if (cursorPosition === null || filledLength < cursorPosition) {
        if (isFilled(this.maskOptions, newValue)) {
          cursorPosition = filledLength;
        } else {
          cursorPosition = getRightEditablePosition(this.maskOptions, filledLength);
        }
      }
    }

    if (this.maskOptions.mask && isEmpty(this.maskOptions, newValue) && !showEmpty && (!hasValue || !this.props.value)) {
      newValue = '';
    }

    let newSelection = { start: cursorPosition, end: cursorPosition };

    if (isFunction(beforeMaskedValueChange)) {
      const modifiedValue = beforeMaskedValueChange(
        { value: newValue, selection: newSelection },
        { value: this.value, selection: this.previousSelection },
        null,
        this.getBeforeMaskedValueChangeConfig()
      );
      newValue = modifiedValue.value;
      newSelection = modifiedValue.selection;
    }

    this.value = newValue;
    const isValueChanged = this.getInputValue() !== this.value;

    // render depends on this.maskOptions and this.value,
    // call forceUpdate to keep it in sync
    if (isValueChanged) {
      this.setInputValue(this.value);
      this.forceUpdate();
    } else if (isMaskChanged) {
      this.forceUpdate();
    }

    let isSelectionChanged = false;
    if (newSelection.start != null && newSelection.end != null) {
      isSelectionChanged = !previousSelection
                           ||
                           previousSelection.start !== newSelection.start
                           ||
                           previousSelection.end !== newSelection.end;
    }

    if (isSelectionChanged || isValueChanged) {
      this.setSelection(newSelection.start, newSelection.end);
    }
  }"