Skip to content

Rich Paste ​

Rich paste and drag-and-drop support for NativeScript text inputs. Handles images, GIFs, files, and text from the clipboard with one shared TypeScript API across iOS and Android.

The plugin supports:

  • Pasting images, GIFs, and static images from the clipboard
  • Pasting files (PDF, RTF, HTML) from the clipboard
  • Drag-and-drop of images and files into text inputs
  • MIME-based accept filtering (all, image/*, text/plain, etc.)
  • Drop-in replacements for TextField and TextView
  • Automatic temp file management for pasted binary content

Installation ​

bash
npm install @nstudio/nativescript-rich-paste

Usage ​

NativeScript Core ​

Drop-in replacements for TextField and TextView which work identically but with enhanced rich paste features. Just append RichPaste to the end of the element name.

xml
<Page xmlns:rp="@nstudio/nativescript-rich-paste">
  <StackLayout class="p-20">
    <rp:TextFieldRichPaste accept="all" hint="Paste rich data..." paste="{{ onPaste }}" />
    <rp:TextViewRichPaste accept="image/*" hint="Drop images here..." enableDragDrop="true" paste="{{ onPaste }}" drop="{{ onDrop }}" />
  </StackLayout>
</Page>
typescript
import { EventData, Page } from '@nativescript/core';
import { PasteEventData } from '@nstudio/nativescript-rich-paste';

export function navigatingTo(args: EventData) {
  const page = args.object as Page;
  page.bindingContext = new DemoModel();
}

class DemoModel {
  onPaste(args: PasteEventData) {
    const payload = args.data;
    switch (payload.type) {
      case 'text':
        console.log('Text:', payload.value);
        break;
      case 'images':
        payload.items.forEach((img) => {
          console.log(img.uri, img.mimeType, img.animated);
        });
        break;
      case 'files':
        payload.items.forEach((file) => {
          console.log(file.name, file.mimeType, file.size);
        });
        break;
    }
  }

  onDrop(args: PasteEventData) {
    console.log('Dropped:', args.data);
  }
}

Frameworks ​

typescript
import { registerElement } from '@nativescript/angular';
import { TextFieldRichPaste, TextViewRichPaste } from '@nstudio/nativescript-rich-paste';

registerElement('TextFieldRichPaste', () => TextFieldRichPaste);
registerElement('TextViewRichPaste', () => TextViewRichPaste);
html
<TextFieldRichPaste
  accept="all"
  hint="Paste rich data..."
  (paste)="onPaste($event)"
></TextFieldRichPaste>

<TextViewRichPaste
  accept="image/*"
  hint="Drop images here..."
  enableDragDrop="true"
  (paste)="onPaste($event)"
  (drop)="onDrop($event)"
></TextViewRichPaste>
typescript
import { registerElement } from 'react-nativescript';
import { TextFieldRichPaste, TextViewRichPaste } from '@nstudio/nativescript-rich-paste';

registerElement('textFieldRichPaste', () => TextFieldRichPaste);
registerElement('textViewRichPaste', () => TextViewRichPaste);
typescript
import { registerElement } from 'nativescript-vue';
import { TextFieldRichPaste, TextViewRichPaste } from '@nstudio/nativescript-rich-paste';

registerElement('TextFieldRichPaste', () => TextFieldRichPaste);
registerElement('TextViewRichPaste', () => TextViewRichPaste);
typescript
import { registerNativeViewElement } from '@nativescript-community/svelte-native/dom';
import { TextFieldRichPaste, TextViewRichPaste } from '@nstudio/nativescript-rich-paste';

registerNativeViewElement('textFieldRichPaste', () => TextFieldRichPaste);
registerNativeViewElement('textViewRichPaste', () => TextViewRichPaste);
typescript
import { registerElement } from 'dominative';
import { TextFieldRichPaste, TextViewRichPaste } from '@nstudio/nativescript-rich-paste';

registerElement('textFieldRichPaste', TextFieldRichPaste);
registerElement('textViewRichPaste', TextViewRichPaste);

Paste Payload ​

The paste and drop events emit a PasteEventData object whose data property is a discriminated union:

Text ​

typescript
interface PasteTextPayload {
  type: 'text';
  value: string;
}

Images ​

typescript
interface PasteImagesPayload {
  type: 'images';
  items: PasteImageItem[];
}

interface PasteImageItem {
  uri: string;        // file:// URI to a temp file
  mimeType: string;   // e.g. 'image/png', 'image/gif'
  width?: number;
  height?: number;
  animated: boolean;   // true for GIFs
}

Files ​

typescript
interface PasteFilesPayload {
  type: 'files';
  items: PasteFileItem[];
}

interface PasteFileItem {
  uri: string;        // file:// URI to a temp file
  mimeType: string;   // e.g. 'application/pdf'
  name?: string;
  size?: number;
}

Unsupported ​

Returned when the clipboard contains data that does not match the accept filter.

typescript
interface PasteUnsupportedPayload {
  type: 'unsupported';
  availableTypes: string[];
}

Events ​

paste ​

Emitted when rich content is pasted from the clipboard.

typescript
import { PasteEventData } from '@nstudio/nativescript-rich-paste';

function onPaste(args: PasteEventData) {
  const payload = args.data;
  console.log('Paste type:', payload.type);
}

For text pastes, the default TextField/TextView behavior still applies (the text is inserted into the field) and the paste event is also fired.

drop ​

Emitted when content is dragged and dropped onto the input. Requires enableDragDrop="true".

typescript
import { DropEventData } from '@nstudio/nativescript-rich-paste';

function onDrop(args: DropEventData) {
  const payload = args.data;
  console.log('Drop type:', payload.type);
}

Properties ​

PropertyTypeDefaultDescription
acceptstring'all'MIME filter for accepted paste content
enableDragDropbooleanfalseEnable drag-and-drop support

accept filter ​

The accept property controls which content types are processed. Supported values:

  • 'all' — accept everything (default)
  • 'image/*' — accept all image types
  • 'image/png' — accept only PNG images
  • 'image/gif' — accept only GIF images
  • 'text/plain' — accept only plain text
  • 'application/pdf' — accept only PDF files
  • Comma-separated — e.g. 'image/*,application/pdf'

Classes ​

  • TextFieldRichPaste — extends NativeScript TextField
  • TextViewRichPaste — extends NativeScript TextView

Both classes expose the same accept, enableDragDrop properties and emit paste and drop events.

Temp File Management ​

Pasted binary content (images, files) is written to temporary files under the app's temp directory. You can clean up temp files at any time:

typescript
import { PasteInputTempFiles } from '@nstudio/nativescript-rich-paste';

// Remove all temp files created by rich paste
PasteInputTempFiles.cleanupAll();

Platform Notes ​

iOS ​

  • Uses custom UITextField/UITextView subclasses that intercept the native paste: action
  • Reads from UIPasteboard.generalPasteboard with support for images, GIFs, file URLs, and UTI-based document types
  • Drag-and-drop uses UIDropInteraction with a native delegate
  • GIF animation is preserved by detecting com.compuserve.gif UTI and writing raw data to temp files
  • Supports file reference URL resolution including Finder bookmark data

Android ​

  • Uses OnReceiveContentListener on API 31+ for unified paste and drag-and-drop handling
  • Falls back to onTextContextMenuItem interception on older API levels
  • Resolves MIME types via ContentResolver, file extension mapping, and ClipDescription
  • Validates GIF files by checking the file header magic bytes
  • Images are decoded via BitmapFactory and compressed to JPEG temp files

License ​

Apache License Version 2.0