nexabase-report 0.28.0 → 0.28.1
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/NEXAREPORT.md +291 -0
- package/dist/{html2pdf-C6SN8ITW.js → html2pdf-B3mAxkNT.js} +2 -2
- package/dist/{index-Cn1BXocE.js → index-n-ggfS1p.js} +22089 -22193
- package/dist/{index.es-BQk_vh5w.js → index.es-5IFpweNE.js} +2 -2
- package/dist/{jspdf.es.min-CQvy1ivX.js → jspdf.es.min-C6M8fb8R.js} +1 -1
- package/dist/nexabase-report.es.js +1 -1
- package/dist/nexabase-report.umd.js +250 -266
- package/dist/{pptxgen.es-BYDany-_.js → pptxgen.es-KpBnHDuC.js} +1 -1
- package/package.json +10 -4
- package/schema/nexareport.schema.json +1920 -0
package/NEXAREPORT.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
<!-- nexabase-report@0.28.1 — generado por scripts/gen-ai-context.mjs, no editar a mano -->
|
|
2
|
+
# NexaReport — referencia para agentes de IA
|
|
3
|
+
|
|
4
|
+
> Este archivo se genera desde los tipos TypeScript reales del paquete (`src/lib/types/report.ts`
|
|
5
|
+
> vía `schema/nexareport.schema.json`), no a mano — así nunca queda desactualizado respecto al
|
|
6
|
+
> código. Si este archivo dice una versión de `nexabase-report` distinta a la que tienes
|
|
7
|
+
> instalada en `package.json`, hay una más reciente en
|
|
8
|
+
> `https://unpkg.com/nexabase-report@latest/NEXAREPORT.md` — tráela de ahí antes de confiar
|
|
9
|
+
> en este archivo (o corre `npm run build` en el repo de nexabase-report para regenerarla).
|
|
10
|
+
|
|
11
|
+
## Qué es
|
|
12
|
+
|
|
13
|
+
NexaReport es un motor de reportes (diseñador + visor + exportación PDF/Excel/Word) basado en
|
|
14
|
+
**bandas** apiladas verticalmente, al estilo Stimulsoft/FastReport. Un reporte es un único objeto
|
|
15
|
+
JSON: `NexaReportDefinition`.
|
|
16
|
+
|
|
17
|
+
## Estructura mínima de un reporte
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"metadata": { "version": "1.0", "name": "Nombre del reporte", "createdAt": "2026-01-01" },
|
|
22
|
+
"layout": {
|
|
23
|
+
"page": { "format": "A4", "orientation": "portrait", "margins": { "top": 60, "right": 60, "bottom": 60, "left": 60 } },
|
|
24
|
+
"bands": [ /* ver "Tipos de banda" abajo */ ]
|
|
25
|
+
},
|
|
26
|
+
"dataSources": [ { "id": "ds1", "alias": "items", "collection": "items", "enabled": true } ]
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`layout.page.format` es `"A4" | "Letter" | "Ticket" | "Dashboard"`. `orientation` es
|
|
31
|
+
`"portrait" | "landscape"`.
|
|
32
|
+
|
|
33
|
+
## Tipos de banda (`NexaReportBand.type`)
|
|
34
|
+
|
|
35
|
+
- **ReportHeader** — Se imprime una sola vez, al inicio (o en cada página si repeatOnEveryPage: true). El título/membrete del reporte.
|
|
36
|
+
- **PageHeader** — Se repite en la parte superior de CADA página.
|
|
37
|
+
- **DataBand** — La banda de datos principal — una instancia por fila (o una sola con una Table que lista todas las filas). Requiere dataSource.
|
|
38
|
+
- **GroupHeader** — Se imprime al iniciar un grupo (requiere masterField). Va antes de las filas de ese grupo.
|
|
39
|
+
- **GroupFooter** — Se imprime al cerrar un grupo (requiere masterField). Ideal para subtotales.
|
|
40
|
+
- **PageFooter** — Se repite en la parte inferior de CADA página.
|
|
41
|
+
- **ReportFooter** — Se imprime una sola vez, al final de todo el reporte (totales generales, firma).
|
|
42
|
+
- **DetailBand** — Sub-banda para master-detail: una fila hija por cada fila del DataBand padre (parentDataSource + masterField + childField).
|
|
43
|
+
- **StaticPage** — Contenido FIJO de una página completa, independiente de los datos. Repetible: una StaticPage por cada página fija que necesites (ej. una carta de 2 hojas). Puede tener dataSource igual que cualquier otra banda (ej. para el nombre del destinatario). Nace con pageBreakBefore: true.
|
|
44
|
+
|
|
45
|
+
Toda banda puede tener: `pageBreakBefore` / `pageBreakAfter` (forzar salto de página),
|
|
46
|
+
`backgroundColor`, `dataSource` (alias de `dataSources` a usar). Las coordenadas de los
|
|
47
|
+
elementos dentro de una banda (`x`, `y`) son relativas a la banda, en píxeles.
|
|
48
|
+
|
|
49
|
+
## Tipos de elemento (`NexaReportElement.type`)
|
|
50
|
+
|
|
51
|
+
- **Text** — Texto simple. `binding` para un campo ({{campo}} implícito) o `content` con placeholders {{campo}} / expresiones {[expr]}.
|
|
52
|
+
- **Image** — `options.imageSource`: "url" (URL fija en options.imageUrl) o "binding" (campo de datos con la URL/base64).
|
|
53
|
+
- **Barcode** — Código de barras. `binding` o `content` con el valor; `options.barcodeFormat` (ej. "CODE128").
|
|
54
|
+
- **Table** — Tabla tabular — usar dentro de un DataBand. `tableColumns` (id/title/binding/width/format), tableShowHeader/Footer/GroupHeader/Footer, tableGroupBy.
|
|
55
|
+
- **Chart** — `chartConfig` (tipo, series, ejes).
|
|
56
|
+
- **Crosstab** — Tabla dinámica. `crosstabConfig`.
|
|
57
|
+
- **SubReport** — Reporte embebido. `subReportDefinition` (definición completa inline) + `subReportDataSource` (alias en el dataMap del padre) + `subReportBindings` ([{masterField, childField}]) para filtrar por la fila actual del padre.
|
|
58
|
+
- **Line** — Forma. `shapeType` implícito ("Line").
|
|
59
|
+
- **Rectangle** — Forma. `options.fillColor`, `options.cornerRadius`.
|
|
60
|
+
- **Ellipse** — Forma.
|
|
61
|
+
- **Arrow** — Forma.
|
|
62
|
+
- **QRCode** — Código QR. Igual que Barcode pero sin formato.
|
|
63
|
+
- **DrillDown** — Navega a otro reporte al hacer clic. `drillDownConfig`.
|
|
64
|
+
- **Gauge** — `gaugeConfig` (valueField, min, max, ranges).
|
|
65
|
+
- **Indicator** — KPI simple. `indicatorConfig` (binding, aggregation, label).
|
|
66
|
+
- **RichText** — Texto con formato (negrita, listas, etc.). El HTML autorizado va en `richText` (NO en `content`).
|
|
67
|
+
|
|
68
|
+
Todo elemento tiene `id`, `type`, `x`, `y`, `width`, `height`, `style` (obligatorios).
|
|
69
|
+
|
|
70
|
+
## Binding de datos y expresiones
|
|
71
|
+
|
|
72
|
+
- `{{campo}}` dentro de `content` — inserta el valor de ese campo de la fila actual.
|
|
73
|
+
- `{[expresión]}` — evalúa una expresión, incluye funciones de agregación: `sum(campo)`,
|
|
74
|
+
`count(campo)`, `avg(campo)`, `min(campo)`, `max(campo)`, `first(campo)`, `last(campo)`.
|
|
75
|
+
- Variables de sistema: `{{Page}}`, `{{TotalPages}}`, `{{Today}}`, `{{Now}}`, `{{RowNumber}}`,
|
|
76
|
+
`{{TotalRows}}`, `{{ReportName}}`, y más — ver `docs/VIEWER_API.md` para la lista completa.
|
|
77
|
+
- Un elemento con `binding` (en vez de `content`) lee ese campo directamente — usado para
|
|
78
|
+
Barcode/QRCode/Image; para Text es más común usar `content` con `{{...}}`.
|
|
79
|
+
|
|
80
|
+
## Ejemplo 1 — Carta fija de 2 páginas (StaticPage)
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"metadata": {
|
|
85
|
+
"version": "1.0",
|
|
86
|
+
"name": "Carta",
|
|
87
|
+
"createdAt": "2026-01-01"
|
|
88
|
+
},
|
|
89
|
+
"layout": {
|
|
90
|
+
"page": {
|
|
91
|
+
"format": "A4",
|
|
92
|
+
"orientation": "portrait",
|
|
93
|
+
"margins": {
|
|
94
|
+
"top": 60,
|
|
95
|
+
"right": 60,
|
|
96
|
+
"bottom": 60,
|
|
97
|
+
"left": 60
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"bands": [
|
|
101
|
+
{
|
|
102
|
+
"id": "pagina1",
|
|
103
|
+
"type": "StaticPage",
|
|
104
|
+
"height": 900,
|
|
105
|
+
"dataSource": "destinatario",
|
|
106
|
+
"elements": [
|
|
107
|
+
{
|
|
108
|
+
"id": "saludo",
|
|
109
|
+
"type": "Text",
|
|
110
|
+
"x": 0,
|
|
111
|
+
"y": 0,
|
|
112
|
+
"width": 500,
|
|
113
|
+
"height": 30,
|
|
114
|
+
"style": {
|
|
115
|
+
"fontSize": "14px"
|
|
116
|
+
},
|
|
117
|
+
"binding": "nombre",
|
|
118
|
+
"content": "Estimado {{nombre}}:"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "cuerpo",
|
|
122
|
+
"type": "Text",
|
|
123
|
+
"x": 0,
|
|
124
|
+
"y": 40,
|
|
125
|
+
"width": 500,
|
|
126
|
+
"height": 400,
|
|
127
|
+
"style": {
|
|
128
|
+
"fontSize": "12px"
|
|
129
|
+
},
|
|
130
|
+
"content": "Cuerpo de la carta..."
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "pagina2",
|
|
136
|
+
"type": "StaticPage",
|
|
137
|
+
"height": 900,
|
|
138
|
+
"pageBreakBefore": true,
|
|
139
|
+
"elements": [
|
|
140
|
+
{
|
|
141
|
+
"id": "firma",
|
|
142
|
+
"type": "Text",
|
|
143
|
+
"x": 0,
|
|
144
|
+
"y": 700,
|
|
145
|
+
"width": 300,
|
|
146
|
+
"height": 30,
|
|
147
|
+
"style": {
|
|
148
|
+
"fontSize": "12px"
|
|
149
|
+
},
|
|
150
|
+
"content": "Atentamente,\nEl equipo"
|
|
151
|
+
}
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
"dataSources": [
|
|
157
|
+
{
|
|
158
|
+
"id": "ds1",
|
|
159
|
+
"alias": "destinatario",
|
|
160
|
+
"collection": "destinatario",
|
|
161
|
+
"enabled": true
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Ejemplo 2 — Factura con tabla y totales
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"metadata": {
|
|
172
|
+
"version": "1.0",
|
|
173
|
+
"name": "Factura",
|
|
174
|
+
"createdAt": "2026-01-01"
|
|
175
|
+
},
|
|
176
|
+
"layout": {
|
|
177
|
+
"page": {
|
|
178
|
+
"format": "A4",
|
|
179
|
+
"orientation": "portrait"
|
|
180
|
+
},
|
|
181
|
+
"bands": [
|
|
182
|
+
{
|
|
183
|
+
"id": "rh",
|
|
184
|
+
"type": "ReportHeader",
|
|
185
|
+
"height": 80,
|
|
186
|
+
"elements": [
|
|
187
|
+
{
|
|
188
|
+
"id": "titulo",
|
|
189
|
+
"type": "Text",
|
|
190
|
+
"x": 0,
|
|
191
|
+
"y": 0,
|
|
192
|
+
"width": 300,
|
|
193
|
+
"height": 30,
|
|
194
|
+
"style": {
|
|
195
|
+
"fontSize": "20px",
|
|
196
|
+
"fontWeight": "bold"
|
|
197
|
+
},
|
|
198
|
+
"content": "Factura {{numero}}"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"id": "db",
|
|
204
|
+
"type": "DataBand",
|
|
205
|
+
"height": 200,
|
|
206
|
+
"dataSource": "items",
|
|
207
|
+
"elements": [
|
|
208
|
+
{
|
|
209
|
+
"id": "tabla",
|
|
210
|
+
"type": "Table",
|
|
211
|
+
"x": 0,
|
|
212
|
+
"y": 0,
|
|
213
|
+
"width": 500,
|
|
214
|
+
"height": 150,
|
|
215
|
+
"style": {},
|
|
216
|
+
"tableShowFooter": true,
|
|
217
|
+
"tableColumns": [
|
|
218
|
+
{
|
|
219
|
+
"id": "c1",
|
|
220
|
+
"title": "Producto",
|
|
221
|
+
"binding": "nombre",
|
|
222
|
+
"width": 250
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"id": "c2",
|
|
226
|
+
"title": "Cantidad",
|
|
227
|
+
"binding": "cantidad",
|
|
228
|
+
"width": 100,
|
|
229
|
+
"alignment": "right"
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
"id": "c3",
|
|
233
|
+
"title": "Subtotal",
|
|
234
|
+
"binding": "subtotal",
|
|
235
|
+
"width": 150,
|
|
236
|
+
"alignment": "right",
|
|
237
|
+
"format": "$#,##0.00",
|
|
238
|
+
"footerText": "Total: {[sum(subtotal)]}"
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "pf",
|
|
246
|
+
"type": "PageFooter",
|
|
247
|
+
"height": 30,
|
|
248
|
+
"elements": [
|
|
249
|
+
{
|
|
250
|
+
"id": "pag",
|
|
251
|
+
"type": "Text",
|
|
252
|
+
"x": 400,
|
|
253
|
+
"y": 0,
|
|
254
|
+
"width": 100,
|
|
255
|
+
"height": 20,
|
|
256
|
+
"style": {
|
|
257
|
+
"fontSize": "9px",
|
|
258
|
+
"textAlign": "right"
|
|
259
|
+
},
|
|
260
|
+
"content": "Página {{Page}} de {{TotalPages}}"
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
},
|
|
266
|
+
"dataSources": [
|
|
267
|
+
{
|
|
268
|
+
"id": "ds1",
|
|
269
|
+
"alias": "items",
|
|
270
|
+
"collection": "items",
|
|
271
|
+
"enabled": true
|
|
272
|
+
}
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Validación
|
|
278
|
+
|
|
279
|
+
El schema formal completo (todas las interfaces, no solo bandas/elementos) está en
|
|
280
|
+
`schema/nexareport.schema.json` dentro del paquete — también publicado como export
|
|
281
|
+
`nexabase-report/schema`, así que es accesible sin instalar nada vía:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
https://unpkg.com/nexabase-report@0.28.1/schema/nexareport.schema.json
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
(cambia `@0.28.1` por `@latest` para la versión más reciente). Valida el JSON generado
|
|
288
|
+
contra ese schema antes de darlo por bueno — evita que un campo inventado llegue al usuario.
|
|
289
|
+
|
|
290
|
+
Más ejemplos reales (subreportes, crosstab, master-detail, códigos de barras) en `examples/*.json`
|
|
291
|
+
dentro del paquete publicado.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { g as Nl, c as ut, d as Vl } from "./index-
|
|
2
|
-
import { j as Xl } from "./jspdf.es.min-
|
|
1
|
+
import { g as Nl, c as ut, d as Vl } from "./index-n-ggfS1p.js";
|
|
2
|
+
import { j as Xl } from "./jspdf.es.min-C6M8fb8R.js";
|
|
3
3
|
function Jl(Pe, br) {
|
|
4
4
|
for (var fe = 0; fe < br.length; fe++) {
|
|
5
5
|
const HA = br[fe];
|