Files
omni-tools/src/pages/tools/pdf/split-pdf/index.tsx

171 lines
4.9 KiB
TypeScript
Raw Normal View History

2025-03-26 05:43:59 +00:00
import { Box, Typography } from '@mui/material';
2025-04-27 22:52:03 +05:30
import { useEffect, useState } from 'react';
2025-03-26 05:43:59 +00:00
import ToolFileResult from '@components/result/ToolFileResult';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { parsePageRanges, splitPdf } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { PDFDocument } from 'pdf-lib';
2025-03-26 05:55:53 +00:00
import ToolPdfInput from '@components/input/ToolPdfInput';
2025-07-12 23:02:35 -07:00
import { useTranslation } from 'react-i18next';
2025-03-26 05:43:59 +00:00
type InitialValuesType = {
pageRanges: string;
};
const initialValues: InitialValuesType = {
pageRanges: ''
};
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Extract Specific Pages',
description: 'Extract pages 1, 5, 6, 7, and 8 from a PDF document.',
sampleText: '',
sampleResult: '',
sampleOptions: {
pageRanges: '1,5-8'
}
},
{
title: 'Extract First and Last Pages',
description: 'Extract only the first and last pages from a PDF document.',
sampleText: '',
sampleResult: '',
sampleOptions: {
pageRanges: '1,10'
}
},
{
title: 'Extract a Range of Pages',
description: 'Extract a continuous range of pages from a PDF document.',
sampleText: '',
sampleResult: '',
sampleOptions: {
pageRanges: '3-7'
}
}
];
export default function SplitPdf({ title }: ToolComponentProps) {
2025-07-13 13:01:02 +01:00
const { t } = useTranslation('pdf');
2025-03-26 05:43:59 +00:00
const [input, setInput] = useState<File | null>(null);
const [result, setResult] = useState<File | null>(null);
const [isProcessing, setIsProcessing] = useState<boolean>(false);
const [totalPages, setTotalPages] = useState<number>(0);
const [pageRangePreview, setPageRangePreview] = useState<string>('');
// Get the total number of pages when a PDF is uploaded
useEffect(() => {
const getPdfInfo = async () => {
if (!input) {
setTotalPages(0);
return;
}
try {
const arrayBuffer = await input.arrayBuffer();
const pdf = await PDFDocument.load(arrayBuffer);
setTotalPages(pdf.getPageCount());
} catch (error) {
console.error('Error getting PDF info:', error);
setTotalPages(0);
}
};
getPdfInfo();
}, [input]);
const onValuesChange = (values: InitialValuesType) => {
const { pageRanges } = values;
if (!totalPages || !pageRanges?.trim()) {
setPageRangePreview('');
return;
}
try {
const count = parsePageRanges(pageRanges, totalPages).length;
2025-07-13 13:01:02 +01:00
setPageRangePreview(t('splitPdf.pageExtractionPreview', { count }));
2025-03-26 05:43:59 +00:00
} catch (error) {
setPageRangePreview('');
}
};
const compute = async (values: InitialValuesType, input: File | null) => {
if (!input) return;
try {
setIsProcessing(true);
const splitResult = await splitPdf(input, values.pageRanges);
setResult(splitResult);
} catch (error) {
throw new Error('Error splitting PDF:' + error);
} finally {
setIsProcessing(false);
}
};
return (
<ToolContent
title={title}
input={input}
setInput={setInput}
initialValues={initialValues}
compute={compute}
exampleCards={exampleCards}
inputComponent={
2025-03-26 05:55:53 +00:00
<ToolPdfInput
2025-03-26 05:43:59 +00:00
value={input}
2025-05-13 22:52:13 +01:00
onChange={setInput}
2025-03-26 05:43:59 +00:00
accept={['application/pdf']}
2025-07-13 13:01:02 +01:00
title={t('splitPdf.inputTitle')}
2025-03-26 05:43:59 +00:00
/>
}
resultComponent={
<ToolFileResult
2025-07-13 13:01:02 +01:00
title={t('splitPdf.resultTitle')}
2025-03-26 05:43:59 +00:00
value={result}
extension={'pdf'}
loading={isProcessing}
2025-07-13 13:01:02 +01:00
loadingText={t('splitPdf.extractingPages')}
2025-03-26 05:43:59 +00:00
/>
}
getGroups={({ values, updateField }) => [
{
2025-07-13 13:01:02 +01:00
title: t('splitPdf.pageSelection'),
2025-03-26 05:43:59 +00:00
component: (
<Box>
{totalPages > 0 && (
<Typography variant="body2" sx={{ mb: 1 }}>
2025-07-13 13:01:02 +01:00
{t('splitPdf.pdfPageCount', { count: totalPages })}
2025-03-26 05:43:59 +00:00
</Typography>
)}
<TextFieldWithDesc
value={values.pageRanges}
onOwnChange={(val) => {
updateField('pageRanges', val);
}}
2025-07-13 13:01:02 +01:00
description={t('splitPdf.pageRangesDescription')}
placeholder={t('splitPdf.pageRangesPlaceholder')}
2025-03-26 05:43:59 +00:00
/>
{pageRangePreview && (
<Typography
variant="body2"
sx={{ mt: 1, color: 'primary.main' }}
>
{pageRangePreview}
</Typography>
)}
</Box>
)
}
]}
onValuesChange={onValuesChange}
toolInfo={{
2025-07-13 13:01:02 +01:00
title: t('splitPdf.toolInfo.title'),
description: t('splitPdf.toolInfo.description')
2025-03-26 05:43:59 +00:00
}}
/>
);
}