react-pdf-levelup 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -0
- package/fn/aggAlias.js +21 -0
- package/fn/moveComponents.js +129 -0
- package/fn/postinstall.js +66 -0
- package/fn/upVersion.js +12 -0
- package/fn/updateTsconfig.js +10 -0
- package/next.config.mjs +6 -0
- package/package.json +39 -0
- package/public/bg-login.jpg +0 -0
- package/public/codigo_guardado.js +1 -0
- package/public/css/style.css +751 -0
- package/public/dboard/logo.png +0 -0
- package/public/favicon.ico +0 -0
- package/public/fonts/TimesNewerRoman-Bold.otf +0 -0
- package/public/fonts/TimesNewerRoman-BoldItalic.otf +0 -0
- package/public/fonts/TimesNewerRoman-Italic.otf +0 -0
- package/public/fonts/TimesNewerRoman-Regular.otf +0 -0
- package/public/header-pdf.jpg +0 -0
- package/public/home/bgHome.jpg +0 -0
- package/public/home/bgHome2.jpg +0 -0
- package/public/home/download.jpg +0 -0
- package/public/home/undraw_elements_re_25t9.svg +1 -0
- package/public/home/undraw_project_completed_re_jr7u.svg +1 -0
- package/public/home/undraw_shared_goals_re_jvqd.svg +1 -0
- package/public/home/undraw_spread_love_re_v3cl.svg +1 -0
- package/public/home/undraw_target_re_fi8j.svg +1 -0
- package/public/home/undraw_visionary_technology_re_jfp7.svg +1 -0
- package/public/logo.png +0 -0
- package/public/marca/logo.svg +1 -0
- package/src/components/PDF/components/DocumentoTemplate.tsx +140 -0
- package/src/components/PDF/components/PDFContent.tsx +192 -0
- package/src/components/PDF/core/Etiquetas.tsx +152 -0
- package/src/components/PDF/core/Grid.tsx +101 -0
- package/src/components/PDF/core/Img.tsx +22 -0
- package/src/components/PDF/core/LayoutPDF.tsx +186 -0
- package/src/components/PDF/core/Listas.tsx +10 -0
- package/src/components/PDF/core/MakePDF.tsx +50 -0
- package/src/components/PDF/core/PageElements.tsx +50 -0
- package/src/components/PDF/core/Position.tsx +33 -0
- package/src/components/PDF/core/Tablet.tsx +121 -0
- package/src/components/PDF/core/index.tsx +56 -0
- package/src/components/PDF/lib/pdfParser.ts +620 -0
- package/src/components/PDF/services/apiService.ts +17 -0
- package/src/components/PDF/templates/AllTemplate.tsx +134 -0
- package/src/components/PDF/templates/BusinessCardTemplate.tsx +139 -0
- package/src/components/PDF/templates/CertificateTemplate.tsx +31 -0
- package/src/components/PDF/templates/HeaderFooterTemplate.tsx +61 -0
- package/src/components/PDF/templates/InvoiceTemplate.tsx +53 -0
- package/src/components/PDF/templates/ProposalTemplate.tsx +246 -0
- package/src/components/PDF/templates/ReportTemplate.tsx +57 -0
- package/src/components/PDF/templates/ResumeTemplate.tsx +170 -0
- package/src/components/PDF/templates/TablasTemplate.tsx +307 -0
- package/src/components/PDF/templates/index.ts +9 -0
- package/src/components/PDF/view/ColorPicker.tsx +147 -0
- package/src/components/PDF/view/Header.tsx +102 -0
- package/src/components/PDF/view/HomePDF.tsx +177 -0
- package/src/components/PDF/view/SettingsPanel.tsx +703 -0
- package/src/pages/AllTemplate.tsx +53 -0
- package/src/pages/Documento2.tsx +45 -0
- package/src/pages/_app.tsx +6 -0
- package/src/pages/_document.tsx +13 -0
- package/src/pages/api/generatePDF.ts +74 -0
- package/src/pages/api/hello.ts +13 -0
- package/src/pages/api/readFile.ts +18 -0
- package/src/pages/api/readTemplateFile.ts +26 -0
- package/src/pages/api/save.ts +22 -0
- package/src/pages/api/saveFile.ts +20 -0
- package/src/pages/index.tsx +13 -0
- package/src/pages/template/[template].tsx +250 -0
- package/tsconfig.json +63 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import type React from "react"
|
|
3
|
+
import { LayoutPDF, P, H1, Table, Thead, Tbody, Tr, Th, Td, H2 } from "../components/PDF/core"
|
|
4
|
+
|
|
5
|
+
const InvoiceTemplate: React.FC = () => {
|
|
6
|
+
return (
|
|
7
|
+
<LayoutPDF>
|
|
8
|
+
<H1>Factura</H1>
|
|
9
|
+
<P>Factura No: INV-001</P>
|
|
10
|
+
<P>Fecha: {new Date().toLocaleDateString()}</P>
|
|
11
|
+
|
|
12
|
+
<H2>Detalles del cliente</H2>
|
|
13
|
+
<P>Nombre: John Doe</P>
|
|
14
|
+
<P>Dirección: 123 Calle Principal, Ciudad</P>
|
|
15
|
+
|
|
16
|
+
<Table>
|
|
17
|
+
<Thead>
|
|
18
|
+
<Tr>
|
|
19
|
+
<Th>Descripción</Th>
|
|
20
|
+
<Th>Cantidad</Th>
|
|
21
|
+
<Th>Precio unitario</Th>
|
|
22
|
+
<Th>Total</Th>
|
|
23
|
+
</Tr>
|
|
24
|
+
</Thead>
|
|
25
|
+
<Tbody>
|
|
26
|
+
<Tr>
|
|
27
|
+
<Td>Producto A</Td>
|
|
28
|
+
<Td>2</Td>
|
|
29
|
+
<Td>$50.00</Td>
|
|
30
|
+
<Td>$100.00</Td>
|
|
31
|
+
</Tr>
|
|
32
|
+
<Tr>
|
|
33
|
+
<Td>Producto B</Td>
|
|
34
|
+
<Td>1</Td>
|
|
35
|
+
<Td>$75.00</Td>
|
|
36
|
+
<Td>$75.00</Td>
|
|
37
|
+
</Tr>
|
|
38
|
+
<Tr>
|
|
39
|
+
<Td style={{ fontWeight: "bold" }}>Total</Td>
|
|
40
|
+
<Td></Td>
|
|
41
|
+
<Td></Td>
|
|
42
|
+
<Td style={{ fontWeight: "bold" }}>$175.00</Td>
|
|
43
|
+
</Tr>
|
|
44
|
+
</Tbody>
|
|
45
|
+
</Table>
|
|
46
|
+
|
|
47
|
+
<P style={{ marginTop: 20 }}>Gracias por su compra.</P>
|
|
48
|
+
</LayoutPDF>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default InvoiceTemplate
|
|
53
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
import type React from "react"
|
|
3
|
+
import { LayoutPDF, P, H1, H2, BR } from "../core"
|
|
4
|
+
|
|
5
|
+
type DocumentoTemplateProps = {}
|
|
6
|
+
|
|
7
|
+
const DocumentoTemplate: React.FC<DocumentoTemplateProps> = () => {
|
|
8
|
+
return (
|
|
9
|
+
<LayoutPDF size="A4" orientation="portrait">
|
|
10
|
+
<H1>Ejemplo de documento con saltos de línea</H1>
|
|
11
|
+
<P>
|
|
12
|
+
Este es un ejemplo de documento con saltos de línea.
|
|
13
|
+
<BR />
|
|
14
|
+
Este texto aparece después de un salto de línea.
|
|
15
|
+
</P>
|
|
16
|
+
<P>
|
|
17
|
+
Puedes usar múltiples saltos de línea:
|
|
18
|
+
<BR />
|
|
19
|
+
<BR />
|
|
20
|
+
Como puedes ver, hay doble espacio aquí.
|
|
21
|
+
</P>
|
|
22
|
+
|
|
23
|
+
<H2>Tamaños de papel disponibles:</H2>
|
|
24
|
+
<P>
|
|
25
|
+
• A0 - 841 × 1189 mm (muy grande)
|
|
26
|
+
<BR />• A1 - 594 × 841 mm
|
|
27
|
+
<BR />• A2 - 420 × 594 mm
|
|
28
|
+
<BR />• A3 - 297 × 420 mm
|
|
29
|
+
<BR />• A4 - 210 × 297 mm (tamaño estándar)
|
|
30
|
+
<BR />• A5 - 148 × 210 mm
|
|
31
|
+
<BR />• A6 - 105 × 148 mm
|
|
32
|
+
<BR />• A7 - 74 × 105 mm
|
|
33
|
+
<BR />• A8 - 52 × 74 mm
|
|
34
|
+
<BR />• A9 - 37 × 52 mm
|
|
35
|
+
<BR />• A10 - 26 × 37 mm (muy pequeño)
|
|
36
|
+
</P>
|
|
37
|
+
|
|
38
|
+
<P>Puedes cambiar el tamaño del papel en la configuración del documento.</P>
|
|
39
|
+
<P>Prueba a seleccionar diferentes tamaños para ver cómo cambia el documento.</P>
|
|
40
|
+
</LayoutPDF>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default DocumentoTemplate
|
|
45
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { NextApiRequest, NextApiResponse } from "next"
|
|
2
|
+
import { renderToStream } from "@react-pdf/renderer"
|
|
3
|
+
import * as templates from "../../components/PDF/templates"
|
|
4
|
+
|
|
5
|
+
// Import createElement from react-pdf
|
|
6
|
+
import { createElement } from "react"
|
|
7
|
+
|
|
8
|
+
export const config = {
|
|
9
|
+
api: {
|
|
10
|
+
responseLimit: false,
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
15
|
+
if (req.method !== "GET") {
|
|
16
|
+
return res.status(405).json({ error: "Method not allowed" })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
// Get template name and optional data from query parameters
|
|
21
|
+
const { template, data } = req.query
|
|
22
|
+
|
|
23
|
+
if (!template || typeof template !== "string") {
|
|
24
|
+
return res.status(400).json({ error: "Template name is required" })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Convert template name to PascalCase for component name
|
|
28
|
+
const componentName =
|
|
29
|
+
template
|
|
30
|
+
.split("-")
|
|
31
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
32
|
+
.join("") + "Template"
|
|
33
|
+
|
|
34
|
+
// Get the template component
|
|
35
|
+
const Template = templates[componentName as keyof typeof templates]
|
|
36
|
+
|
|
37
|
+
if (!Template) {
|
|
38
|
+
return res.status(404).json({ error: "Template not found" })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Parse the data if provided
|
|
42
|
+
let templateData = {}
|
|
43
|
+
if (data) {
|
|
44
|
+
try {
|
|
45
|
+
templateData = typeof data === "string" ? JSON.parse(data) : data
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return res.status(400).json({ error: "Invalid data format" })
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Create the PDF document
|
|
52
|
+
const MyDocument = createElement(Template, templateData);
|
|
53
|
+
|
|
54
|
+
// Set response headers for PDF
|
|
55
|
+
res.setHeader("Content-Type", "application/pdf")
|
|
56
|
+
res.setHeader("Content-Disposition", `attachment; filename="${template}.pdf"`)
|
|
57
|
+
|
|
58
|
+
// Create a readable stream from the PDF
|
|
59
|
+
const stream = await renderToStream(MyDocument)
|
|
60
|
+
|
|
61
|
+
// Pipe the stream to the response
|
|
62
|
+
stream.pipe(res)
|
|
63
|
+
|
|
64
|
+
// Handle stream errors
|
|
65
|
+
stream.on("error", (error) => {
|
|
66
|
+
console.error("Error streaming PDF:", error)
|
|
67
|
+
res.status(500).json({ error: "Error generating PDF" })
|
|
68
|
+
})
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error("Error generating PDF:", error)
|
|
71
|
+
res.status(500).json({ error: "Error generating PDF" })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
|
2
|
+
import type { NextApiRequest, NextApiResponse } from "next";
|
|
3
|
+
|
|
4
|
+
type Data = {
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default function handler(
|
|
9
|
+
req: NextApiRequest,
|
|
10
|
+
res: NextApiResponse<Data>,
|
|
11
|
+
) {
|
|
12
|
+
res.status(200).json({ name: "John Doe" });
|
|
13
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
6
|
+
if (req.method === 'GET') {
|
|
7
|
+
const filePath = path.join(process.cwd(), 'src', 'components', 'PDF', "components", 'DocumentoTemplate.tsx');
|
|
8
|
+
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
9
|
+
if (err) {
|
|
10
|
+
res.status(500).json({ error: 'Error al leer el archivo' });
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
res.status(200).json({ content: data });
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
res.status(405).json({ error: 'Método no permitido' });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { NextApiRequest, NextApiResponse } from "next"
|
|
2
|
+
import fs from "fs"
|
|
3
|
+
import path from "path"
|
|
4
|
+
|
|
5
|
+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
6
|
+
if (req.method === "GET") {
|
|
7
|
+
const { template } = req.query
|
|
8
|
+
|
|
9
|
+
if (!template || typeof template !== "string") {
|
|
10
|
+
return res.status(400).json({ error: "Nombre de plantilla no válido" })
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const filePath = path.join(process.cwd(), "src", "components", "PDF", "templates", `${template}.tsx`)
|
|
14
|
+
|
|
15
|
+
fs.readFile(filePath, "utf8", (err, data) => {
|
|
16
|
+
if (err) {
|
|
17
|
+
res.status(500).json({ error: `Error al leer el archivo: ${err.message}` })
|
|
18
|
+
return
|
|
19
|
+
}
|
|
20
|
+
res.status(200).json({ content: data })
|
|
21
|
+
})
|
|
22
|
+
} else {
|
|
23
|
+
res.status(405).json({ error: "Método no permitido" })
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
6
|
+
if (req.method === 'POST') {
|
|
7
|
+
const { filename, content } = req.body;
|
|
8
|
+
|
|
9
|
+
const filePath = path.join(process.cwd(), "src", 'pdf', filename);
|
|
10
|
+
|
|
11
|
+
fs.writeFile(filePath, content, (err) => {
|
|
12
|
+
if (err) {
|
|
13
|
+
console.error('Error al guardar el archivo:', err);
|
|
14
|
+
return res.status(500).json({ message: 'Error al guardar el archivo' });
|
|
15
|
+
}
|
|
16
|
+
res.status(200).json({ message: 'Archivo guardado exitosamente' });
|
|
17
|
+
});
|
|
18
|
+
} else {
|
|
19
|
+
res.setHeader('Allow', ['POST']);
|
|
20
|
+
res.status(405).end(`Método ${req.method} no permitido`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NextApiRequest, NextApiResponse } from 'next';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
6
|
+
if (req.method === 'POST') {
|
|
7
|
+
const { filename, content } = req.body;
|
|
8
|
+
const filePath = path.join(process.cwd(), 'src', 'pages', filename);
|
|
9
|
+
|
|
10
|
+
fs.writeFile(filePath, content, 'utf8', (err) => {
|
|
11
|
+
if (err) {
|
|
12
|
+
res.status(500).json({ error: 'Error al guardar el archivo' });
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
res.status(200).json({ message: 'Archivo guardado exitosamente' });
|
|
16
|
+
});
|
|
17
|
+
} else {
|
|
18
|
+
res.status(405).json({ error: 'Método no permitido' });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useRouter } from "next/router"
|
|
4
|
+
import dynamic from "next/dynamic"
|
|
5
|
+
import { useState, useEffect } from "react"
|
|
6
|
+
import { Editor } from "@monaco-editor/react"
|
|
7
|
+
import { Save } from "lucide-react"
|
|
8
|
+
import PDFContent from "../../components/PDF/components/PDFContent"
|
|
9
|
+
import Header from "../../components/PDF/view/Header"
|
|
10
|
+
import type { LayoutSettings } from "../../components/PDF/view/SettingsPanel"
|
|
11
|
+
|
|
12
|
+
const PDFViewer = dynamic(() => import("@react-pdf/renderer").then((mod) => mod.PDFViewer), { ssr: false })
|
|
13
|
+
|
|
14
|
+
const TemplatePage = () => {
|
|
15
|
+
const router = useRouter()
|
|
16
|
+
const { template } = router.query
|
|
17
|
+
const [code, setCode] = useState<string>("")
|
|
18
|
+
const [showModal, setShowModal] = useState<boolean>(false)
|
|
19
|
+
const [filename, setFilename] = useState<string>("")
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const fetchTemplateCode = async () => {
|
|
23
|
+
if (!template) return
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
let templatePath = ""
|
|
27
|
+
switch (template) {
|
|
28
|
+
case "allTemplate":
|
|
29
|
+
templatePath = "/api/readTemplateFile?template=AllTemplate"
|
|
30
|
+
setFilename("AllTemplate.tsx")
|
|
31
|
+
break
|
|
32
|
+
case "invoice":
|
|
33
|
+
templatePath = "/api/readTemplateFile?template=InvoiceTemplate"
|
|
34
|
+
setFilename("InvoiceTemplate.tsx")
|
|
35
|
+
break
|
|
36
|
+
case "report":
|
|
37
|
+
templatePath = "/api/readTemplateFile?template=ReportTemplate"
|
|
38
|
+
setFilename("ReportTemplate.tsx")
|
|
39
|
+
break
|
|
40
|
+
case "certificate":
|
|
41
|
+
templatePath = "/api/readTemplateFile?template=CertificateTemplate"
|
|
42
|
+
setFilename("CertificateTemplate.tsx")
|
|
43
|
+
break
|
|
44
|
+
default:
|
|
45
|
+
templatePath = "/api/readFile"
|
|
46
|
+
setFilename("DocumentoTemplate.tsx")
|
|
47
|
+
break
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const response = await fetch(templatePath)
|
|
51
|
+
const data = await response.json()
|
|
52
|
+
setCode(data.content)
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error("Error al leer el archivo:", error)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fetchTemplateCode()
|
|
59
|
+
}, [template])
|
|
60
|
+
|
|
61
|
+
const saveDocument = async () => {
|
|
62
|
+
try {
|
|
63
|
+
const response = await fetch("/api/saveFile", {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify({ filename, content: code }),
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
const result = await response.json()
|
|
70
|
+
console.log(result.message)
|
|
71
|
+
setShowModal(false)
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error("Error al guardar el archivo:", error)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const handleEditorChange = (value: string | undefined) => {
|
|
78
|
+
setCode(value || "")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const getTemplateTitle = () => {
|
|
82
|
+
switch (template) {
|
|
83
|
+
case "allTemplate":
|
|
84
|
+
return "All Template"
|
|
85
|
+
case "invoice":
|
|
86
|
+
return "Plantilla de Factura"
|
|
87
|
+
case "report":
|
|
88
|
+
return "Plantilla de Reporte"
|
|
89
|
+
case "certificate":
|
|
90
|
+
return "Plantilla de Certificado"
|
|
91
|
+
default:
|
|
92
|
+
return "Plantilla por Defecto"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const handleApplySettings = (settings: LayoutSettings) => {
|
|
97
|
+
// Generar el nuevo código con las configuraciones aplicadas
|
|
98
|
+
const updatedCode = generateUpdatedLayoutCode(code, settings)
|
|
99
|
+
setCode(updatedCode)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Función para generar el código actualizado con las nuevas configuraciones
|
|
103
|
+
const generateUpdatedLayoutCode = (originalCode: string, settings: LayoutSettings): string => {
|
|
104
|
+
// Buscar la sección de estilos
|
|
105
|
+
const styleStartIndex = originalCode.indexOf("const styles = StyleSheet.create({")
|
|
106
|
+
const styleEndIndex = originalCode.indexOf("})") + 2
|
|
107
|
+
|
|
108
|
+
if (styleStartIndex === -1 || styleEndIndex === -1) {
|
|
109
|
+
console.error("No se pudo encontrar la sección de estilos en el código")
|
|
110
|
+
return originalCode
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Generar nuevos estilos
|
|
114
|
+
let newStyles = `const styles = StyleSheet.create({\n page: {\n`
|
|
115
|
+
|
|
116
|
+
// Agregar propiedades de estilo
|
|
117
|
+
newStyles += ` backgroundColor: "${settings.backgroundColor}",\n`
|
|
118
|
+
|
|
119
|
+
// Agregar padding
|
|
120
|
+
if (settings.customPadding) {
|
|
121
|
+
newStyles += ` paddingTop: ${settings.paddingTop},\n`
|
|
122
|
+
newStyles += ` paddingRight: ${settings.paddingRight},\n`
|
|
123
|
+
newStyles += ` paddingBottom: ${settings.paddingBottom},\n`
|
|
124
|
+
newStyles += ` paddingLeft: ${settings.paddingLeft},\n`
|
|
125
|
+
} else {
|
|
126
|
+
newStyles += ` padding: ${settings.padding},\n`
|
|
127
|
+
if (settings.showPageNumbers) {
|
|
128
|
+
newStyles += ` paddingBottom: ${settings.padding + 14},\n`
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
newStyles += ` fontFamily: "${settings.fontFamily}",\n`
|
|
133
|
+
newStyles += ` fontSize: ${settings.fontSize},\n`
|
|
134
|
+
newStyles += ` lineHeight: ${settings.lineHeight},\n`
|
|
135
|
+
newStyles += ` position: "relative",\n`
|
|
136
|
+
newStyles += ` },\n\n`
|
|
137
|
+
|
|
138
|
+
// Agregar estilos para números de página si están habilitados
|
|
139
|
+
if (settings.showPageNumbers) {
|
|
140
|
+
newStyles += ` pageNumber: {\n`
|
|
141
|
+
newStyles += ` position: "absolute",\n`
|
|
142
|
+
newStyles += ` fontSize: 14,\n`
|
|
143
|
+
newStyles += ` top: 792 - 14,\n`
|
|
144
|
+
newStyles += ` left: 0,\n`
|
|
145
|
+
newStyles += ` right: 0,\n`
|
|
146
|
+
newStyles += ` textAlign: "center",\n`
|
|
147
|
+
newStyles += ` color: "grey",\n`
|
|
148
|
+
newStyles += ` },\n`
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
newStyles += `})`
|
|
152
|
+
|
|
153
|
+
// Reemplazar la sección de estilos en el código original
|
|
154
|
+
let updatedCode = originalCode.substring(0, styleStartIndex) + newStyles + originalCode.substring(styleEndIndex)
|
|
155
|
+
|
|
156
|
+
// Actualizar la etiqueta Page con el tamaño y orientación
|
|
157
|
+
const pageTagRegex = /<Page[^>]*>/
|
|
158
|
+
const pageTagMatch = updatedCode.match(pageTagRegex)
|
|
159
|
+
|
|
160
|
+
if (pageTagMatch) {
|
|
161
|
+
const originalPageTag = pageTagMatch[0]
|
|
162
|
+
const newPageTag = `<Page size="${settings.pageSize}" orientation="${settings.orientation}" style={styles.page}>`
|
|
163
|
+
updatedCode = updatedCode.replace(originalPageTag, newPageTag)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Manejar la numeración de páginas
|
|
167
|
+
const pageNumberRegex = /<Text\s+style={styles\.pageNumber}[^>]*>[\s\S]*?<\/Text>/
|
|
168
|
+
const pageNumberMatch = updatedCode.match(pageNumberRegex)
|
|
169
|
+
|
|
170
|
+
if (settings.showPageNumbers && !pageNumberMatch) {
|
|
171
|
+
// Agregar numeración de páginas si no existe
|
|
172
|
+
const closingPageTag = "</Page>"
|
|
173
|
+
const pageNumberText = `\n <Text
|
|
174
|
+
style={styles.pageNumber}
|
|
175
|
+
render={({ pageNumber, totalPages }) => \`\${pageNumber} / \${totalPages}\`}
|
|
176
|
+
fixed
|
|
177
|
+
/>`
|
|
178
|
+
|
|
179
|
+
updatedCode = updatedCode.replace(closingPageTag, `${pageNumberText}\n ${closingPageTag}`)
|
|
180
|
+
} else if (!settings.showPageNumbers && pageNumberMatch) {
|
|
181
|
+
// Eliminar numeración de páginas si existe pero no se desea
|
|
182
|
+
updatedCode = updatedCode.replace(pageNumberMatch[0], "")
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return updatedCode
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<>
|
|
190
|
+
<Header
|
|
191
|
+
title={getTemplateTitle()}
|
|
192
|
+
showSaveModal={() => setShowModal(true)}
|
|
193
|
+
isTemplatePage={true}
|
|
194
|
+
currentCode={code}
|
|
195
|
+
onApplySettings={handleApplySettings}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
<div className="container-playground">
|
|
199
|
+
<div className="container-editor fade-in">
|
|
200
|
+
<Editor
|
|
201
|
+
theme="vs-dark"
|
|
202
|
+
value={code}
|
|
203
|
+
defaultLanguage="javascript"
|
|
204
|
+
onChange={handleEditorChange}
|
|
205
|
+
options={{
|
|
206
|
+
minimap: { enabled: true },
|
|
207
|
+
fontSize: 14,
|
|
208
|
+
wordWrap: "on",
|
|
209
|
+
automaticLayout: true,
|
|
210
|
+
lineNumbers: "on",
|
|
211
|
+
scrollBeyondLastLine: false,
|
|
212
|
+
smoothScrolling: true,
|
|
213
|
+
}}
|
|
214
|
+
/>
|
|
215
|
+
</div>
|
|
216
|
+
<div className="container-render fade-in">
|
|
217
|
+
{typeof window !== "undefined" && (
|
|
218
|
+
<PDFViewer>
|
|
219
|
+
<PDFContent content={code} />
|
|
220
|
+
</PDFViewer>
|
|
221
|
+
)}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
|
|
225
|
+
<div className={`modal ${showModal ? "show" : ""}`}>
|
|
226
|
+
<div className="modal-content">
|
|
227
|
+
<h2>Guardar Documento</h2>
|
|
228
|
+
<input
|
|
229
|
+
type="text"
|
|
230
|
+
value={filename}
|
|
231
|
+
onChange={(e) => setFilename(e.target.value)}
|
|
232
|
+
placeholder="Nombre del archivo"
|
|
233
|
+
/>
|
|
234
|
+
<div>
|
|
235
|
+
<button className="btn btn-primary" onClick={saveDocument}>
|
|
236
|
+
<Save size={20} />
|
|
237
|
+
Guardar
|
|
238
|
+
</button>
|
|
239
|
+
<button className="btn btn-outline" onClick={() => setShowModal(false)}>
|
|
240
|
+
Cancelar
|
|
241
|
+
</button>
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
</>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export default TemplatePage
|
|
250
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"lib": [
|
|
4
|
+
"dom",
|
|
5
|
+
"dom.iterable",
|
|
6
|
+
"esnext"
|
|
7
|
+
],
|
|
8
|
+
"allowJs": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noEmit": false,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"module": "esnext",
|
|
14
|
+
"moduleResolution": "node",
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"isolatedModules": true,
|
|
17
|
+
"jsx": "react",
|
|
18
|
+
"incremental": true,
|
|
19
|
+
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo",
|
|
20
|
+
"paths": {
|
|
21
|
+
"@/*": [
|
|
22
|
+
"./src/*"
|
|
23
|
+
],
|
|
24
|
+
"@components/*": [
|
|
25
|
+
"./src/components/*"
|
|
26
|
+
],
|
|
27
|
+
"@fn/*": [
|
|
28
|
+
"./src/functions/*"
|
|
29
|
+
],
|
|
30
|
+
"@env": [
|
|
31
|
+
"./env.ts"
|
|
32
|
+
],
|
|
33
|
+
"@public/*": [
|
|
34
|
+
"./public/*"
|
|
35
|
+
],
|
|
36
|
+
"@nano": [
|
|
37
|
+
"./src/components/nano/index.tsx"
|
|
38
|
+
],
|
|
39
|
+
"@hook/*": [
|
|
40
|
+
"./src/hook/*"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"outDir": "./dist",
|
|
44
|
+
"declaration": true,
|
|
45
|
+
"declarationDir": "./dist/types",
|
|
46
|
+
"target": "ES2017",
|
|
47
|
+
"plugins": [
|
|
48
|
+
{
|
|
49
|
+
"name": "next"
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"include": [
|
|
54
|
+
"**/**/*.ts",
|
|
55
|
+
"**/*.ts",
|
|
56
|
+
"**/*.tsx",
|
|
57
|
+
".next/types/**/*.ts",
|
|
58
|
+
"src/components/swiper/estructura/lib/swiper-gl.min.js"
|
|
59
|
+
],
|
|
60
|
+
"exclude": [
|
|
61
|
+
"node_modules"
|
|
62
|
+
]
|
|
63
|
+
}
|