Skip to content

TextInput Events

Maciej Jastrzebski edited this page Aug 13, 2024 · 38 revisions

Single Line - basic flow

RN version: 0.71.6

Setup:

<TextInput
  style={styles.textInput}
  value={value}
  onChangeText={handleChangeText}
  onPressIn={handlePressIn}
  onPressOut={handlePressOut}
  onFocus={handleFocus}
  onBlur={handleBlur}
  onChange={handleChange}
  onEndEditing={handleEndEditing}
  onSubmitEditing={handleSubmitEditing}
  onKeyPress={handleKeyPress}
  onSelectionChange={handleSelectionChange}
  onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "Test" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406399.731625, "touches": [[Circular]]}
LOG  Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 153, "locationY": 10.333328247070312, "pageX": 173, "pageY": 121.33332824707031, "target": 75, "timestamp": 975406478.905625, "touches": []}

LOG  Event: keyPress {"eventCount": 0, "key": "T", "target": 75}
LOG  Event: change {"eventCount": 1, "target": 75, "text": "T"}
LOG  Event: changeText T
LOG  Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11}, "target": 75}

LOG  Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG  Event: change {"eventCount": 2, "target": 75, "text": "Te"}
LOG  Event: changeText Te
LOG  Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 19}, "target": 75}

LOG  Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG  Event: change {"eventCount": 3, "target": 75, "text": "Tes"}
LOG  Event: changeText Tes
LOG  Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 28}, "target": 75}

LOG  Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG  Event: change {"eventCount": 4, "target": 75, "text": "Test"}
LOG  Event: changeText Test
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 34}, "target": 75}

LOG  Event: submitEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG  Event: endEditing {"eventCount": 4, "target": 75, "text": "Test"}
LOG  Event: blur {"eventCount": 4, "target": 75, "text": "Test"}

Android:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060200, "touches": [[Circular]]}
LOG  Event: focus {"target": 53}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 80.36363983154297, "locationY": 29.090909957885742, "pageX": 100.36363983154297, "pageY": 129.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 107060255, "touches": []}

LOG  Event: change {"eventCount": 2, "target": 53, "text": "T"}
LOG  Event: changeText T
LOG  Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG  Event: keyPress {"key": "T"}

LOG  Event: change {"eventCount": 4, "target": 53, "text": "Te"}
LOG  Event: changeText Te
LOG  Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG  Event: keyPress {"key": "e"}

LOG  Event: change {"eventCount": 6, "target": 53, "text": "Tes"}
LOG  Event: changeText Tes
LOG  Event: selectionChange {"selection": {"end": 3, "start": 3}}
LOG  Event: keyPress {"key": "s"}

LOG  Event: change {"eventCount": 8, "target": 53, "text": "Test"}
LOG  Event: changeText Test
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG  Event: keyPress {"key": "t"}

LOG  Event: submitEditing {"target": 53, "text": "Test"}
LOG  Event: blur {"target": 53}
LOG  Event: endEditing {"target": 53, "text": "Test"}

Notes:

  • Sequence of events on focusing both platforms is the same: pressIn - focus - pressOut
  • Sequence of events on pressing Enter on both platforms is slightly:
    • iOS: submitEditing - endEditing - blur
    • Android: submitEditing - blur - endEditing
  • Sequence of events of typing is different:
    • iOS: keyPress - change - changeText - selectionChange - contentSizeChange
    • Android: change - changeText - selectionChange - keyPress
  • The submitEditing event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element
  • In case of unmanaged TextInput (i.e. no value prop being passed) the events are the same on Android

Mutli-Line - basic flow

RN version: 0.71.6

Setup:

<TextInput
  style={styles.textInput}
  value={value}
  mutliline={true}
  onChangeText={handleChangeText}
  onPressIn={handlePressIn}
  onPressOut={handlePressOut}
  onFocus={handleFocus}
  onBlur={handleBlur}
  onChange={handleChange}
  onEndEditing={handleEndEditing}
  onSubmitEditing={handleSubmitEditing}
  onKeyPress={handleKeyPress}
  onSelectionChange={handleSelectionChange}
  onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "AB\nCD" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407822.0294167, "touches": [[Circular]]}
LOG  Event: focus {"eventCount": 0, "target": 75, "text": ""}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 244.66665649414062, "locationY": 14.333328247070312, "pageX": 264.6666564941406, "pageY": 125.33332824707031, "target": 75, "timestamp": 1014407901.1994168, "touches": []}

LOG  Event: keyPress {"eventCount": 0, "key": "A", "target": 75}
LOG  Event: change {"eventCount": 1, "target": 75, "text": "A"}
LOG  Event: changeText A
LOG  Event: selectionChange {"selection": {"end": 1, "start": 1}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 11.666666666666666}, "target": 75}

LOG  Event: keyPress {"eventCount": 1, "key": "B", "target": 75}
LOG  Event: change {"eventCount": 2, "target": 75, "text": "AB"}
LOG  Event: changeText AB
LOG  Event: selectionChange {"selection": {"end": 2, "start": 2}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 23.333333333333332}, "target": 75}

// Enter key
LOG  Event: keyPress {"eventCount": 2, "key": "Enter", "target": 75}
LOG  Event: change {"eventCount": 3, "target": 75, "text": "AB\n"}
LOG  Event: changeText AB
LOG  Event: selectionChange {"selection": {"end": 3, "start": 3}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 43, "width": 23.333333333333332}, "target": 75}

LOG  Event: keyPress {"eventCount": 3, "key": "C", "target": 75}
LOG  Event: change {"eventCount": 4, "target": 75, "text": "AB\nC"}
LOG  Event: changeText AB\nC
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}, "target": 75}

LOG  Event: keyPress {"eventCount": 4, "key": "D", "target": 75}
LOG  Event: change {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG  Event: changeText AB\nCD
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 43, "width": 25.333333333333332}, "target": 75}

LOG  Event: endEditing {"eventCount": 5, "target": 75, "text": "AB\nCD"}
LOG  Event: blur {"eventCount": 5, "target": 75, "text": "AB\nCD"}

Android:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.09090805053711, "pageX": 277.4545593261719, "pageY": 133.09091186523438, "target": 53, "targetSurface": -1, "timestamp": 168170420, "touches": [[Circular]]}
LOG  Event: focus {"target": 53}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 257.4545593261719, "locationY": 33.818180084228516, "pageX": 277.4545593261719, "pageY": 133.81817626953125, "target": 53, "targetSurface": -1, "timestamp": 168170514, "touches": []}

LOG  Event: change {"eventCount": 2, "target": 53, "text": "A"}
LOG  Event: changeText A
LOG  Event: selectionChange {"selection": {"end": 1, "start": 1}}
LOG  Event: keyPress {"key": "A"}

LOG  Event: change {"eventCount": 4, "target": 53, "text": "AB"}
LOG  Event: changeText AB
LOG  Event: selectionChange {"selection": {"end": 2, "start": 2}}
LOG  Event: keyPress {"key": "B"}

// Enter
LOG  Event: contentSizeChange {"contentSize": {"height": 61.45454406738281, "width": 352.7272644042969}, "target": 53}
LOG  Event: change {"eventCount": 6, "target": 53, "text": "AB\n"}
LOG  Event: changeText AB
LOG  Event: selectionChange {"selection": {"end": 3, "start": 3}}

LOG  Event: change {"eventCount": 8, "target": 53, "text": "AB\nC"}
LOG  Event: changeText AB\nC
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}
LOG  Event: keyPress {"key": "C"}

LOG  Event: change {"eventCount": 10, "target": 53, "text": "AB\nCD"}
LOG  Event: changeText AB\nCD
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG  Event: keyPress {"key": "D"}

LOG  Event: blur {"target": 53}
LOG  Event: endEditing {"target": 53, "text": "AB\nCD"}

Notes:

  • Sequence of events on focusing both platforms is the same: pressIn - focus - pressOut
  • Sequence of events on pressing Enter on both platforms is slightly:
    • iOS: endEditing - blur
    • Android: blur - endEditing
  • Sequence of events of typing is different:
    • iOS: keyPress - change - changeText - selectionChange - contentSizeChange (when it actually changes)
    • Android: contentSizeChange (only for Enter) - change - changeText - selectionChange - keyPress (not for Enter)
  • The submitEditing event is only emitted if user presses done/next/etc field, but not in case of tapping on another focusable element

Impact of editable={false} prop

Setup:

<TextInput
  style={styles.textInput}
  value={value}
  onChangeText={handleChangeText}
  editable={false}
  onPressIn={handlePressIn}
  onPressOut={handlePressOut}
  onFocus={handleFocus}
  onBlur={handleBlur}
  onChange={handleChange}
/>

Steps:

  1. Press TextInput

Output:

iOS:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054389.9047917, "touches": [[Circular]]}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 57.33332824707031, "locationY": 35, "pageX": 77.33332824707031, "pageY": 146, "target": 117, "timestamp": 707054477.4037917, "touches": []}

Android:

(No events logged)

Managed TextInput rejecting changes

RN version: 0.71.6

Setup:

<TextInput
  style={styles.textInput}
  value="AAAA"
  editable={true}
  onPressIn={handlePressIn}
  onPressOut={handlePressOut}
  onFocus={handleFocus}
  onBlur={handleBlur}
  onChange={handleChange}
  onChangeText={handleChangeText}
  onSubmitEditing={handleSubmitEditing}
  onKeyPress={handleKeyPress}
  onSelectionChange={handleSelectionChange}
  onContentSizeChange={handleContentSizeChange}
/>

Steps:

  1. Press on the text input
  2. Type "Test" using on screen keyboard
  3. Press "return" to close the keyboard

Output:

iOS:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401529.229625, "touches": [[Circular]]}
LOG  Event: focus {"eventCount": 0, "target": 75, "text": "AAAA"}
LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 107, "locationY": 12, "pageX": 127, "pageY": 123, "target": 75, "timestamp": 967401608.349625, "touches": []}

LOG  Event: keyPress {"eventCount": 0, "key": "t", "target": 75}
LOG  Event: change {"eventCount": 1, "target": 75, "text": "AAAAt"}
LOG  Event: changeText AAAAt
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}

LOG  Event: keyPress {"eventCount": 1, "key": "e", "target": 75}
LOG  Event: change {"eventCount": 2, "target": 75, "text": "AAAAe"}
LOG  Event: changeText AAAAe
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 56}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}

LOG  Event: keyPress {"eventCount": 2, "key": "s", "target": 75}
LOG  Event: change {"eventCount": 3, "target": 75, "text": "AAAAs"}
LOG  Event: changeText AAAAs
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 55.666666666666664}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}

LOG  Event: keyPress {"eventCount": 3, "key": "t", "target": 75}
LOG  Event: change {"eventCount": 4, "target": 75, "text": "AAAAt"}
LOG  Event: changeText AAAAt
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 52.333333333333336}, "target": 75}
LOG  Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 46.666666666666664}, "target": 75}

LOG  Event: submitEditing {"eventCount": 4, "target": 75, "text": "AAAA"}
LOG  Event: blur {"eventCount": 4, "target": 75, "text": "AAAA"}

Android:

LOG  Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073165, "touches": [[Circular]]}
LOG  Event: focus {"target": 53}

// `selectionChange` only happens on first focus. Subsequent focuses skip it.
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}

LOG  Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 94.18181610107422, "locationY": 22.18181800842285, "pageX": 114.18181610107422, "pageY": 122.18181610107422, "target": 53, "targetSurface": -1, "timestamp": 91073239, "touches": []}

LOG  Event: change {"eventCount": 2, "target": 53, "text": "AAAAT"}
LOG  Event: changeText AAAAT
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG  Event: keyPress {"key": "T"}
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}

LOG  Event: change {"eventCount": 4, "target": 53, "text": "AAAAe"}
LOG  Event: changeText AAAAe
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG  Event: keyPress {"key": "e"}
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}

LOG  Event: change {"eventCount": 6, "target": 53, "text": "AAAAs"}
LOG  Event: changeText AAAAs
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG  Event: keyPress {"key": "s"}
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}

LOG  Event: change {"eventCount": 8, "target": 53, "text": "AAAAt"}
LOG  Event: changeText AAAAt
LOG  Event: selectionChange {"selection": {"end": 5, "start": 5}}
LOG  Event: keyPress {"key": "t"}
LOG  Event: selectionChange {"selection": {"end": 4, "start": 4}}

LOG  Event: submitEditing {"target": 53, "text": "AAAA"}
LOG  Event: blur {"target": 53}

Using backspace

Android:

Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 54.54545593261719, "locationY": 20, "pageX": 74.54545593261719, "pageY": 120, "target": 83, "targetSurface": -1, "timestamp": 542793523, "touches": [[Circular]]}
Event: focus {"target": 83}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 54.54545593261719, "locationY": 20, "pageX": 74.54545593261719, "pageY": 120, "target": 83, "targetSurface": -1, "timestamp": 542793571, "touches": []}

Event: change {"eventCount": 2, "target": 83, "text": "A"}
Event: changeText A
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "A"}

Event: change {"eventCount": 4, "target": 83, "text": "Ab"}
Event: changeText Ab
Event: selectionChange {"selection": {"end": 2, "start": 2}}
Event: keyPress {"key": "b"}

Event: change {"eventCount": 6, "target": 83, "text": "A"}
Event: changeText A
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "Backspace"}

Event: change {"eventCount": 8, "target": 83, "text": ""}
Event: changeText 
Event: selectionChange {"selection": {"end": 0, "start": 0}}
Event: keyPress {"key": "Backspace"}
Event: contentSizeChange {"contentSize": {"height": 45.818180084228516, "width": 352.7272644042969}, "target": 83}

Event: contentSizeChange {"contentSize": {"height": 40.3636360168457, "width": 381316.375}, "target": 83}
Event: change {"eventCount": 10, "target": 83, "text": "C"}
Event: changeText C
Event: selectionChange {"selection": {"end": 1, "start": 1}}
Event: keyPress {"key": "C"}

Event: submitEditing {"target": 83, "text": "C"}
Event: blur {"target": 83}
Event: endEditing {"target": 83, "text": "C"}

Clearing TextInput

Scenario:

  1. TextInput Events experiment
  2. Fill in TextInput with Random text, focus out
  3. Start recording events
  4. Enter text field
  5. Select all text using context menu
  6. Press backspace
  7. Exit TextInput

iOS

// Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 59.5, "locationY": 6, "pageX": 79.5, "pageY": 90, "target": 75, "timestamp": 166484128.726374, "touches": [[Circular]]}
Event: focus {"eventCount": 23, "target": 75, "text": "Test"}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 59.5, "locationY": 6, "pageX": 79.5, "pageY": 90, "target": 75, "timestamp": 166484183.03356, "touches": []}

// Select all (Cmd+A)
Event: selectionChange {"selection": {"end": 4, "start": 0}, "target": 75}

// Press backspace
Event: keyPress {"eventCount": 23, "key": "Backspace", "target": 75}
Event: change {"eventCount": 24, "target": 75, "text": ""}
Event: changeText 
Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: contentSizeChange {"contentSize": {"height": 21.5, "width": 143.5}, "target": 75}

// Exit
Event: endEditing {"eventCount": 24, "target": 75, "text": ""}
Event: blur {"eventCount": 24, "target": 75, "text": ""}

iOS (clear button)

Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 321, "locationY": 19.5, "pageX": 341, "pageY": 103.5, "target": 75, "timestamp": 166027702.319404, "touches": [[Circular]]}
Event: keyPress {"eventCount": 18, "key": "Backspace", "target": 75}
Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: contentSizeChange {"contentSize": {"height": 21.5, "width": 143.5}, "target": 75}
Event: change {"eventCount": 19, "target": 75, "text": ""}
Event: changeText 
Event: selectionChange {"selection": {"end": 0, "start": 0}, "target": 75}
Event: focus {"eventCount": 19, "target": 75, "text": ""}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 321, "locationY": 19.5, "pageX": 341, "pageY": 103.5, "target": 75, "timestamp": 166027788.429719, "touches": []}

Android

// Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 18.172496795654297, "locationY": 24.707475662231445, "pageX": 38.1724967956543, "pageY": 124.70747375488281, "target": 53, "targetSurface": -1, "timestamp": 216026, "touches": [[Circular]]}
Event: focus {"target": 53}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 18.172496795654297, "locationY": 24.707475662231445, "pageX": 38.1724967956543, "pageY": 124.70747375488281, "target": 53, "targetSurface": -1, "timestamp": 216070, "touches": []}

// Select all
Event: selectionChange {"selection": {"end": 4, "start": 0}}

// Press backspace
Event: change {"eventCount": 20, "target": 53, "text": ""}
Event: changeText 
Event: selectionChange {"selection": {"end": 0, "start": 0}}
Event: contentSizeChange {"contentSize": {"height": 45.818180084228516, "width": 352.7272644042969}, "target": 53}

// Exit
Event: blur {"target": 53}
Event: endEditing {"target": 53, "text": ""}

User Event design

// Step 1: enter
- focus (skip pressIn/pressOut in sync with RTL UserEvent clear())

// Step 2: select all
- selectionChange: whole text

// Step 3: clear with backspace key (in sync with type())
- keyPress: backspace
- change: ""
- changeText: ""
- selectionChange: zero range
- contentSizeChange: (for multiline-only)

// Step 4: exit
- blur

Pasting Text

iOS

// Step 1: Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2948717.0664166664, "touches": [[Circular]]}
Event: focus {"eventCount": 2, "target": 153, "text": ""}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2948811.551, "touches": []}

// Step 2. Press to trigger menu
Event: pressIn {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2949547.4370000004, "touches": [[Circular]]}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 1, "locationX": 34.33332824707031, "locationY": 28.333333333333314, "pageX": 54.33332824707031, "pageY": 146, "target": 153, "timestamp": 2950717.1967916666, "touches": []}

// Step 3. Actual paste
Event: change {"eventCount": 3, "target": 153, "text": "Hello"}
Event: changeText Hello
Event: selectionChange {"selection": {"end": 5, "start": 5}, "target": 153}
Event: contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 41}, "target": 153}

// Step 4. Exit
Event: endEditing {"eventCount": 3, "target": 153, "text": "Hello"}
Event: blur {"eventCount": 3, "target": 153, "text": "Hello"}

Android

// Step 1. Enter
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40841617, "touches": [[Circular]]}
Event: focus {"target": 97}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40841721, "touches": []}

// Step 2. Press to trigger menu
Event: pressIn {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40843111, "touches": [[Circular]]}
Event: pressOut {"changedTouches": [[Circular]], "identifier": 0, "locationX": 48.75334930419922, "locationY": 22.465774536132812, "pageX": 68.9438247680664, "pageY": 122.65625, "target": 97, "targetSurface": -1, "timestamp": 40844142, "touches": []}

// Step 3. Actual paste
Event: contentSizeChange {"contentSize": {"height": 40.761905670166016, "width": 399473.53125}, "target": 97}
Event: change {"eventCount": 50, "target": 97, "text": "Hello"}
Event: changeText Hello
Event: selectionChange {"selection": {"end": 5, "start": 5}}

// Step 4. Exit
Event: blur {"target": 97}
Event: endEditing {"target": 97, "text": "pageY"}

User Event design

// Step 1: Enter
- focus

// Step 2: select all
- selectionChange: whole text

// Step 3. Actual paste
- change {"text": "Hello"}
- changeText Hello
- selectionChange {"selection": {"end": 5, "start": 5}, "target": 153}
- contentSizeChange {"contentSize": {"height": 21.666666666666668, "width": 41}, "target": 153}

// Step 4. Exit
- endEditing {"eventCount": 3, "target": 153, "text": "Hello"}
- blur {"eventCount": 3, "target": 153, "text": "Hello"}