@delement/sig
v1.0.0
Published
Signature Electronic Signature Widget for CryptoPro CAdES
Maintainers
Readme
Signature Electronic Signature Widget for CryptoPro CAdES
@delement/sig is a React widget for qualified electronic signatures through CryptoPro CAdES Plugin. Upload documents, select a certificate, and receive verified .sig files.
The npm package contains ready-to-use JavaScript and TypeScript declarations. UI components, styles, icons, and the CryptoPro API are bundled.
Install Signature
npm i @delement/sigRequires matching React/ReactDOM versions >=19, an installed CryptoPro CAdES Plugin, and a valid certificate with a private key.
Quick start
import { Signature } from "@delement/sig";
export const DefaultSignature = () => (
<form>
<Signature
filesUploader={{ name: "documents" }}
onSuccess={(event) => console.log(event.data.signatures)}
onError={(event) => console.error(event.data)}
/>
</form>
);By default, the widget accepts PDFs and creates detached CAdES BES signatures in Base64. Uploaded documents and generated signatures are available through the named file input and the form's FormData.
After complete success, the uploader stays disabled, the action becomes Clear, and a localized success modal opens. The named file input stays enabled so the parent form can submit both documents and signatures. Closing the success modal keeps the files locked. Clear removes every file, including signatures, and resets the success state; replacing filesUploader.items also unlocks the uploader.
Configuration
All props are optional; import TSignatureProps for the complete typed contract.
| Prop | Purpose |
| --- | --- |
| filesUploader | Input name, allowed fileTypes (default: ["pdf"]), maxSize (5 MB total), and maxFiles (2, including signatures). Increase the file limit for multiple documents. |
| filesUploader.items | Initial File objects or URL descriptors. Keep the array stable; replacing it resets files and cancels pending signing. |
| cryptoPro | signedFileTypes (uploader types by default) and signatureFileTypes (default: "sig"). |
| signatureOptions | Signature mode, profile, attributes, and output format; see below. |
| certificateFilter | Keeps certificates matching (certificate) => boolean. |
| onSuccess | Receives TSignatureSuccessEvent after a complete batch is ready in the file input; event.data contains { files, signatures, certificate }. |
| onError | Receives TSignatureErrorEvent; event.data contains a localized UI, file, plugin, certificate, or signing error. Native CryptoPro codes are retained when supplied. |
| locales | Russian/English translation overrides. |
| helpSlot | Custom help content. null/false keep the default link; an empty fragment hides it. |
| children | Custom controls using useSignature. |
| extraAttrs, extraClasses | Root HTML attributes and class modifiers. Keep the default baseClass: "signature" for built-in styles. |
Cancellation does not emit callbacks. A partial batch failure does not call onSuccess; completed signatures remain available. Upload/URL errors are displayed in the widget. An empty CryptoPro certificate list calls onError; an empty filtered list does not.
Success and error events
Each callback receives one native CustomEvent: signature:success or signature:error, with cancelable: true. Its detail and additional readonly data field hold the same payload: TSignatureSuccessResult for success, a message string for errors. Both event types are exported.
Call event.preventDefault() synchronously in onSuccess to handle success yourself. It suppresses the uploader lock, Clear action and success modal. Verified files are already in the named input and FormData; useSignature().signature remains available, isSigned stays false, and signing can run again after modal closure. In onError, preventDefault() suppresses the error modal while keeping the message in useSignature().status. Certificate-loading errors still appear below Select.
import { Signature, type TSignatureSuccessEvent, type TSignatureErrorEvent } from "@delement/sig";
const handleSuccess = (event: TSignatureSuccessEvent) => {
event.preventDefault();
console.log(event.data.files, event.data.signatures, event.data.certificate);
};
const handleError = (event: TSignatureErrorEvent) => {
event.preventDefault();
console.error(event.data);
};
export const CustomSignatureEvents = () => (
<form><Signature filesUploader={{ name: "documents" }} onSuccess={handleSuccess} onError={handleError} /></form>
);Call preventDefault() before the first await; the widget chooses the default action immediately after the callback returns. Aborting, clearing files and dismissing errors do not emit success/error callbacks.
Signature options
Use the exported TSignatureOptions type for signatureOptions or the CryptoProManager constructor.
| Option | Values | Default |
| --- | --- | --- |
| mode | "detached", "attached" | "detached" |
| profile | "cades-bes", "cades-t", "cades-x-long-type-1", "pkcs7" | "cades-bes" |
| certificateInclude | "signer", "chain-except-root", "whole-chain" | "signer" |
| checkCertificate | Preliminary certificate-chain validation | true |
| tsaAddress | HTTP(S) timestamp service for T/X profiles; rejected for BES/PKCS7 | None |
| signedAttributes | signingTime, documentName, documentDescription; object or synchronous (file: File) => object | None |
| outputFormat | "base64", "der" | "base64" |
| displayData | Device display location: "none", "content", "attribute" | "none" |
Attached CMS includes the original bytes; it does not produce PDF/PAdES. T/X profiles require a working timestamp service and the applicable CryptoPro licenses. Invalid settings are rejected without a profile fallback. checkCertificate: false does not disable date, private-key, or signature-result checks. signingTime is claimed signer time, not a trusted timestamp; device display depends on the hardware.
The selected settings apply to the whole batch. Updates affect the next signing session.
Manual signing
Import useSignature inside a child of <Signature>. It exposes signable files, filtered certificates, the last successful signature batch, status, isSigned, isSigning, isCertificatesLoading, sign, abort, and clear.
status is { type: "progress", stage, message }, { type: "error", message }, or null. message is localized and matches the widget. Stages are loading-certificates, preparing, checking-certificate, creating-signature, and verifying-signature; signing stages repeat for each file. Waiting for certificate selection, completion, and cancellation clear the status. Errors remain until dismissal or another session; progress does not trigger onError.
import { Signature, useSignature, type TSignatureStatus } from "@delement/sig";
const StatusMessage = ({ status }: { status: TSignatureStatus | null }) => <p role="status">{status?.message}</p>;
const SigningStatus = () => {
const { status, abort, clear, isSigned, isSigning } = useSignature();
return <>
<StatusMessage status={status} />
<button type="button" disabled={!isSigning} onClick={abort}>Cancel</button>
<button type="button" disabled={isSigning || !isSigned} onClick={clear}>Clear signed files</button>
</>;
};
export const SignatureWithStatus = () => <Signature><SigningStatus /></Signature>;sign() opens certificate selection; sign(certificate) signs directly with that certificate. It returns void; receive the result through event.data in onSuccess or hook state. certificateFilter limits the selection list, not explicitly supplied certificates. Both signing paths are blocked while isSigned is true; new sessions remain blocked until standard modals finish closing. Closing selection or replacing files cancels pending signing.
isSigned means the standard success UI was applied; a prevented success can have a non-null signature with isSigned: false. clear() removes all files from the uploader and named input, cancels any active session and resets signature/isSigned without callbacks. Replacing items unlocks the uploader and resets isSigned while preserving the historical signature; use the current files/input for form submission. The standard signing/Clear action stays disabled until modal closure completes.
abort() cancels certificate discovery and the remaining signing steps, closes selection and clears the session status without onError/onSuccess. Existing files, inserted signatures and the last successful batch remain; an already signed batch stays locked. Closing selection, replacing files and unmounting also abort the manager; replacing items still replaces the files. A cancelled active session can restart once modal closure finishes. A native plugin call already in progress may finish later; its result is ignored.
CryptoPro without the widget
Use CryptoProManager in the browser without mounting the widget. Each instance has its own signature settings.
import { CryptoProManager } from "@delement/sig";
export async function signDocument(file: File): Promise<File> {
const manager = new CryptoProManager();
const [certificate] = await manager.getUserCertificates();
// Select a certificate in your own application.
if (!certificate) throw new Error("No certificates available");
return manager.getSignatureFile(certificate, file);
}getSignatureFile(certificate, file, fileType = "sig", getLocale?, options?) returns a Base64/DER File. getSignature(certificate, content, getLocale?, options?) returns verified Base64 and accepts a File, a Base64 string, or { type: "base64" | "text", value }. Explicit operation options replace constructor settings.
getVerifySignature(signatureFile, { mode, profile, format?, original? }, getLocale?) verifies an external signature. Specify its mode and profile; format defaults to "base64". Detached signatures require original; attached signatures reject it. A successful result contains isSignVerify: true, signers, and certificates; failure contains isSignVerify: false and message.
getBinaryFileSignature(file) reads file bytes as Base64. getDetachedSignature and getVerifyDetachedSignature always use detached BES/Base64, independently of constructor settings. Constructor validation and signing operations can fail; handle errors in your application.
manager.abort() cancels all active operations of that instance. Their promises reject promptly with an Error named AbortError, including verification methods that normally return a failed verification result. File reads abort; certificate enumeration and later native calls stop, and acquired stores close. An ongoing native call or shared plugin loading may finish later. Other instances and discovered manager.certificates are preserved; later method calls start fresh operations. TSignatureCryptoManager defines the three-method contract: getUserCertificates, getBinaryFileSignature, and getDetachedSignature.
Localisation
Initial language follows the document's lang; Russian is the fallback. locales accepts { group: { key: [ruValue, enValue] } }, for example locales={{ signature: { signButton: ["Подписать", "Sign"] } }}. Values can be strings or translation functions; omitted values keep defaults. Use plain text for error overrides.
Translations are shared between widgets: the latest explicit locales applies to all instances. Language/locale updates preserve files and active signing.
The status region below the certificate Select announces loading, actual signing stages, and certificate-loading errors. Select shows a loading indicator throughout signing. Override progress messages with the signature keys certificatesLoading, preparing, checking-certificate, creating-signature, and verifying-signature, for example locales={{ signature: { "checking-certificate": ["Проверка сертификата…", "Checking certificate…"] } }}. Progress text updates live; existing errors retain their original text. Signing failures open the error modal unless prevented by onError.
Success uses signature.successTitle, signingSuccess for one file and signingBatchSuccess for several files; the Clear button uses clearButton. The certificate, error and success modals stay mounted and follow Russian/English language and locale updates.
React SSR renders a loading state; signing runs in the browser. Pass identical props and deterministic translation functions on the server and client.
Styling widget
The status region below the certificate Select uses the signature__modalStatus class.
Override --signature… CSS properties on .signature, such as --signatureFilesUploaderZoneBg for the upload zone background. Use .signature.signature when your stylesheet loads before the bundled styles.
The Clear action has a transparent background and colored text/border. Its separate --signatureClearBtn… group uses the same suffixes as --signatureBtn…, including Bg, TextColor, BorderColor, BorderRadius, Hover…, Active… and Disabled…. Layout and typography inherit the signing-button defaults unless overridden; Clear colors have their own defaults. Use SizeMediumHeight and SizeMediumHorPaddings to set its height and horizontal padding.
.signature {
--signatureClearBtnTextColor: #6b3757;
--signatureClearBtnBorderColor: #6b3757;
--signatureClearBtnHoverTextColor: #4a233b;
--signatureClearBtnHoverBorderColor: #4a233b;
--signatureClearBtnSizeMediumHeight: 48px;
--signatureClearBtnBorderRadius: 12px;
}