cas-pdf-parser-react
v0.1.3
Published
React hooks and components for cas-pdf-parser — parse Indian CAS PDFs in the browser
Maintainers
Readme
cas-pdf-parser-react
React hook and drop-in component for parsing Indian CAS PDFs in the browser.
Built on top of cas-pdf-parser. Supports CAMS, KFintech, NSDL, and CDSL statements.
npm install cas-pdf-parser-react cas-pdf-parserComponents
<CASFileInput /> — drop-in UI
Zero-config file input with drag-and-drop, password field, and parse button.
import { CASFileInput } from 'cas-pdf-parser-react';
import workerSrc from 'pdfjs-dist/build/pdf.worker.min.mjs?url'; // Vite
function App() {
return (
<CASFileInput
workerSrc={workerSrc}
onParsed={(data) => console.log(data)}
onError={(msg) => console.error(msg)}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| workerSrc | string | required | Path to pdfjs worker script |
| maxFileSizeMB | number | 10 | Max file size before rejecting |
| onParsed | (data: ParseResult) => void | — | Called with parsed data on success |
| onError | (error: string) => void | — | Called with error message on failure |
| className | string | — | Class applied to the outer wrapper div |
| passwordPlaceholder | string | 'PAN / Password' | Placeholder for password field |
The component manages all state internally. Style it via className or the data-cas-status attribute:
[data-cas-status="parsing"] { opacity: 0.7; }
[data-cas-status="done"] { border-color: green; }
[data-cas-status="error"] { border-color: red; }useCASParser — hook
Full control over the parse lifecycle.
import { useCASParser } from 'cas-pdf-parser-react';
import workerSrc from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
function MyUploader() {
const { parse, data, status, error, reset } = useCASParser({
workerSrc,
maxFileSizeMB: 10,
onSuccess: (data) => console.log('Parsed:', data),
onError: (msg) => console.error('Error:', msg),
});
const handleFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) await parse(file, 'ABCDE1234F');
};
return (
<div>
<input type="file" accept=".pdf" onChange={handleFile} />
<p>Status: {status}</p>
{error && <p style={{ color: 'red' }}>{error}</p>}
{data && <pre>{JSON.stringify(data, null, 2)}</pre>}
{status === 'done' && <button onClick={reset}>Reset</button>}
</div>
);
}Options
| Option | Type | Default | Description |
|---|---|---|---|
| workerSrc | string | required | Path to pdfjs worker script |
| maxFileSizeMB | number | 10 | Max file size, rejected before parsing |
| onSuccess | (data: ParseResult) => void | — | Called on successful parse |
| onError | (error: string) => void | — | Called on failure |
Return values
| Value | Type | Description |
|---|---|---|
| parse | (file: File, password: string) => Promise<void> | Trigger a parse |
| data | ParseResult \| null | Parsed result, null until done |
| status | ParseStatus | Current state (see below) |
| error | string \| null | Error message, non-null only on error |
| reset | () => void | Reset back to idle |
Status values
| Status | Meaning |
|---|---|
| idle | Waiting for input |
| validating | Checking file size and type |
| parsing | PDF is being parsed |
| done | Parse succeeded, data is available |
| error | Parse failed, error has the message |
Setting up the pdfjs worker
The worker script must be served from your public folder. Pick the method for your bundler:
Vite
import workerSrc from 'pdfjs-dist/build/pdf.worker.min.mjs?url';Next.js (App Router)
Copy the worker to your public folder:
cp node_modules/pdfjs-dist/build/pdf.worker.min.mjs public/Then pass:
workerSrc="/pdf.worker.min.mjs"Create React App / Webpack
import { workerSrc } from 'pdfjs-dist/build/pdf.worker.entry';Full Example — CASFileInput with data display
import { useState } from 'react';
import { CASFileInput, type ParseResult } from 'cas-pdf-parser-react';
import workerSrc from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
export default function PortfolioPage() {
const [portfolio, setPortfolio] = useState<ParseResult | null>(null);
return (
<div style={{ maxWidth: 520, margin: '0 auto', padding: 24 }}>
<CASFileInput
workerSrc={workerSrc}
onParsed={setPortfolio}
onError={(msg) => alert(msg)}
/>
{portfolio && (
<div style={{ marginTop: 24 }}>
<h2>{portfolio.investor_info.name}</h2>
<p>File type: {portfolio.file_type}</p>
{'folios' in portfolio && (
<ul>
{portfolio.folios.map((folio) =>
folio.schemes.map((scheme) => (
<li key={scheme.isin ?? scheme.scheme}>
{scheme.scheme} —{' '}
{scheme.valuation.value.toFixed(2)}
</li>
))
)}
</ul>
)}
</div>
)}
</div>
);
}ParseResult shape
ParseResult is CASData | NSDLCASData. Distinguish them with:
if ('folios' in data) {
// CASData — CAMS or KFintech
data.folios[0].schemes[0].transactions
} else {
// NSDLCASData — NSDL or CDSL
data.accounts[0].equities
data.accounts[0].mutual_funds
data.nps?.schemes
}See cas-pdf-parser for the full response shape.
Peer Dependencies
| Package | Version |
|---|---|
| react | >=17 |
| cas-pdf-parser | * |
| pdfjs-dist | bundled inside cas-pdf-parser |
License
MIT
