nexabase-report 0.3.3 → 0.4.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.
@@ -0,0 +1,199 @@
1
+ # Viewer
2
+
3
+ `<nexa-viewer>` is a custom element (Web Component) that renders NexaReport definitions. It works in any framework (Vue, React, Angular, Svelte, Blazor, plain HTML) and requires no Vue dependency in the consumer application.
4
+
5
+ ## Usage
6
+
7
+ ### HTML / Vanilla JS
8
+
9
+ ```html
10
+ <script src="https://cdn.jsdelivr.net/npm/nexabase-report/dist/nexabase-report.umd.js"></script>
11
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nexabase-report/dist/style.css">
12
+
13
+ <nexa-viewer id="viewer" minimal></nexa-viewer>
14
+
15
+ <script>
16
+ NexaReport.registerNexaReport();
17
+
18
+ const viewer = document.getElementById('viewer');
19
+ viewer.definition = { /* report JSON */ };
20
+ viewer.data = [ /* data array */ ];
21
+ </script>
22
+ ```
23
+
24
+ ### Vue 3
25
+
26
+ ```vue
27
+ <script setup>
28
+ import { registerNexaReport } from 'nexabase-report';
29
+
30
+ registerNexaReport();
31
+ </script>
32
+
33
+ <template>
34
+ <nexa-viewer
35
+ :definition="reportDef"
36
+ :data="reportData"
37
+ :parameters="{ year: 2024 }"
38
+ skip-params-dialog
39
+ show-toolbar
40
+ />
41
+ </template>
42
+ ```
43
+
44
+ ### React
45
+
46
+ ```tsx
47
+ import { useEffect, useRef } from 'react';
48
+
49
+ export function ReportViewer({ definition, data }) {
50
+ const viewerRef = useRef(null);
51
+
52
+ useEffect(() => {
53
+ window.NexaReport?.registerNexaReport();
54
+ }, []);
55
+
56
+ useEffect(() => {
57
+ if (viewerRef.current) {
58
+ viewerRef.current.definition = definition;
59
+ viewerRef.current.data = data;
60
+ }
61
+ }, [definition, data]);
62
+
63
+ return <nexa-viewer ref={viewerRef} />;
64
+ }
65
+ ```
66
+
67
+ ### Blazor
68
+
69
+ ```razor
70
+ @page "/report/{ReportId}"
71
+
72
+ <div class="viewer-container">
73
+ <nexa-viewer id="reportViewer" style="width:100%; height:1200px;"></nexa-viewer>
74
+ </div>
75
+
76
+ <script src="https://cdn.jsdelivr.net/npm/nexabase-report/dist/nexabase-report.umd.js"></script>
77
+ <script>
78
+ window.loadReport = async function(reportJson, data) {
79
+ if (!window._nexaReg) {
80
+ NexaReport.registerNexaReport();
81
+ window._nexaReg = true;
82
+ }
83
+ const viewer = document.getElementById('reportViewer');
84
+ viewer.definition = reportJson;
85
+ viewer.data = data;
86
+ };
87
+ </script>
88
+
89
+ @code {
90
+ [Parameter] public string ReportId { get; set; }
91
+
92
+ protected override async Task OnInitializedAsync() {
93
+ await JSRuntime.InvokeVoidAsync("loadReport", reportDef, reportData);
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## Viewer Props
99
+
100
+ | Prop | Type | Default | Description |
101
+ |------|------|---------|-------------|
102
+ | `definition` | `NexaReportDefinition \| string` | — | Report definition object or JSON string. |
103
+ | `data` | `any[] \| Record<string, any[]> \| string` | — | Data for the report. Array (single source) or object keyed by datasource alias. |
104
+ | `parameters` | `Record<string, any>` | `{}` | Initial values for report parameters. |
105
+ | `minimal` | `boolean \| string` | `false` | Compact mode: hides toolbar and sidebar. |
106
+ | `showToolbar` | `boolean \| string` | `true` | Show/hide the export toolbar. |
107
+ | `showThumbs` | `boolean \| string` | `true` | Show/hide the thumbnail sidebar. |
108
+ | `skipParamsDialog` | `boolean` | `false` | Skip the parameter input dialog at load time. |
109
+ | `currentPage` | `number` | `1` | Initial page number to display. |
110
+ | `apiBaseUrl` | `string` | — | NexaBase API URL for dynamic data loading. |
111
+ | `apiKey` | `string` | — | NexaBase API key for authenticated data. |
112
+ | `locale` | `string` | `'es'` | UI language: `'es'`, `'en'`, or `'pt'`. |
113
+ | `licenseKey` | `string` | — | Commercial license key. Without a valid key, an "Unlicensed" watermark appears at the bottom. |
114
+
115
+ ## Viewer Methods
116
+
117
+ Access via `document.querySelector('nexa-viewer')` or a template ref:
118
+
119
+ ```javascript
120
+ const viewer = document.querySelector('nexa-viewer');
121
+
122
+ // Navigation
123
+ viewer.goToPage(3); // Jump to page 3
124
+ viewer.nextPage(); // Go to next page
125
+ viewer.previousPage(); // Go to previous page
126
+
127
+ // Export
128
+ await viewer.exportPdf(); // Standard PDF
129
+ await viewer.exportPdfWithBookmarks(); // PDF with bookmarks/TOC
130
+ await viewer.exportExcel(); // Excel .xlsx
131
+ await viewer.exportWord(); // Word .docx
132
+ await viewer.exportCsv(); // CSV with UTF-8 BOM
133
+
134
+ // State
135
+ console.log(viewer.pageNumber); // Current page (get/set)
136
+ console.log(viewer.totalPages); // Total pages (read-only)
137
+ ```
138
+
139
+ ## Events
140
+
141
+ ```javascript
142
+ const viewer = document.querySelector('nexa-viewer');
143
+
144
+ viewer.addEventListener('data-request', (e) => {
145
+ console.log('Data requested for:', e.detail.alias);
146
+ // Fetch data and set: viewer.data = { [e.detail.alias]: [...] }
147
+ });
148
+
149
+ viewer.addEventListener('page-change', (e) => {
150
+ console.log('Page changed to:', e.detail);
151
+ });
152
+
153
+ viewer.addEventListener('drill-click', (e) => {
154
+ console.log('Drill-down clicked:', e.detail);
155
+ // e.detail = { element, sourceData, targetReportId, parameters, config }
156
+ });
157
+ ```
158
+
159
+ ## Renderers
160
+
161
+ The viewer includes specialized renderers for each element type:
162
+
163
+ | Renderer | Description |
164
+ |----------|-------------|
165
+ | `TextRenderer` | Text, expressions, bindings with highlight search |
166
+ | `ImageRenderer` | Image from URL or data field, with `object-fit` support (contain/cover/fill) |
167
+ | `TableRenderer` | Tabular data with headers, alternating row colors, conditional styling |
168
+ | `ChartRenderer` | ECharts (bar, line, pie, area, scatter, radar, etc.) |
169
+ | `CrosstabRenderer` | Pivot table with row/column grouping and aggregations |
170
+ | `BarcodeRenderer` | CODE128, EAN13, CODE39, etc. via jsbarcode |
171
+ | `QRCodeRenderer` | QR codes via qrcode library |
172
+ | `ShapeRenderer` | Rectangle, Ellipse, Line, Arrow rendered as SVG/canvas |
173
+ | `DashboardWidgetRenderer` | Dashboard widgets (Indicator, Chart, Gauge, Table) |
174
+
175
+ ## Pagination
176
+
177
+ NexaReport uses a two-phase pagination engine:
178
+
179
+ 1. **Streaming Phase** (`generateStream`): Processes all bands and data rows, computing page breaks based on element heights, table row heights, and watermark space.
180
+
181
+ 2. **Page Generation Phase** (`generatePages`): Splits the stream into individual pages, handling table row splitting across page boundaries and accounting for `PageHeader`, `PageFooter`, and `ReportFooter` space.
182
+
183
+ The `currentPage` prop allows programmatically navigating to any page. The thumbnail sidebar shows all pages and lets users click to navigate.
184
+
185
+ ## Watermark
186
+
187
+ Without a valid `licenseKey`, the viewer displays an "Unlicensed · Trial version" banner at the bottom. This does not block functionality but serves as a reminder to activate a commercial license.
188
+
189
+ ## Styling
190
+
191
+ The viewer uses scoped styles. Global overrides can be applied via CSS custom properties on the host element:
192
+
193
+ ```css
194
+ nexa-viewer {
195
+ --viewer-bg: #f8fafc;
196
+ --viewer-toolbar-bg: #ffffff;
197
+ --viewer-border: #e2e8f0;
198
+ }
199
+ ```
package/docs/index.md ADDED
@@ -0,0 +1,65 @@
1
+ ---
2
+ layout: home
3
+
4
+ hero:
5
+ name: "NexaReport"
6
+ text: "Professional Report Designer & Viewer"
7
+ tagline: "Vue 3 · TypeScript · WYSIWYG · Export to PDF/Excel/Word · 100% Client-Side"
8
+ image:
9
+ src: /logo.svg
10
+ alt: NexaReport
11
+ actions:
12
+ - theme: brand
13
+ text: Get Started
14
+ link: /guide/getting-started
15
+ - theme: alt
16
+ text: View on GitHub
17
+ link: https://github.com/nexabase/nexabase-report
18
+
19
+ features:
20
+ - icon: 🎨
21
+ title: WYSIWYG Designer
22
+ details: Drag & drop report designer with ribbon, sidebar, snap-to-grid, i18n support (ES/EN/PT) and real-time preview.
23
+
24
+ - icon: 📦
25
+ title: Custom Element Viewer
26
+ details: "<nexa-viewer> works in Vue, React, Angular, Svelte, Blazor, or plain HTML — no Vue dependency in the consumer."
27
+
28
+ - icon: 📊
29
+ title: Charts, Crosstabs, Tables
30
+ details: ECharts integration (bar, line, pie, area, scatter), crosstab pivot tables, banded report model with data bands.
31
+
32
+ - icon: 📄
33
+ title: PDF, Excel, Word, CSV
34
+ details: 100% client-side export. Native vector PDF, SheetJS Excel, docx Word, and UTF-8 BOM CSV — no server required.
35
+
36
+ - icon: 🔑
37
+ title: Commercial Licensing
38
+ details: Designer supports license key activation (personal, business, enterprise). Watermark-free with valid license.
39
+
40
+ - icon: 🌐
41
+ title: CDN Ready
42
+ details: One script tag to include in any project. No build step required for HTML demos or quick integrations.
43
+ ---
44
+
45
+ <div class="vp-doc flex flex-col items-center justify-center min-h-[30vh] text-center px-6">
46
+ <h2 class="mb-4 text-2xl font-bold text-[var(--vp-c-brand-1)]">Try it now — no install needed</h2>
47
+ <div class="code-block w-full max-w-2xl rounded-lg overflow-hidden text-left">
48
+
49
+ ```html
50
+ <script src="https://cdn.jsdelivr.net/npm/nexabase-report/dist/nexabase-report.umd.js"></script>
51
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nexabase-report/dist/style.css">
52
+
53
+ <nexa-viewer id="viewer" minimal></nexa-viewer>
54
+
55
+ <script>
56
+ NexaReport.registerNexaReport();
57
+
58
+ const viewer = document.getElementById('viewer');
59
+ viewer.definition = { /* your report JSON */ };
60
+ viewer.data = [ /* your data array */ ];
61
+ </script>
62
+ ```
63
+
64
+ </div>
65
+ </div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexabase-report",
3
- "version": "0.3.3",
3
+ "version": "0.4.1",
4
4
  "description": "Professional report designer and viewer for NexaBase — drag & drop designer, PDF/Excel export, charts, crosstabs, subreports.",
5
5
  "license": "MIT",
6
6
  "author": "NexaBase Team",
@@ -54,20 +54,6 @@
54
54
  "custom-element",
55
55
  "web-component"
56
56
  ],
57
- "scripts": {
58
- "dev": "vite",
59
- "build": "vue-tsc -b && vite build",
60
- "preview": "vite preview",
61
- "test": "vitest run",
62
- "test:watch": "vitest",
63
- "test:coverage": "vitest run --coverage",
64
- "release:patch": "npm test && npm run build && npm version patch",
65
- "release:minor": "npm test && npm run build && npm version minor",
66
- "release:major": "npm test && npm run build && npm version major",
67
- "prepack": "npm run build",
68
- "lint": "eslint src/lib/",
69
- "lint:fix": "eslint src/lib/ --fix"
70
- },
71
57
  "dependencies": {
72
58
  "@nexabase/sdk": "^2.17.6",
73
59
  "@types/jsbarcode": "^3.11.4",
@@ -98,7 +84,25 @@
98
84
  "typescript-eslint": "^8.31.1",
99
85
  "vite": "^5.4.14",
100
86
  "vite-plugin-dts": "^4.5.4",
87
+ "vitepress": "^1.6.4",
101
88
  "vitest": "^4.1.5",
102
89
  "vue-tsc": "^3.2.6"
90
+ },
91
+ "scripts": {
92
+ "dev": "vite",
93
+ "build": "vue-tsc -b && vite build",
94
+ "preview": "vite preview",
95
+ "test": "vitest run",
96
+ "test:watch": "vitest",
97
+ "test:coverage": "vitest run --coverage",
98
+ "release:patch": "pnpm test && pnpm build && pnpm version patch",
99
+ "release:minor": "pnpm test && pnpm build && pnpm version minor",
100
+ "release:major": "pnpm test && pnpm build && pnpm version major",
101
+ "lint": "eslint src/lib/",
102
+ "lint:fix": "eslint src/lib/ --fix",
103
+ "license:gen": "node scripts/gen-license.mjs",
104
+ "docs:dev": "vitepress dev docs-site",
105
+ "docs:build": "vitepress build docs-site",
106
+ "docs:preview": "vitepress preview docs-site"
103
107
  }
104
- }
108
+ }
@@ -1,26 +0,0 @@
1
- import { a as c } from "./index-DGMS37uu.js";
2
- import { r as f } from "./html2canvas-PXHaohUp.js";
3
- function l(r, n) {
4
- for (var o = 0; o < n.length; o++) {
5
- const e = n[o];
6
- if (typeof e != "string" && !Array.isArray(e)) {
7
- for (const t in e)
8
- if (t !== "default" && !(t in r)) {
9
- const a = Object.getOwnPropertyDescriptor(e, t);
10
- a && Object.defineProperty(r, t, a.get ? a : {
11
- enumerable: !0,
12
- get: () => e[t]
13
- });
14
- }
15
- }
16
- }
17
- return Object.freeze(Object.defineProperty(r, Symbol.toStringTag, { value: "Module" }));
18
- }
19
- var s = f();
20
- const i = /* @__PURE__ */ c(s), u = /* @__PURE__ */ l({
21
- __proto__: null,
22
- default: i
23
- }, [s]);
24
- export {
25
- u as h
26
- };