xtrinch / react-touch-screen-keyboard

React touch screen virtual keyboard, opened on input focused
MIT License
47 stars 31 forks source link

Pass events in callbacks #52

Open buesing opened 5 years ago

buesing commented 5 years ago

I want to animate the keyboard on focus/blur. It would be helpful if the events would be passed to e.g. onBlur so I can prevent it, do my animation, and the fire it again. Unless I'm missing another easy way to do this.

reganlawton commented 5 years ago

@buesing

The <KeyboardedInput /> component has callbacks for for onFocus and onBlur. Do you have an animation workflow that doesn't fit those callbacks?

buesing commented 5 years ago

Yes, I want to

  onBlur = (e) => {
    e.preventDefault();
    TweenMax.fromTo(".keyboard-wrapper", 0.5, {
      y: 0,
      autoAlpha: 1,
    }, {
      autoAlpha: 0,
      y: 100,
    });
  }

But I can't, because the event is not passed and the element disappears instantly. Is there any way to get it to have an out-animation?

reganlawton commented 5 years ago

@buesing Could you possible do the using the KeyboardInput ref?

  <KeyboardedInput
    ref={ref => { this.myInput = ref; }}
    ...

Or is it possible to use CSS transitions to achieve your goal?

reganlawton commented 5 years ago

@buesing Due to the way the project works by triggering the the focus event on the input I'm not sure your animation is going to be supported with out breaking support for other cases.

buesing commented 5 years ago

If you passed me the event I think I could just prevent it, no? That wouldn't break anything.

reganlawton commented 5 years ago

@buesing

The event is handled inside a setTimeout() function. I believe this is done to keep the input focused when hitting the virtual keys. See below.


handleFocus() {
    const that = this;
    // Prevent blinking of the keyboard if opaque
    setTimeout(() => {
      if (that.input && typeof (that.props.value) !== 'undefined') {
        that.input.focus();
        that.input.select();
        that.input.setSelectionRange(that.props.value.length, that.props.value.length);

        // Only trigger on first focus
        if (this.state.showKeyboard === false && that.props.onFocus) {
          that.props.onFocus(that.props.value);
        }

        that.setState({ ...this.state, showKeyboard: true });
      }
    }, 0);
  }

  handleFocusLost() {
    const that = this;
    setTimeout(() => {
      if (!document.activeElement.classList.contains('keyboard-button')
        && !document.activeElement.classList.contains('keyboard')
        && !document.activeElement.classList.contains('keyboard-row')
        && !document.activeElement.classList.contains('react-draggable-transparent-selection')) {

        if (that.props.onBlur) {
          that.props.onBlur(that.props.value);
        }

        that.setState({ ...that.state, showKeyboard: false });
      }
    }, 0);
  }```

I had a quick play and refactored to pass the event through as a second param for the callback but quickly noticed that the event is fired continuously to keep focus on the input. Which would fire the animation multiple times and my guess would look quite funny.

My idea would be to create a `onStart` and `onEnd` callback prop. Which could pass the event one time then skip over after.
buesing commented 5 years ago

Yes, sounds like it could work. I just need some way to fade out the keyboard after focus is lost.

reganlawton commented 5 years ago

@buesing Sorry for the late reply this change is gonna take abit of testing to make sure the change doesn't impact the current workflow of the library. I'll buzz you once I have a branch for you to test.