preactjs / preact

⚛️ Fast 3kB React alternative with the same modern API. Components & Virtual DOM.
https://preactjs.com
MIT License
36.79k stars 1.95k forks source link

Support for composition events #1978

Open birtles opened 5 years ago

birtles commented 5 years ago

So far as I can tell, although jsx.d.ts includes a definition for composition events such as onCompositionEnd, they are not implemented.

Furthermore, while isComposing is available through InputEvent, it is not normalized between browsers so, for example, in Firefox there will be an input event where it is true but there is not in Chrome. Without composition events it is not possible to work around this and, for example, only update search results once the current composition has been committed.

Test case:

https://codesandbox.io/s/bold-currying-vqfq8

birtles commented 5 years ago

Test case:

https://codesandbox.io/s/bold-currying-vqfq8

Typing and committing あ in the above test case gives:

Firefox:

input (data: あ, isComposing: true)
input (data: あ, isComposing: false)

Chrome:

input (data: あ, isComposing: true)
input (data: あ, isComposing: true)
birtles commented 5 years ago

For what it's worth, the browser interop issue has some discussion at: https://github.com/w3c/uievents/issues/202

It would be nice to have these events regardless of the outcome of that, however.

marvinhagemeister commented 5 years ago

Thanks for posting this. I've read through the linked w3c issue a couple of times, but I'm not sure what the expected behavior is. There seem to be arguments made in favor of both sides. From what I can gather so far, the firefox implementation is the preferred one. Is that correct?

birtles commented 5 years ago

Sorry, I possibly confused the issue by linking to that spec discussion. For what it's worth, as a Web developer, I find the Firefox behavior more useful (e.g. for ignoring uncommitted input).

As far as Preact is concerned, however, the issue is simply that authors can't rely on isComposing both due to compat issues and because the Chrome behavior makes it impossible to ignore uncommitted input. As a result authors needs to listen to composition events instead but Preact does not appear to implement them (unlike React). Instead, it seems authors need to add native event listeners to elements, e.g.: https://github.com/birchill/hikibiki/commit/4b324e7197bc58fdca4d1c5ac0ab069fcf4ea28d

developit commented 5 years ago

Hi @birtles - I think this is actually a case sensitivity issue. My guess is that you'll find this works:

<input oncompositionend={() => { ... }} />
birtles commented 5 years ago

Hi @birtles - I think this is actually a case sensitivity issue. My guess is that you'll find this works:

<input oncompositionend={() => { ... }} />

Oh yes, you're right. That does indeed work.