-
Notifications
You must be signed in to change notification settings - Fork 52
Add handlers for composition on Inputs #1082
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Tanney-102
merged 17 commits into
channel-io:next-v1
from
Tanney-102:features/handle-composition
Feb 27, 2023
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
e54ef67
feat(useEventLocker): implement hook that provide functions to lock e…
Tanney-102 318595f
feat(useKeyboardActionLockerWhileComposing): implement hook
Tanney-102 b9dc4ff
feat(TextField): wrap keyboard event handlers with composing locker
Tanney-102 f52de23
fix(TestField.test): correct fired event for lock keyboard event test
Tanney-102 cea3508
fix(TextField.test): move tests for composing into new decribe context
Tanney-102 b33855f
feat(TextArea): wrap keyboard event handlers with composing locker
Tanney-102 d513c25
docs: add change set
Tanney-102 0351092
fix(useKeyboardActionLockerWhileComposing): merge logics from useEven…
Tanney-102 22fa9f5
fix(useKeyboardActionLockerWhileComposing): remove key===enter condit…
Tanney-102 2523d76
refactor(useKeyboardActionLockerWhileComposing): replace isComposingR…
Tanney-102 2886919
fix(TextField.test): force fired key events to notice isComposing state
Tanney-102 333b0be
fix(TextArea.test): force fired key events to notice isComposing state
Tanney-102 63073db
fix(useKeyboardActionLockerWhileComposing): remove onKeyPress from ar…
Tanney-102 593a988
fix: case sensitive import
Tanney-102 abc7927
docs(changeset): add details to changeset document
Tanney-102 f3aac26
test(TextArea): rewrite test case for keyboard locker in English
Tanney-102 461a50a
test(TextField): rewrite test case for keyboard locker
Tanney-102 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| "@channel.io/bezier-react": minor | ||
| --- | ||
|
|
||
| - keyboard event locker added. | ||
| - TextField and TextArea use keyboard event locker, so that they can block keyboard event handling for IME control keys while composing. | ||
|
|
||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
packages/bezier-react/src/components/Forms/Inputs/constants/CommonImeControlKeys.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export const COMMON_IME_CONTROL_KEYS = ['Enter', 'Escape', 'Tab', ' ', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
packages/bezier-react/src/components/Forms/useKeyboardActionLockerWhileComposing.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| /* External dependencies */ | ||
| import React, { useCallback, useRef } from 'react' | ||
|
|
||
| type HandlerCache<TargetElement extends HTMLElement = HTMLInputElement> = | ||
| Map<React.KeyboardEventHandler<TargetElement>, React.KeyboardEventHandler<TargetElement>> | ||
| interface UseKeyboardActionLockerWhileComposingProps<TargetElement extends HTMLElement = HTMLInputElement> { | ||
| keysToLock?: string[] | ||
| onKeyDown?: React.KeyboardEventHandler<TargetElement> | ||
| onKeyUp?: React.KeyboardEventHandler<TargetElement> | ||
| } | ||
|
|
||
| const isSafari = () => window.navigator.userAgent.search('Safari') >= 0 && window.navigator.userAgent.search('Chrome') < 0 | ||
|
|
||
| function useKeyboardActionLockerWhileComposing<TargetElement extends HTMLElement = HTMLInputElement>({ | ||
| keysToLock, | ||
| onKeyDown, | ||
| onKeyUp, | ||
| }: UseKeyboardActionLockerWhileComposingProps<TargetElement>) { | ||
| const handlerCache = useRef<HandlerCache<TargetElement>>(new Map()) | ||
|
|
||
| const wrapHandler = useCallback((handler?: React.KeyboardEventHandler<TargetElement>) => { | ||
| if (!handler) { return undefined } | ||
| if (handlerCache.current.has(handler)) { return handlerCache.current.get(handler) } | ||
|
|
||
| const wrappedHandler = (event: React.KeyboardEvent<TargetElement>) => { | ||
| // NOTE: If keysToLock is not provided, lock all keys. | ||
| const isKeyLocked = | ||
| event.nativeEvent.isComposing && | ||
| (!keysToLock || keysToLock.some(controlKey => event.key === controlKey)) | ||
| /** | ||
| * NOTE | ||
| * According to the spec(https://www.w3.org/TR/uievents/#events-composition-key-events), | ||
| * keyDown event that exit composition should be fired before compositionEnd event. | ||
| * However, Safari has different behavior. | ||
| * In Safari, keyDown event that exit composition is fired after compositionEnd event. | ||
| * So, we need to prevent keyDown event that exit composition in Safari. | ||
| * Browser fires keydown event with keyCode 229 when user is composing. | ||
| * An event that exits composition is also fired with keyCode 229, even though it has fired after compositionEnd event. | ||
| * Therefore, we need to check if the event is fired with keyCode 229 in Safari. | ||
| */ | ||
| const isSafariKeydownWhileComposing = | ||
| isSafari() && | ||
| event.type === 'keydown' && | ||
| event.keyCode === 229 | ||
|
|
||
| if (isKeyLocked || isSafariKeydownWhileComposing) { | ||
| event.stopPropagation() | ||
| return | ||
| } | ||
| handler?.(event) | ||
| } | ||
|
|
||
| handlerCache.current.set(handler, wrappedHandler) | ||
| return wrappedHandler | ||
| }, [keysToLock]) | ||
|
|
||
| return { | ||
| handleKeyDown: wrapHandler(onKeyDown), | ||
| handleKeyUp: wrapHandler(onKeyUp), | ||
| } | ||
| } | ||
|
|
||
| export default useKeyboardActionLockerWhileComposing |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fireEvent대신userEvent를 통해 테스트 가능할까요? (관련 링크)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
userEvent에서는 composition을 mocking할 수 있는 방법을 따로 지원하지 않습니다 😢