Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions proposals/0000-textinput-onpaste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Add onPaste to TextInput
author:
- Abdelhafidh Belalia
date: 2024-07-18
---

# RFC0000: Add onPaste to TextInput

## Summary

Add `onPaste` prop to `TextInput` component

## Basic example

```js
<TextInput onPaste={() => console.log("User pressed Paste")} />
```

## Motivation

Detect `Paste` event on TextInput. In our use case detecting paste event can be used to support image pasting.

## Detailed design

iOS:

1. In `RCTUITextField`/`RCTUITextView` override the `paste:` method to call the delegate adapater `[didPaste]`
2. Implement the `didPaste` method on the delegate adapater and call the delegate input `[textInputDidPaste]`
3. Implement the `textInputDidPaste` method on the delegate input to disptach the `onPaste` event

Android:

1. In `ReactEditText` override the `onTextContextMenuItem` method to call the `PasteWatcher` insatnce
2. In `ReactTextInputManager` create and set the `PasteWatcher` instance for the view (`ReactEditText`)
3. Implement the `PasteWatcher` class to to disptach the `onPaste` event

There is a PR for that change already https://github.com/facebook/react-native/pull/45425

## Drawbacks

None

## Alternatives

None

## Adoption strategy

This is not a breaking change. Developers can adopt the feature by simply adding `onPaste` prop to their components

## How we teach this

Update the docs https://github.com/facebook/react-native-website/pull/4161

## Unresolved questions

- onPaste event does not expose any clipboard data. How can we add such data?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NickGerleman Can we handle this as a follow up?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The event without data would require accessing clipboard afterward, and since that happens asynchronously, the data may have changed or be incorrect. A concrete example of this, is if you paste a password, a password manager might immediately clear it from the clipboard.

I.e. the current approach without the data is impossible to make reliable, and would encourage users to add code which falls into the anti-pattern.

I don't know how much time @cipolleschi has dedicated to this change, but did want to share the context I had on this, and some of the baselines of what these events should look like.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data can be as follow:

{
    target: viewTag,
    items: [
        {
            type: "image/jpeg", // MIME type
            data: "data:image/jpeg;base64,..." // data: plaintext for text/plain and base64 encoded data for the rest
        }
    ],
}

items is an array that holds different items present in the clipboard, but for the current implementation only the first item is added.

Android implementation facebook/react-native@af06d9e

Screen.Recording.2024-07-24.at.3.22.50.AM-2.mov

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding pasting files, using base64 string is not looking very performant (dealing with long strings can be slow). I'm looking into passing the URI instead, for Android we can directly use clipData.getItemAt(0).getUri()

(still investigating the same for iOS)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On iOS the clipboard items do not expose any URI. When a file is pasted, we copy its data into a temporarily file and provide that file's URI instead. Proposal updated.

Copy link

@intergalacticspacehighway intergalacticspacehighway Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@s77rt thanks for working on this. can we make the paste event resemble the ClipboardEvent API? Like this example

So we can access clipboard data using event.nativeEvent.clipboardData. I like the temporary file approach over base64. Since we're returning the file URI, we can do below.

onPaste = (e) => {
    if (e.nativeEvent.clipboardData.types.indexOf('text/plain') > -1) {
        // User pasted a plain text
        const text = e.nativeEvent.clipboardData.getData('text/plain')
    }
    
    else if (e.nativeEvent.clipboardData.types.indexOf('text/uri-list') > -1) {
        // User pasted an image/file url
        const uri = e.nativeEvent.clipboardData.getData('text/uri-list')
        // in case of multiple URIs, they are separated by `\n` newline character.
    }
}

clipboardData is of type DataTransfer but for now we can support types and getData.

Also some more references - https://www.w3.org/TR/clipboard-apis/, get data