@korala/react
React components and hooks for embedding Korala document signing in your application.
Installation
pnpm add @korala/react
Usage
KoralaSigner Component
The main component for embedding the signing experience:
import { KoralaSigner } from '@korala/react';
function SigningPage({ signingToken }: { signingToken: string }) {
return (
<KoralaSigner
token={signingToken}
signingUrl="https://sign.yourdomain.com" // Optional, defaults to env var
className="w-full h-[600px]"
onReady={() => console.log('Embed ready')}
onLoaded={(data) => console.log('Document loaded:', data)}
onViewed={(data) => console.log('Document viewed:', data)}
onFieldFilled={(data) => console.log('Field filled:', data)}
onSigned={(data) => console.log('Document signed:', data)}
onDeclined={(data) => console.log('Document declined:', data)}
onError={(data) => console.error('Error:', data)}
/>
);
}
Props
token | string | Yes | The signer's access token |
signingUrl | string | No | Base URL of the signing app. Defaults to NEXT_PUBLIC_KORALA_SIGNING_URL env var |
className | string | No | CSS class for the iframe |
style | CSSProperties | No | Inline styles for the iframe |
allowedOrigins | string[] | No | Override the signing URL origin used for postMessage validation |
onReady | (data) => void | No | Called when embed is initialized |
onLoaded | (data) => void | No | Called when document is loaded |
onViewed | (data) => void | No | Called when signer views the document |
onFieldFilled | (data) => void | No | Called when a field is filled |
onSigned | (data) => void | No | Called when signing is complete |
onDeclined | (data) => void | No | Called when signer declines |
onError | (data) => void | No | Called on errors |
useKoralaEvents Hook
Alternative to callbacks - listen to all events via a hook:
import { useKoralaEvents } from '@korala/react';
function SigningStatus() {
const { status, events, lastEvent } = useKoralaEvents({
signingUrl: 'https://app.korala.ai',
});
return (
<div>
<p>Status: {status}</p>
<p>Events received: {events.length}</p>
</div>
);
}
Returns:
status: 'loading' | 'ready' | 'loaded' | 'viewed' | 'signing' | 'signed' | 'declined' | 'error'
events: Array of all received events
lastEvent: Most recent event
clearEvents: Function to clear stored events
useKoralaSignerRef Hook
Drive the signing iframe from your own UI.
import { KoralaSigner, useKoralaSignerRef } from '@korala/react';
function ControlledSigner({ token }: { token: string }) {
const { ref, close, getStatus, gotoField, gotoPage, getFields } =
useKoralaSignerRef();
return (
<>
<KoralaSigner ref={ref} token={token} />
<button onClick={() => gotoField()}>Go to next field</button>
</>
);
}
close() | None | Closes the signing session |
getStatus() | KoralaGetStatusResult | Document status and progress counts |
gotoField(fieldId?) | KoralaGotoFieldResult | Scrolls to a field; omit the id for the next unfilled one |
gotoPage(pageNumber) | KoralaGotoPageResult | Scrolls to a 1-based page |
getFields() | KoralaGetFieldsResult | Every field: type, label, page, required, filled |
getFields plus gotoField is what you need to build next/previous controls
or a field list in your own chrome. This helps on long agreements, where the
signature block is usually in the last third of the document.
Embeds hide the signing viewer's page and previous/next-field controls by
default. Your app can drive the viewer with gotoField and gotoPage, or pass
showNavigation to KoralaSigner to render Korala's controls. Direct signing
links show the controls.
The SDK and the signing app ship separately, so your app can be on a newer SDK
than the page it embeds. The ready event's commands array lists what the
viewer understands. Feature-detect against it because older signing apps omit it and
support only close and get_status.
Navigation moves the signer and nothing else. These methods will not fill a
field, tick a checkbox or open the signature pad. Your app cannot know what the
signer can see, so it takes them to the field and leaves the acting to
them. gotoField resolves once the viewer has stopped scrolling and reports
arrived, unreachable, or not_found.
Event Data Types
LoadedEventData
{
documentId: string;
documentName: string;
signerName: string;
signerEmail: string;
totalFields: number;
requiredFields: number;
}
SignedEventData
{
documentId: string;
signerId: string;
signedAt: string;
}
DeclinedEventData
{
documentId: string;
signerId: string;
reason?: string;
declinedAt: string;
}
ErrorEventData
{
code: string;
message: string;
recoverable: boolean;
}
Environment Variables
Set in your .env.local:
NEXT_PUBLIC_KORALA_SIGNING_URL=http://localhost:3003