Skip to content

feat: add linkOnPaste prop to EnrichedTextInput (iOS, Android, Web) - #746

Open
jtatar wants to merge 1 commit into
software-mansion:mainfrom
jtatar:feat/link-on-paste
Open

feat: add linkOnPaste prop to EnrichedTextInput (iOS, Android, Web)#746
jtatar wants to merge 1 commit into
software-mansion:mainfrom
jtatar:feat/link-on-paste

Conversation

@jtatar

@jtatar jtatar commented Aug 5, 2026

Copy link
Copy Markdown

Summary

Adds an opt-in linkOnPaste prop to <EnrichedTextInput /> (iOS, Android, Web).

When enabled, pasting clipboard content that is solely a URL over a
non-empty selection turns the selected text into a link pointing to that
URL, instead of replacing the selection with the pasted text. This is a common
rich-text convenience (it mirrors the "paste URL onto selected text" behavior
of editors like Google Docs, Notion, Slack).

Disabled by default (linkOnPaste={false}), so existing behavior is
unchanged for current users — the feature only activates when explicitly turned
on.

Behavior details:

  • The pasted text is recognized as a URL only when it fully matches the
    configured linkRegex (or the default link-detection patterns when
    linkRegex is not set). Clipboard text containing a URL plus other text
    (e.g. see https://example.com) is not treated as a link and falls back
    to a normal paste.
  • Scheme-less URLs (e.g. www.example.com) get an https:// prefix in the
    resulting link href, while the visible selected text is preserved.
  • Falls back to the normal paste when the selection is empty/whitespace-only,
    or when the link style cannot be applied at the selection (inside inline code
    or a code block).
  • Has no effect when link detection is disabled with linkRegex={null}.

Implementation:

  • JS: prop on the codegen spec, types.ts, default props (false), and the
    native/web EnrichedTextInput wrappers.
  • iOS: gated branch in EnrichedInputTextView's paste:; a new
    tryAddLinkAt:... (returns whether the link was applied) and
    linkURLIfEntireString: on EnrichedTextInputView; a
    matchesEntireLinkRegexWithConfig: full-string variant on LinkStyle.
  • Android: gated branch in handleTextPaste; a linkifySelectionOnPaste
    helper plus a linkExactRegex (whole-string) companion to linkRegex, and a
    setLinkOnPaste ViewManager setter.
  • Web: handleLinkOnPaste wired into the TipTap editor's handlePaste,
    reusing the existing autolink regex and the EnrichedLink.setLink command
    (which already bails out when the link style is blocked).

Test Plan

Web (automated): added a test-links linkOnPaste suite to
.playwright/tests/links.spec.ts covering: linkifying the selection with a full
URL, https:// prefixing for a scheme-less URL, and the two fallback cases
(non-bare-URL text, and no selection). Run with yarn test:e2e:web. The full
links suite (35 tests) passes.

Manual (all platforms). The example app enables linkOnPaste on its editor
screens. To verify:

  1. Type Hello world, select world.
  2. Copy a URL that the editor's linkRegex accepts and paste over the selection
    world becomes a link to that URL (visible text unchanged).
  3. Copy a scheme-less form (www.…) → the link href is prefixed with https://.
  4. Copy text that is not a bare URL (e.g. see https://…) → normal paste
    (selection replaced, not linkified).
  5. Set linkOnPaste={false} → step 2 becomes a normal paste again (selection
    replaced), confirming the default/off behavior is unchanged.

yarn typecheck, yarn lint, and yarn lint-clang all pass; the Android
Gradle lintVerify builds the module cleanly.

Compatibility

OS Implemented
iOS
Android
Web

Checklist

  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

Copilot AI review requested due to automatic review settings August 5, 2026 13:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an opt-in linkOnPaste prop to EnrichedTextInput across iOS/Android/Web so that pasting a bare URL over a non-empty selection linkifies the selected text instead of replacing it, matching common rich-text editor behavior while keeping default behavior unchanged.

Changes:

  • Introduces the linkOnPaste prop end-to-end (types/defaults, native codegen spec, native + web wrappers).
  • Implements platform-specific paste interception/linkification logic (iOS/Android/Web) with “whole-string URL” detection and scheme-less https:// normalization.
  • Updates example apps and adds Playwright E2E coverage for Web.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/web/linkOnPaste.ts Implements web linkOnPaste paste handler and URL normalization.
src/web/EnrichedTextInput.tsx Wires handleLinkOnPaste into TipTap paste handling and threads prop via refs.
src/utils/EnrichedTextInputDefaultProps.ts Adds linkOnPaste: false default.
src/types.ts Documents and exposes linkOnPaste?: boolean on the public props interface.
src/spec/EnrichedTextInputNativeComponent.ts Adds linkOnPaste?: boolean to codegen native props.
src/native/EnrichedTextInput.tsx Passes linkOnPaste through the native wrapper to the native component.
ios/styles/LinkStyle.mm Adds “match entire string” link-regex helper for bare-URL paste detection.
ios/interfaces/StyleHeaders.h Exposes the new LinkStyle “entire string” matcher in headers.
ios/EnrichedTextInputView.mm Adds tryAddLinkAt... (BOOL return) and linkURLIfEntireString: helper for iOS paste flow.
ios/EnrichedTextInputView.h Exposes linkOnPaste ivar and new helper method declarations.
ios/enrichedInputTextView/EnrichedInputTextView.mm Adds iOS paste: branch for linkifying selection + refactors plain-text extraction helper.
docs/INPUT_API_REFERENCE.md Documents the new linkOnPaste prop behavior and platform support.
apps/example/src/screens/TestScreen.tsx Enables linkOnPaste in the native example screen for manual testing.
apps/example/src/screens/DevScreen.tsx Enables linkOnPaste in the native dev screen for manual testing.
apps/example-web/src/testScreens/TestLinks.tsx Enables linkOnPaste in the web example test screen.
apps/example-web/src/App.tsx Enables linkOnPaste in the main web example app configuration.
android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputViewManager.kt Adds ViewManager setter for linkOnPaste.
android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt Implements Android selection-linkify-on-paste logic + whole-string regex companion.
.playwright/tests/links.spec.ts Adds E2E suite covering linkOnPaste success + fallback cases.
.playwright/helpers/clipboard.ts Adds helper to paste over an existing selection without collapsing it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ios/enrichedInputTextView/EnrichedInputTextView.mm
Comment thread ios/EnrichedTextInputView.mm Outdated
@jtatar
jtatar force-pushed the feat/link-on-paste branch from c404c81 to b0a05c2 Compare August 5, 2026 13:20
When enabled, pasting clipboard content that is solely a URL over a
non-empty selection turns the selected text into a link pointing to that
URL instead of replacing the selection. Disabled by default.

- Recognizes a URL only when it fully matches linkRegex (or the default
  link-detection patterns); scheme-less URLs get an https:// prefix.
- Falls back to a normal paste for empty/whitespace selections, non-bare-URL
  clipboard text, or when the link style is blocked (inline code, code block).
- No effect when link detection is disabled via linkRegex={null}.

JS: prop on the codegen spec, types, default props, native/web wrappers.
iOS: gated branch in paste:, tryAddLinkAt:/linkURLIfEntireString: on the view,
     matchesEntireLinkRegexWithConfig: on LinkStyle.
Android: gated branch in handleTextPaste, linkifySelectionOnPaste helper,
     linkExactRegex companion, setLinkOnPaste ViewManager setter.
Web: handleLinkOnPaste wired into TipTap handlePaste.

Docs (INPUT_API_REFERENCE), example apps and a Playwright linkOnPaste suite
(4 cases, all green; full links suite 35 passed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jtatar
jtatar force-pushed the feat/link-on-paste branch from b0a05c2 to 3770d52 Compare August 5, 2026 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants