Using Clipboard
Read from and write to the system clipboard — copy, paste and detect, with the platform quirks handled for you.
The package exports a single frozen Clipboard object. There is nothing to instantiate and no permissions to request — sigx prebuild auto-discovers and links the native module.
Basic usage
Import the named Clipboard export and call its methods directly.
import { Clipboard } from '@sigx/lynx-clipboard';
// Write — asynchronous, rejects if the native write fails
await Clipboard.setString('Hello, world!');
// Read — asynchronous, resolves to "" when empty
const text = await Clipboard.getString();
// Detect — asynchronous boolean
const isPopulated = await Clipboard.hasString();
All three cross the native bridge asynchronously and return promises. setString rejects with a SigxError (code: 'native_error') when the platform refuses the write — on Android a clip over the binder transaction limit does — so await it and handle the rejection. Neither read rejects on an empty clipboard — getString resolves to "" and hasString resolves to false.
Copy on tap
The common case: copy a value when the user taps a button. Flip the "Copied!" state only after the promise resolves, so a failed write does not claim success.
import { Clipboard } from '@sigx/lynx-clipboard';
import { signal } from '@sigx/lynx';
function CopyButton({ value }: { value: string }) {
const copied = signal(false);
const onTap = async () => {
try {
await Clipboard.setString(value);
copied.set(true);
} catch (err) {
// SigxError with code 'native_error' — the platform refused the write
console.warn('copy failed', err);
}
};
return (
<view bindtap={onTap}>
<text>{() => (copied() ? 'Copied!' : 'Copy')}</text>
</view>
);
}
Passing null or undefined is coerced to an empty string natively, so a missing value clears the clipboard rather than throwing.
Paste on explicit user intent
Read the clipboard only in response to a deliberate action such as a Paste button.
import { Clipboard } from '@sigx/lynx-clipboard';
import { signal } from '@sigx/lynx';
function PasteField() {
const draft = signal('');
const onPaste = async () => {
const text = await Clipboard.getString();
if (text) draft.set(text);
};
return (
<view>
<text>{draft}</text>
<view bindtap={onPaste}>
<text>Paste</text>
</view>
</view>
);
}
On iOS 14 and later, any clipboard read surfaces a system "Pasted from <App>" toast. Do not poll getString on a timer or read on mount — call it only on explicit user intent, or the toast will fire repeatedly and feel like a privacy leak.
Enable a paste button only when content exists
Use hasString to gate UI without triggering the iOS paste toast — hasString reports presence without reading the contents.
import { Clipboard } from '@sigx/lynx-clipboard';
import { signal } from '@sigx/lynx';
function SmartPaste() {
const canPaste = signal(false);
// Check once, on a deliberate event (e.g. when a menu opens).
const refresh = async () => {
canPaste.set(await Clipboard.hasString());
};
return (
<view bindtap={refresh}>
<text>{() => (canPaste() ? 'Paste available' : 'Nothing to paste')}</text>
</view>
);
}
Guarding against a missing native module
If the native module is not linked into the current build, isAvailable returns false. Check it before exposing clipboard UI so the rest of your app degrades gracefully.
import { Clipboard } from '@sigx/lynx-clipboard';
if (Clipboard.isAvailable()) {
await Clipboard.setString('ready');
} else {
// Module not linked — run `sigx prebuild` and rebuild the app.
}
isAvailable is synchronous and safe to call at any time; the read and write methods assume the module is present.
Notes
- No permissions are required. The module declares no Android permissions and no iOS
Info.plistkeys. - On Android the copied clip is labelled
sigx-lynx-go;hasStringrequires a primary clip with atext/*MIME type. - See the API reference for full signatures, and Installation for project setup.
