@reportwright/viewer 0.12.1 → 0.13.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/CHANGELOG.md +93 -0
- package/README.md +18 -1
- package/THIRD-PARTY-NOTICES.md +52 -0
- package/dist/{chunk-DXHLIJEY.js → chunk-47ZAKRVN.js} +6 -6
- package/dist/{chunk-NR2G4TMG.js → chunk-B5ZCT3UK.js} +47 -26
- package/dist/chunk-B5ZCT3UK.js.map +6 -0
- package/dist/chunk-BR5K6SBL.js +324 -0
- package/dist/chunk-BR5K6SBL.js.map +6 -0
- package/dist/chunk-CCH7CFU5.js +5026 -0
- package/dist/chunk-CCH7CFU5.js.map +6 -0
- package/dist/{peer/chunk-BQFI3DHK.js → chunk-ES2LYZ6S.js} +292 -25
- package/dist/chunk-ES2LYZ6S.js.map +6 -0
- package/dist/{chunk-S2IUUI6N.js → chunk-GOCWG6FG.js} +67 -49
- package/dist/chunk-GOCWG6FG.js.map +6 -0
- package/dist/{chunk-3D2KFKG2.js → chunk-GRYITZPG.js} +11 -9
- package/dist/chunk-GRYITZPG.js.map +6 -0
- package/dist/{chunk-2BPBQMH2.js → chunk-H422SRD3.js} +8 -8
- package/dist/chunk-JD6EJ3LI.js +18 -0
- package/dist/{chunk-Z7MKH66Z.js → chunk-MS2LQC2O.js} +236 -12
- package/dist/chunk-MS2LQC2O.js.map +6 -0
- package/dist/{chunk-Q6MMPKQA.js → chunk-PF4RFKX2.js} +13 -12
- package/dist/chunk-PF4RFKX2.js.map +6 -0
- package/dist/{chunk-PGP3QA6L.js → chunk-PKXTMC4J.js} +1351 -75
- package/dist/chunk-PKXTMC4J.js.map +6 -0
- package/dist/{chunk-M6AYND5G.js → chunk-U2ZY2NPQ.js} +16 -7
- package/dist/chunk-U2ZY2NPQ.js.map +6 -0
- package/dist/{chunk-DPVJEFKP.js → chunk-WOBRKNIA.js} +13 -13
- package/dist/{chunk-DPVJEFKP.js.map → chunk-WOBRKNIA.js.map} +1 -1
- package/dist/chunk-XXTAPZO4.js +34 -0
- package/dist/{chunk-VNOWPSE6.js → chunk-ZGRJJ6OW.js} +1226 -887
- package/dist/chunk-ZGRJJ6OW.js.map +6 -0
- package/dist/designer.d.ts +11 -3
- package/dist/designer.js +598 -390
- package/dist/designer.js.map +3 -3
- package/dist/engine.worker.bwip.js +51422 -0
- package/dist/engine.worker.bwip.js.map +6 -0
- package/dist/engine.worker.js +59582 -26
- package/dist/engine.worker.js.map +3 -3
- package/dist/peer/{chunk-WSNRD2AQ.js → chunk-3EYYRJR4.js} +13 -12
- package/dist/{chunk-Q6MMPKQA.js.map → peer/chunk-3EYYRJR4.js.map} +1 -1
- package/dist/peer/{chunk-TSC4RAH3.js → chunk-3XZY54LM.js} +1351 -75
- package/dist/peer/chunk-3XZY54LM.js.map +6 -0
- package/dist/peer/chunk-5RUNOIS7.js +33 -0
- package/dist/peer/chunk-5RUNOIS7.js.map +6 -0
- package/dist/peer/{chunk-6I2EAAVN.js → chunk-7IP67PA6.js} +47 -26
- package/dist/peer/chunk-7IP67PA6.js.map +6 -0
- package/dist/peer/{chunk-R4VX5UC7.js → chunk-A6UXBSTP.js} +8 -8
- package/dist/peer/{chunk-V42KN7HD.js → chunk-CFTFTV2O.js} +6 -6
- package/dist/peer/chunk-JQTRDHQP.js +866 -0
- package/dist/peer/chunk-JQTRDHQP.js.map +6 -0
- package/dist/peer/chunk-KD6CDYGE.js +5024 -0
- package/dist/peer/chunk-KD6CDYGE.js.map +6 -0
- package/dist/peer/chunk-MXR6JBMP.js +546 -0
- package/dist/peer/chunk-MXR6JBMP.js.map +6 -0
- package/dist/peer/chunk-N42DCZZA.js +378 -0
- package/dist/peer/chunk-N42DCZZA.js.map +6 -0
- package/dist/{chunk-6TPZ7G74.js → peer/chunk-RKFP7SDY.js} +292 -25
- package/dist/peer/chunk-RKFP7SDY.js.map +6 -0
- package/dist/peer/{chunk-BMAXIBP2.js → chunk-WABYQWMT.js} +13 -13
- package/dist/peer/{chunk-BMAXIBP2.js.map → chunk-WABYQWMT.js.map} +1 -1
- package/dist/peer/chunk-WVQQCD4M.js +14211 -0
- package/dist/peer/chunk-WVQQCD4M.js.map +6 -0
- package/dist/peer/chunk-XHCRHVRK.js +17 -0
- package/dist/peer/chunk-XHCRHVRK.js.map +6 -0
- package/dist/peer/{chunk-WQGENQZO.js → chunk-ZS3J4WBH.js} +11 -9
- package/dist/peer/chunk-ZS3J4WBH.js.map +6 -0
- package/dist/peer/designer.js +455 -247
- package/dist/peer/designer.js.map +3 -3
- package/dist/peer/engine.worker.bwip.js +51422 -0
- package/dist/peer/engine.worker.bwip.js.map +6 -0
- package/dist/peer/engine.worker.js +59582 -25
- package/dist/peer/engine.worker.js.map +3 -3
- package/dist/peer/viewer.js +16 -12
- package/dist/peer/viewer.js.map +1 -1
- package/dist/viewer.d.ts +2 -1
- package/dist/viewer.js +16 -12
- package/dist/viewer.js.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-3D2KFKG2.js.map +0 -6
- package/dist/chunk-6TPZ7G74.js.map +0 -6
- package/dist/chunk-BRB34AJ2.js +0 -16
- package/dist/chunk-M6AYND5G.js.map +0 -6
- package/dist/chunk-NR2G4TMG.js.map +0 -6
- package/dist/chunk-PGP3QA6L.js.map +0 -6
- package/dist/chunk-S2IUUI6N.js.map +0 -6
- package/dist/chunk-ULKEEARQ.js +0 -553
- package/dist/chunk-ULKEEARQ.js.map +0 -6
- package/dist/chunk-VNOWPSE6.js.map +0 -6
- package/dist/chunk-Z7MKH66Z.js.map +0 -6
- package/dist/peer/chunk-2FZTYEDE.js +0 -15
- package/dist/peer/chunk-6I2EAAVN.js.map +0 -6
- package/dist/peer/chunk-BQFI3DHK.js.map +0 -6
- package/dist/peer/chunk-TSC4RAH3.js.map +0 -6
- package/dist/peer/chunk-WQGENQZO.js.map +0 -6
- package/dist/peer/chunk-WSNRD2AQ.js.map +0 -6
- /package/dist/{chunk-DXHLIJEY.js.map → chunk-47ZAKRVN.js.map} +0 -0
- /package/dist/{chunk-2BPBQMH2.js.map → chunk-H422SRD3.js.map} +0 -0
- /package/dist/{chunk-BRB34AJ2.js.map → chunk-JD6EJ3LI.js.map} +0 -0
- /package/dist/{peer/chunk-2FZTYEDE.js.map → chunk-XXTAPZO4.js.map} +0 -0
- /package/dist/peer/{chunk-R4VX5UC7.js.map → chunk-A6UXBSTP.js.map} +0 -0
- /package/dist/peer/{chunk-V42KN7HD.js.map → chunk-CFTFTV2O.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,99 @@
|
|
|
2
2
|
|
|
3
3
|
All `@reportwright/*` packages (formerly `@pagewrightjs/*`) share one version. The versioning policy is in [CONTRIBUTING.md](CONTRIBUTING.md#versioning-semver).
|
|
4
4
|
|
|
5
|
+
## 0.13.1 — 2026-10-09
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **N10: the CJK fonts are named Regular in the PDF.** `@reportwright/fonts-cjk` downloads variable TrueType fonts whose default instance is Thin; 0.13.0 cut and renamed the subset at Regular, but `exportPdf` and `exportPdfStream` built the BaseFont from the full font's PostScript name, so pdffonts showed `NotoSansJP-Thin` / `NotoSansKR-Thin`. Both now take the name from the subset they embed (`NotoSansJP-Regular`). Test: tests/engine/b11-cjk-names.test.js (the downloaded fonts are tested when present).
|
|
9
|
+
- **N44: a streamed tagged PDF's memory stays flat.** The writer kept where each object is in arrays of 7 bytes an object that doubled; a tagged million-row ledger has 8–11 million objects (an element per cell), most of tagging's ~125 MB at 1M rows. They are now blocks of 16,384 entries, each deflated (~2 KB) once the numbers are two blocks past; the tagger lets go of a page's elements when it ends. Same file byte for byte (but its ID): veraPDF UA-1 and A-2a pass, same `pdfinfo -struct` tree. Off-heap peak at 50k/100k/200k rows: 16.8/29.1/36.6 MB before, 6.7/7.3/9.3 MB after (RSS ~205 MB either way). Test: tests/engine/b11-n44-tagged-memory.test.js.
|
|
10
|
+
- **N45: `pw render` stopped by a signal leaves no temporary file.** SIGTERM (Docker, Kubernetes, CI), SIGINT (Ctrl+C) and SIGHUP remove `<file>.<pid>.part`, keep an older PDF at the path as it was, and exit 143, 130 or 129. Before, every one of them left the `.part` file. Test: tests/engine/b10-perf-cli.test.js.
|
|
11
|
+
- **N41: a copied worker starts.** The npm package's `engine.worker.js` bundles its libraries (bidi-js, fontkit) instead of importing them by name, so an esbuild app that copies it next to its bundle renders in the worker (it crashed with "Failed to resolve module specifier bidi-js" and fell back to the main thread). Barcodes and the standard-font metrics are files next to it (`engine.worker.bwip.js`, `engine.worker.stdfonts.js`), as in the browser build; the README says to copy `engine.worker*.js`. Test: tests/e2e/b11-esbuild-worker.mjs.
|
|
12
|
+
- **N40: `fonts` is optional.** `render()`, `exportPdf()`, `exportPdfStream()` and the Word, Excel and PowerPoint exports use one default store over `@reportwright/fonts` when given none, and an export loads the fonts the model uses into whatever store it gets, so render and export need not share a store (it failed with "this.loader is not a function" or 'Font "Helvetica" is not loaded'). A report in the standard PDF fonts needs no store and no fonts package (a bold title in a Helvetica report no longer loads Inter-Bold); a font that cannot load says "Install @reportwright/fonts, or pass { fontStore }". Test: tests/engine/b11-fonts-n40.test.js, and the packed packages in all four combinations (packages.test.js).
|
|
13
|
+
- **N19: one warning prefix.** The engine package's console warnings and deprecations start with `[reportwright]`, as the rest do (they said `[@reportwright/engine]`).
|
|
14
|
+
- **N43: the standard-font metrics are a table.** Helvetica, Times, Courier, Symbol and ZapfDingbats widths and font-wide metrics are generated once from the Adobe AFM data (`scripts/gen-standard-metrics.mjs` → `src/engine/text/standard-metrics.js`, 22 KB, 5 KB gzipped) instead of decompressed with pako from `@pdf-lib/standard-fonts` at every cold start; that package is no longer a dependency of `@reportwright/engine` or `@reportwright/viewer` (pdf-lib still installs it for itself), and the viewer's `engine.worker.stdfonts.js` is gone (the table is in the worker: 588 → 594 KB gzipped, about 100 KB gzipped less in all). PDFs are byte-identical. A new process making a 1-page Helvetica invoice: median of 10, 115 → 94 ms on an M2 (Node 20). Test: tests/engine/b11-fonts-n43.test.js.
|
|
15
|
+
- **N42: the designer Outline passes axe.** It was a `listbox` whose rows also hold their move buttons (a listbox may hold only options: aria-required-children, critical). The rows are now toggle buttons (`aria-pressed`) in a labelled group, with the same keyboard: one Tab stop, Up/Down/Home/End, Enter or Space selects.
|
|
16
|
+
- **N44: a large sort's memory stays flat.** The disk spill behind grouped and sorted streamed reports held a 1,000-row batch from every sorted run while merging (50 runs at 1,000,000 rows), so its memory grew with the rows. Runs are now about 8 MB (at most 10,000 rows), batches 200 rows, and the merge holds about 4 MB: past that many runs, groups of runs are merged on disk first. A 200,000-row grouped ledger: 280 → 232 MB peak; the same with 50 runs (the run count of 1,000,000 rows): 296 → 240 MB. `spillSorter({ runMB, mergeMB })` sets them. The engine README recommends `presorted: true` with ORDER BY at the source for big grouped reports. Test: tests/engine/b11-mem-spill.test.js.
|
|
17
|
+
- **SILENT-6: an item taller than the page warns in `validate()`.** A body item taller than the room the page has for the body (the page less its margins, page header and footer, a body section's own page and bands counted) warns with both heights and what the render does: its lower part is cut at the page bottom (a text box's text of more than one line continues on the next page). Tables, matrices, lists and subreports, which split by their rows, and pageless pages are quiet. `render()` keeps its own warning where it cuts (with the page number) and does not repeat validate's. Test: tests/engine/b11-mem-silent6-tall.test.js.
|
|
18
|
+
- **N37: repeated copies cascade.** Ctrl+D (Duplicate) and Paste put a copy 12 pt right and down, and 12 more while an item already sits there, so copying the same item again and again fans the copies out instead of stacking them on the first copy. A pasted coordinate that is not a finite number starts at 0, and the steps are bounded, so a paste of hostile JSON (`1e309`, 2^60) cannot hang the tab. Test: tests/engine/b11-mem-designer-cascade.test.js.
|
|
19
|
+
|
|
20
|
+
## 0.13.0 — 2026-10-09
|
|
21
|
+
|
|
22
|
+
A minor release: new options (`largeReportRows`, `signal`, `warnOnLeave`, `onDirtyChange`), the 14 standard PDF fonts, streamed Excel and Word exports, and warnings where mistakes used to be silent. The tester's 0.12.1 tickets are fixed except where noted; fonts are still TTF (WOFF2 is not done).
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- **Cold Helvetica invoice (A1.1):** a report that names only the standard PDF fonts loads no font file and no fontkit (Inter loads in a second layout pass only when some text needs it, such as a character WinAnsi lacks), and `exportPdf` writes such a model (standard-font text, boxes, lines, links) with the engine's own PDF writer instead of pdf-lib. A new process making a 1-page Helvetica invoice PDF: about 115 ms instead of 224 ms on an M2, with the same text, fonts and page content. Embedded fonts, images, form fields, PDF/A, tagged, encrypted and signed files still go through pdf-lib.
|
|
26
|
+
- **Cold start (A1.1):** pdf-lib and fontkit load on first use (in Node through `require`, elsewhere `import()`), not
|
|
27
|
+
when the engine is imported: `import('@reportwright/engine')` takes about 42 ms instead of 175 ms on an M2, a render
|
|
28
|
+
loads only fontkit, and the streaming PDF writer never loads pdf-lib. A new process making a 1-page invoice PDF:
|
|
29
|
+
about 318 ms instead of 364 ms (most of what is left is compiling harfbuzz-subset.wasm, about 150 ms).
|
|
30
|
+
- **Large classic renders (A1.4, A1.5):** `render()` past 100,000 rows warns once (`Large report (N rows):
|
|
31
|
+
exportPdfStream writes it in about 320 MB; render + exportPdf holds it all in memory`), in the model's warnings and
|
|
32
|
+
once per process on the console. The threshold is the render option `largeReportRows` (100000; `0` or `false`: off). `exportPdf` takes a rendered model, so it cannot switch to streaming itself; the
|
|
33
|
+
engine README shows `exportPdfStream` with a sink that keeps the bytes.
|
|
34
|
+
- **Excel streams; Word is written page by page (A1.9):** `exportXlsxStream` keeps memory flat; `exportDocxStream` lowers it, but a Word export's memory still grows slowly with the rows, so it is not yet a flat stream. `exportDocxStream` and `exportXlsxStream` (engine package and `src/exporters/officestream.js`) write a report's Word or Excel file to a sink as its pages or rows are made, with `exportPdfStream`'s sink, `timeoutMs` and `signal`; a report that cannot stream is written whole (`why`). `exportDocx` writes the document XML into the zip page by page instead of holding it. Peak RSS of a Word export, 20k / 50k rows: 329 / 499 MB before (render + exportDocx), 259 / 286 MB streamed with a flat live heap (17.5 / 17.3 MB after GC); Excel 251 / 432 MB before, 125 / 126 MB streamed (`scripts/mem-office.mjs`).
|
|
35
|
+
- **Viewer first load (A1.6):** the embedded viewer no longer loads the engine (layout, expressions, charts, maps, barcodes) on the main thread up front: the worker renders, and the engine loads on the main thread on the first export, parameter list or main-thread render. First load 827 → 652 KB gzipped (about 262 KB once fontkit loads lazily); the render worker 908 → 579 KB, with bwip-js in `engine.worker.bwip.js` beside it, imported for a report with a barcode (a worker copied alone renders such a report on the main thread). `tests/engine/b10-bundle-size.test.js` holds both to a budget.
|
|
36
|
+
- **`pw render -f pdf` streams (A1.4):** into a file, a flowing report is written by `exportPdfStream` (the message says
|
|
37
|
+
`streamed`; the text is the whole-model PDF's), through a temporary file renamed on success, so a failed run leaves
|
|
38
|
+
no damaged PDF. Encrypted files, reports that cannot stream and `-o -` render the whole model as before. A streamed
|
|
39
|
+
grouped report no longer warns that the group totals' internal fields (`__g0_0`) are missing.
|
|
40
|
+
- **First PDF of a cold process (Node):** harfbuzz-subset.wasm is compiled synchronously, which V8 does lazily; the async compile also optimized the whole module in the background, and the first export waited for it. A cold 1-page invoice in Inter: export 215 ms → 40 ms, whole process 498 ms → 305 ms (median of 10, M2). Browsers keep the async compile. A PDF in the standard fonts never loads the subsetter.
|
|
41
|
+
- **CJK fonts survive upgrades (N10):** `@reportwright/fonts-cjk` downloads into a cache folder outside the package (`REPORTWRIGHT_FONTS_DIR`, else `$XDG_CACHE_HOME/reportwright/fonts-cjk`, else `%LOCALAPPDATA%\reportwright\fonts-cjk` on Windows or `~/.cache/reportwright/fonts-cjk`), so upgrading the package no longer deletes them; `defaultFontStore()` reads that folder, then the package's old `fonts/` folder, so existing installs keep working. New exports: `cacheDir()`, `fontPath(name)`.
|
|
42
|
+
- **The 14 standard PDF fonts (A1.2):** `fontFamily` `Helvetica`, `Times-Roman` and `Courier` (four faces each, PostScript names such as `Helvetica-BoldOblique`), `Symbol` and `ZapfDingbats` are named in the PDF and not embedded (Type1, WinAnsiEncoding, the Adobe AFM widths from `@pdf-lib/standard-fonts`); layout measures with the same widths. Aliases: Arial → Helvetica, Times New Roman → Times-Roman, Courier New → Courier. An invoice in Helvetica is about 1.6 KB. Characters WinAnsi lacks are drawn in Inter with a warning; PDF/A and PDF/UA embed Inter (JetBrains Mono for Courier) at the standard font's glyph positions, with a warning; `exportPdfStream` does the same. SVG/HTML name the font with a CSS fallback list, Word and PowerPoint name Arial, Times New Roman or Courier New. `@pdf-lib/standard-fonts` (already installed with pdf-lib) is now a declared dependency, kept external in the packages.
|
|
43
|
+
- **Unknown fonts (N39):** a `fontFamily` the engine does not have is no longer swapped silently: the render warns once per name (`Font "NoSuchFont" is not available; using Inter.`), and monospace names (Consolas, Menlo, Monaco…) use the shipped JetBrains Mono instead of Inter, so aligned columns stay aligned. Family names match in any case, a CSS list (`"Brand, Inter"`) uses its first available font, and the generic names `sans-serif` and `monospace` map to Inter and JetBrains Mono without a warning.
|
|
44
|
+
- **Streaming tickets, from the 0.12.1 retest (N23-N29):** `exportPdfStream` with `encrypt` or `prepare` and `sqlRows` no
|
|
45
|
+
longer fails with "Save the report first" (the rows are gathered for the whole-model render); a misspelled option
|
|
46
|
+
key (`encrpyt`, `windw`) warns with "Did you mean" in `render()`'s model warnings, `exportPdfStream`'s result and
|
|
47
|
+
`exportPdf`'s `onWarning`, and a misspelling of `encrypt` or `prepare` throws so no file is written without its
|
|
48
|
+
password or signature; `sqlRows` yielding single rows says "sqlRows must yield arrays of rows (got an object with
|
|
49
|
+
keys …)" and sync iterables are accepted; `spill.dir` that does not exist says so; `pw render --base` on a private
|
|
50
|
+
address names `--allow-internal`; README: the temp-file + rename pattern for a failed stream and a `pg` +
|
|
51
|
+
`pg-cursor` `sqlRows` example; the `exportPdf` option docs (pdfa, prepare, save) say what the code does.
|
|
52
|
+
- **Data and form-field retest tickets (B9):**
|
|
53
|
+
- A `number` (or `date`) field with text in it (N26) warns once per field with the first bad row and how many values
|
|
54
|
+
are empty, in a render and in a streamed export. Numeric strings such as "12.34" stay silent.
|
|
55
|
+
- A data set whose path matches an object that holds the rows (`data: { orders: { rows: [...] } }`) warns and names
|
|
56
|
+
the array key (N8). An object of fields, such as `$.meta`, does not.
|
|
57
|
+
- `validate()` warns on an aggregate with no scope outside a table, list or data-set item (it uses the first data
|
|
58
|
+
set), and on `nullable: false` or `allowBlank: false` with no default on a parameter that is not required.
|
|
59
|
+
- A form field has a `label` (falls back to `tooltip`); a tagged PDF uses it as the field's accessible name (`/TU`)
|
|
60
|
+
and warns for each field without one (N30).
|
|
61
|
+
- **Tagged PDF table of contents (N32):** a TOC is tagged `TOC > TOCI > Reference > Link`, with the entry text, its page number and the link annotation inside one Link (it was plain `P` elements with a Link around the number only), and its title is an `H1`. veraPDF PDF/UA-1: compliant. The streaming PDF's tagging is unchanged.
|
|
62
|
+
- **Cascading parameters in the viewer:** when a parent parameter changes, a dependent value its list no longer offers is replaced (by the default if still offered, else the first choice) in the state the run uses, and the report re-runs with it. Before, the panel dropped the value but the run kept the old one ("Delhi, South region" with no rows).
|
|
63
|
+
- **Viewer page thumbnails (A11Y-3):** `.vthumb` no longer has an `aria-label` that differs from its visible number (axe `label-content-name-mismatch`); its name "Page 1" comes from hidden text beside the visible 1.
|
|
64
|
+
- **Viewer worker fallback (N1):** when the render worker cannot load (Vite 7 without `worker: { format: 'es' }`, or esbuild not following `new Worker(new URL(...))`), the viewer logs once `[reportwright] worker did not load (<reason>); rendering on the main thread`, and `handle.usesWorker` says which one you got. The viewer README now starts with the bundler setup. No Vite plugin: the setting is one line.
|
|
65
|
+
- **Worker file (N18):** `engine.worker.js` is one self-contained file (no `chunk-*.js` imports), so copying it alone next to a page works.
|
|
66
|
+
- **Viewer fonts (N31):** the viewer fetches a font face only when the layout first needs it, not all seven up front. A report in Inter Regular and Bold now downloads 670 KB (two files) instead of 4.9 MB. Serve `fontsUrl` with `Cache-Control: public, max-age=31536000, immutable` (in the viewer README). WOFF2 for the browser is not done yet.
|
|
67
|
+
- **Streaming PDF (`exportPdfStream`) failures, from the 0.12.1 retest:**
|
|
68
|
+
- A sink that stops reading no longer hangs the export: `timeoutMs` covers the waits for drain (504, `code:
|
|
69
|
+
'ETIMEDOUT'`), a sink's `error` or `close` ends the wait, and the new `signal` option (an `AbortSignal`) stops the
|
|
70
|
+
export at its next wait (rows, sink, sort, page) with an `AbortError`. `sqlRows` gets `{ signal }` as its third
|
|
71
|
+
argument. On timeout or abort the rows' cursors are closed and spill files removed.
|
|
72
|
+
- **Polar chart without `xValue`** (the angle) says so in validate() and the render ("a polar chart needs xValue"), instead of
|
|
73
|
+
"N of N rows have no x or y value". A valid polar chart gets no warnings.
|
|
74
|
+
- **Variable font subsets say their weight:** a variable font cut at Regular is named Regular (family, subfamily, full and PostScript names) with usWeightClass 400, and its variation tables are dropped, in the PDF and HTML subsets.
|
|
75
|
+
- **Deprecation messages** all say "will be removed in 1.0" (exportHtml's said 0.9). A test greps the source for a deprecation string that names 0.9.
|
|
76
|
+
- **Rich text warnings** say "Rich text:" once (an unnamed item was named "Rich text" and the parser repeated it). The legend warning says what is accepted: a chart's legend is "bottom" or "none", and it is drawn at the bottom.
|
|
77
|
+
|
|
78
|
+
- **Designer (b9):**
|
|
79
|
+
- Embedded designer: `mountDesigner` asks before the page is left with unsaved changes (`warnOnLeave`, default
|
|
80
|
+
true; false leaves it to the host), and the handle has `isDirty()` and an `onDirtyChange(dirty)` option. The guard is
|
|
81
|
+
removed on save and on `unmount()` (N34). A blank report is named "Untitled report" (it was "New report").
|
|
82
|
+
- Keyboard: the outline rows are a listbox with one Tab stop (Up/Down/Home/End move, Enter or Space selects, Shift
|
|
83
|
+
adds; then Delete and the arrows act on the selection); the left rail's tabs take the focus to their section;
|
|
84
|
+
canvas items are Tab stops named "Text box T1, x 10, y 10" that Enter selects (N35).
|
|
85
|
+
- Paste uses the paste event's clipboard (no clipboard-read permission), else the copy made in this tab, and says
|
|
86
|
+
when there is nothing to paste (N36).
|
|
87
|
+
- Width and height are at least 1 pt (a line may be 0 one way) (N33). Ctrl+D offsets the copy by 12 pt, as a paste
|
|
88
|
+
does (N37).
|
|
89
|
+
- Opening a report gives an item without an `id` a stable one (a hash of its band, place and name), so the same
|
|
90
|
+
file always reads back the same; the other normalisation (names, band heights, a table's size) is unchanged (N38).
|
|
91
|
+
- Embedded designer (shadow root): the table cell menu acts again, and Esc and Ctrl+S work after a click on a band
|
|
92
|
+
label, a matrix or a drill-through in Preview.
|
|
93
|
+
- A table that gets taller (Add group) grows its band; a drop into a 0 pt band grows it. A number field dropped on a
|
|
94
|
+
group header cell gives `=Sum(...)`, as on a footer. A matrix value shown as a percentage gets the format P1 while
|
|
95
|
+
its format is still the default N0. The matrix's drill-down toggle starts closed, as the table's.
|
|
96
|
+
- Accessibility: the fx button is named "fx: Open the expression editor"; table row tags have 4.85:1 contrast.
|
|
97
|
+
|
|
5
98
|
## 0.12.1 — 2026-10-08
|
|
6
99
|
|
|
7
100
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,6 +4,21 @@
|
|
|
4
4
|
|
|
5
5
|
The ReportWright report viewer in any web app (React is bundled inside, in a shadow root, so your styles do not leak in). A React app imports `@reportwright/viewer/react-peer` (and `/react-peer/designer`) instead, the same viewer using the app's own React, so the page loads React once; `@reportwright/react` does this for you:
|
|
6
6
|
|
|
7
|
+
## Bundler setup (read this first)
|
|
8
|
+
|
|
9
|
+
The viewer renders in a Web Worker (`engine.worker.js`, one self-contained file next to the viewer). Bundlers that understand
|
|
10
|
+
`new Worker(new URL(...))` pick it up; two settings matter:
|
|
11
|
+
|
|
12
|
+
- **Vite 7**: set `worker: { format: 'es' }` in `vite.config.js`. Without it the build fails with
|
|
13
|
+
`Invalid value "iife" for option "worker.format"`.
|
|
14
|
+
- **esbuild** (plain bundling) does not follow `new Worker(new URL(...))`: copy the worker files next to your bundle:
|
|
15
|
+
`cp node_modules/@reportwright/viewer/dist/engine.worker*.js dist/`. `engine.worker.js` has no imports (its libraries are
|
|
16
|
+
inside it); `engine.worker.bwip.js` (barcodes) loads only when a report
|
|
17
|
+
needs it. Without it those reports render on the main thread, with the warning below.
|
|
18
|
+
|
|
19
|
+
If the worker cannot load, the viewer still renders, on the main thread (slow and janky at 100k rows), and logs once
|
|
20
|
+
`[reportwright] worker did not load (<reason>); rendering on the main thread`. `handle.usesWorker` tells you which one you got.
|
|
21
|
+
|
|
7
22
|
Import it through your bundler (Vite, webpack, esbuild, Rollup, Next…). Its third-party libraries (pdf-lib,
|
|
8
23
|
@pdf-lib/fontkit, bwip-js, fflate, bidi-js) are ordinary dependencies, pinned to the versions the tests ran
|
|
9
24
|
against, so the package itself holds only ReportWright's own readable code.
|
|
@@ -28,7 +43,7 @@ mountViewer('#report', {
|
|
|
28
43
|
});
|
|
29
44
|
```
|
|
30
45
|
|
|
31
|
-
Nothing calls `/api`; each font is downloaded once; the toolbar uses the system font.
|
|
46
|
+
Nothing calls `/api`; each font is downloaded once, and only when the layout first needs it (a report in Inter Regular and Bold fetches those two files, not all seven); the toolbar uses the system font.
|
|
32
47
|
|
|
33
48
|
If a font cannot be loaded (wrong `fontsUrl`, the folder not served), the report does not draw: the viewer shows
|
|
34
49
|
"The report did not run. Font "Inter-Regular" did not load (HTTP 404)" with a Retry button, and `onReady(error)` is called
|
|
@@ -37,6 +52,8 @@ with that error. Fix the path and retry; there is no fallback font. `onReady(err
|
|
|
37
52
|
you pass as `fontsUrl`; `fontsUrl` is not inferred from the package. Copying only `fonts/` works too
|
|
38
53
|
(PDFs then embed whole fonts, and PDF/A export needs `icc/`).
|
|
39
54
|
|
|
55
|
+
Serve `fontsUrl` with `Cache-Control: public, max-age=31536000, immutable`: the files do not change within a package version, so a returning visitor downloads none of them.
|
|
56
|
+
|
|
40
57
|
## What works standalone, what needs the server
|
|
41
58
|
|
|
42
59
|
The npm packages are a library: nothing here needs a ReportWright server. The server is a separate, self-hosted app
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
ReportWright is MIT licensed (see LICENSE). It ships or bundles the following third-party work, under their own licenses.
|
|
4
|
+
|
|
5
|
+
## Bundled code
|
|
6
|
+
|
|
7
|
+
| Component | Version | License | Used for |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| [HarfBuzz](https://github.com/harfbuzz/harfbuzz), compiled to WebAssembly by [harfbuzzjs](https://github.com/harfbuzz/harfbuzzjs) | harfbuzzjs 1.6.2 | HarfBuzz: "Old MIT" (below); harfbuzzjs: MIT, Copyright (c) 2019-2026 The harfbuzzjs project authors | text shaping (`harfbuzz.wasm`) and font subsetting (`harfbuzz-subset.wasm`) |
|
|
10
|
+
| [pdf-lib](https://github.com/Hopding/pdf-lib) | 1.17.1 | MIT, Copyright (c) 2019 Andrew Dillon | the classic PDF writer (encryption, `prepare`, `save`) |
|
|
11
|
+
| [@pdf-lib/fontkit](https://github.com/Hopding/fontkit) | 1.1.1 | MIT | reading font files |
|
|
12
|
+
| [@pdf-lib/standard-fonts](https://github.com/Hopding/standard-fonts) | 1.0.0 | MIT; the metrics are Adobe's AFM files for the 14 standard PDF fonts | Helvetica, Times and Courier widths: generated from its AFM data into src/engine/text/standard-metrics.js (scripts/gen-standard-metrics.mjs); the package itself is not a runtime dependency |
|
|
13
|
+
| [bwip-js](https://github.com/metafloor/bwip-js) | 4.11.4 | MIT | barcodes |
|
|
14
|
+
| [fflate](https://github.com/101arrowz/fflate) | 0.8.3 | MIT | zip and deflate (Excel, Word, PowerPoint, PDF streams) |
|
|
15
|
+
| [bidi-js](https://github.com/lojjic/bidi-js) | 1.0.3 | MIT | right-to-left text |
|
|
16
|
+
|
|
17
|
+
The full license text of each npm dependency is in its package under `node_modules`.
|
|
18
|
+
|
|
19
|
+
### HarfBuzz ("Old MIT" license)
|
|
20
|
+
|
|
21
|
+
HarfBuzz is licensed under the so-called "Old MIT" license. Its copyright holders are listed in
|
|
22
|
+
[COPYING](https://github.com/harfbuzz/harfbuzz/blob/main/COPYING) in the HarfBuzz repository.
|
|
23
|
+
|
|
24
|
+
> Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify,
|
|
25
|
+
> and distribute this software and its documentation for any purpose, provided that the above copyright notice and
|
|
26
|
+
> the following two paragraphs appear in all copies of this software.
|
|
27
|
+
>
|
|
28
|
+
> IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
|
|
29
|
+
> CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE COPYRIGHT HOLDER HAS
|
|
30
|
+
> BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
31
|
+
>
|
|
32
|
+
> THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
33
|
+
> MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE
|
|
34
|
+
> COPYRIGHT HOLDER HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
35
|
+
|
|
36
|
+
## Fonts (in @reportwright/fonts and @reportwright/fonts-cjk)
|
|
37
|
+
|
|
38
|
+
All fonts are under the [SIL Open Font License 1.1](https://openfontlicense.org); each family's license file ships next
|
|
39
|
+
to it in `public/fonts` (OFL-Inter.txt, OFL-JetBrainsMono.txt, OFL-NotoSans*.txt).
|
|
40
|
+
|
|
41
|
+
| Family | Source |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Inter | [rsms/inter](https://github.com/rsms/inter) |
|
|
44
|
+
| JetBrains Mono | [JetBrains/JetBrainsMono](https://github.com/JetBrains/JetBrainsMono) |
|
|
45
|
+
| Noto Sans Arabic, Bengali, Devanagari, Gujarati, Hebrew, Kannada, Khmer, Lao, Myanmar, Tamil, Telugu, Thai | [notofonts](https://github.com/notofonts) |
|
|
46
|
+
| Noto Sans CJK and Noto Emoji (fonts-cjk, downloaded on demand) | [notofonts](https://github.com/notofonts) |
|
|
47
|
+
|
|
48
|
+
## Colour profile
|
|
49
|
+
|
|
50
|
+
`sRGB-v2-magic.icc` (the PDF/A output intent) is from
|
|
51
|
+
[Compact-ICC-Profiles](https://github.com/saucecontrol/Compact-ICC-Profiles) by Clinton Ingram, released under
|
|
52
|
+
CC0 1.0 (public domain).
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
formatValue,
|
|
3
|
-
isoDate,
|
|
4
|
-
roundHalfAway
|
|
5
|
-
} from "./chunk-GJS242RR.js";
|
|
6
1
|
import {
|
|
7
2
|
mergedRegions,
|
|
8
3
|
needsTableData,
|
|
9
4
|
textRows
|
|
10
5
|
} from "./chunk-F6RMRXIN.js";
|
|
6
|
+
import {
|
|
7
|
+
formatValue,
|
|
8
|
+
isoDate,
|
|
9
|
+
roundHalfAway
|
|
10
|
+
} from "./chunk-GJS242RR.js";
|
|
11
11
|
import "./chunk-OLLMACWA.js";
|
|
12
12
|
|
|
13
13
|
// src/exporters/csv.js
|
|
@@ -95,4 +95,4 @@ export {
|
|
|
95
95
|
exportCsv,
|
|
96
96
|
writeCsvStream
|
|
97
97
|
};
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
98
|
+
//# sourceMappingURL=chunk-47ZAKRVN.js.map
|
|
@@ -1,33 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EXPORT_DEFAULTS,
|
|
3
3
|
arrangeToolbar,
|
|
4
|
+
clearStaleParams,
|
|
4
5
|
exportOptionsFrom,
|
|
5
6
|
fetchReport,
|
|
6
7
|
findText,
|
|
7
|
-
fontStore,
|
|
8
8
|
frozenAt,
|
|
9
9
|
galleyDefinition,
|
|
10
|
+
loadFontStore,
|
|
10
11
|
loadModelFonts,
|
|
11
12
|
loadReportFonts,
|
|
12
13
|
origin,
|
|
13
14
|
pageLinks,
|
|
14
15
|
paramChoices,
|
|
16
|
+
parameterOptions,
|
|
15
17
|
pdfBlob,
|
|
16
18
|
rangeValue,
|
|
17
19
|
readingText,
|
|
18
20
|
renderReport,
|
|
21
|
+
reportFetch,
|
|
19
22
|
serverPdfUrl,
|
|
20
23
|
subsetter,
|
|
21
24
|
usingWorker
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import {
|
|
24
|
-
NO_CJK_FONTS,
|
|
25
|
-
parameterOptions,
|
|
26
|
-
reportFetch
|
|
27
|
-
} from "./chunk-VNOWPSE6.js";
|
|
25
|
+
} from "./chunk-ES2LYZ6S.js";
|
|
28
26
|
import {
|
|
29
|
-
|
|
30
|
-
} from "./chunk-
|
|
27
|
+
NO_CJK_FONTS
|
|
28
|
+
} from "./chunk-BR5K6SBL.js";
|
|
31
29
|
import {
|
|
32
30
|
needsExportData
|
|
33
31
|
} from "./chunk-F6RMRXIN.js";
|
|
@@ -35,10 +33,13 @@ import {
|
|
|
35
33
|
fontKeysOf,
|
|
36
34
|
linkTitle,
|
|
37
35
|
pageToSvg
|
|
38
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-U2ZY2NPQ.js";
|
|
39
37
|
import {
|
|
40
|
-
|
|
41
|
-
} from "./chunk-
|
|
38
|
+
safeUrl
|
|
39
|
+
} from "./chunk-72S6DETS.js";
|
|
40
|
+
import {
|
|
41
|
+
CORE_FONT_KEY
|
|
42
|
+
} from "./chunk-MS2LQC2O.js";
|
|
42
43
|
import {
|
|
43
44
|
__commonJS,
|
|
44
45
|
__toESM
|
|
@@ -19399,7 +19400,17 @@ usgewählte Liste oder den Container, sonst unter den Hauptteil", "選択した
|
|
|
19399
19400
|
b2_selItems: ["{n} items selected", "{n} आइटम चुने गए", "{n} elementos seleccionados", "{n} éléments sélectionnés", "{n} Elemente ausgewählt", "{n} 個の項目を選択", "已选择 {n} 个项目", "{n} itens selecionados", "تم تحديد {n} عناصر"],
|
|
19400
19401
|
b2_selBand: ["Band: {band}", "बैंड: {band}", "Banda: {band}", "Bande : {band}", "Bereich: {band}", "バンド: {band}", "区域:{band}", "Faixa: {band}", "النطاق: {band}"],
|
|
19401
19402
|
b2_selCell: ["Cell in {name}", "{name} में सेल", "Celda de {name}", "Cellule de {name}", "Zelle in {name}", "{name} のセル", "{name} 中的单元格", "Célula em {name}", "خلية في {name}"],
|
|
19402
|
-
b2_pageInfo: ["Page {size} · {w} × {h} {unit}", "पृष्ठ {size} · {w} × {h} {unit}", "Página {size} · {w} × {h} {unit}", "Page {size} · {w} × {h} {unit}", "Seite {size} · {w} × {h} {unit}", "ページ {size} · {w} × {h} {unit}", "页面 {size} · {w} × {h} {unit}", "Página {size} · {w} × {h} {unit}", "الصفحة {size} · {w} × {h} {unit}"]
|
|
19403
|
+
b2_pageInfo: ["Page {size} · {w} × {h} {unit}", "पृष्ठ {size} · {w} × {h} {unit}", "Página {size} · {w} × {h} {unit}", "Page {size} · {w} × {h} {unit}", "Seite {size} · {w} × {h} {unit}", "ページ {size} · {w} × {h} {unit}", "页面 {size} · {w} × {h} {unit}", "Página {size} · {w} × {h} {unit}", "الصفحة {size} · {w} × {h} {unit}"],
|
|
19404
|
+
// batch 9 (designer bugs)
|
|
19405
|
+
b9_nothingToPaste: ["Nothing to paste: copy items in a designer first (Ctrl+C)", "चिपकाने को कुछ नहीं: पहले डिज़ाइनर में आइटम कॉपी करें (Ctrl+C)", "Nada que pegar: copie primero elementos en un diseñador (Ctrl+C)", "Rien à coller : copiez d’abord des éléments dans un concepteur (Ctrl+C)", "Nichts zum Einf\
|
|
19406
|
+
ügen: zuerst Elemente in einem Designer kopieren (Strg+C)", "貼り付けるものがありません。先にデザイナーで項目をコピーしてください (Ctrl+C)", "没有可粘贴的内容:请先在设计器中复制项目 (Ctrl+C)", "Nada para colar: copie primeiro itens em um designer (Ctrl+C)", "لا شيء للصق: انسخ عناصر في مصمم أولاً (Ctrl+C)"],
|
|
19407
|
+
b9_itemLabel: ["{type} {name}, x {x}, y {y}", "{type} {name}, x {x}, y {y}", "{type} {name}, x {x}, y {y}", "{type} {name}, x {x}, y {y}", "{type} {name}, x {x}, y {y}", "{type} {name}、x {x}、y {y}", "{type} {name},x {x},y {y}", "{type} {name}, x {x}, y {y}", "{type} {name}، x {x}، y {y}"],
|
|
19408
|
+
b9_outlineKeys: ["Up and Down move between rows; Enter or Space selects (Shift adds); then Delete removes and the arrows move the selection on the page", "ऊपर और नीचे पंक्तियों के बीच जाते हैं; Enter या Space चुनता है (Shift जोड़ता है); फिर Delete हटाता है और तीर पेज पर चयन को खिसकाते हैं",
|
|
19409
|
+
"Arriba y Abajo cambian de fila; Intro o Espacio selecciona (Mayús añade); luego Supr elimina y las flechas mueven la selección en la página", "Haut et Bas passent d’une ligne à l’autre ; Entrée ou Espace sélectionne (Maj ajoute) ; ensuite Suppr supprime et les flèches déplacent la sélection sur la page", "Auf und Ab wechseln die Zeile; Eingabe oder Leertaste wählt aus (Umschalt fü\
|
|
19410
|
+
gt hinzu); dann löscht Entf und die Pfeile verschieben die Auswahl auf der Seite", "上下で行を移動、Enter または Space で選択 (Shift で追加)。その後 Delete で削除、矢印でページ上の選択を移動", "上下键在行间移动;Enter 或空格选择(Shift 添加);然后 Delete 删除,方向键在页面上移动所选项", "Cima e Baixo mudam de linha; Enter \
|
|
19411
|
+
ou Espaço seleciona (Shift adiciona); depois Delete remove e as setas movem a seleção na página", "السهمان لأعلى ولأسفل للتنقل بين الصفوف؛ Enter أو المسافة للتحديد (Shift للإضافة)؛ ثم Delete للحذف والأسهم لتحريك التحديد في الصفحة"],
|
|
19412
|
+
p_field_label: ["Label (the name a screen reader says)", "लेबल (स्क्रीन रीडर जो नाम बोलता है)", "Etiqueta (el nombre que dice un lector de pantalla)", "Libellé (le nom que lit un lecteur d’écran)", "Beschriftung (der Name, den ein Screenreader vorliest)", "ラベル (スクリーンリーダーが読み上げる名前)", "标签(屏幕阅读器读出的名称)",
|
|
19413
|
+
"Rótulo (o nome que um leitor de tela diz)", "التسمية (الاسم الذي يقرؤه قارئ الشاشة)"]
|
|
19403
19414
|
};
|
|
19404
19415
|
var b2_default = Object.fromEntries(LANGS.map((l, i) => [l, Object.fromEntries(Object.entries(ROWS).map(([k, v]) => [k, v[i]]))]));
|
|
19405
19416
|
|
|
@@ -19448,7 +19459,7 @@ var import_react = __toESM(require_react(), 1);
|
|
|
19448
19459
|
|
|
19449
19460
|
// src/viewer/exports.js
|
|
19450
19461
|
async function loadedFonts(model) {
|
|
19451
|
-
const store =
|
|
19462
|
+
const store = await loadFontStore();
|
|
19452
19463
|
await store.load(fontKeysOf(model));
|
|
19453
19464
|
return store;
|
|
19454
19465
|
}
|
|
@@ -19464,10 +19475,10 @@ async function exportBlob(fmt, model, def, opt = {}) {
|
|
|
19464
19475
|
const o = { ...EXPORT_DEFAULTS, ...opt.options || {} };
|
|
19465
19476
|
const lang = def.locale || opt.lang || "en";
|
|
19466
19477
|
if (fmt === "json") return new Blob([JSON.stringify(model)], { type: "application/json" });
|
|
19467
|
-
if (fmt === "csv") return new Blob([(await import("./chunk-
|
|
19478
|
+
if (fmt === "csv") return new Blob([(await import("./chunk-47ZAKRVN.js")).exportCsv(model, { locale: def.locale, currency: def.currency })], { type: "text/csv;charset=utf-8" });
|
|
19468
19479
|
if (fmt === "html" && opt.interactive !== false && o.html === "interactive") {
|
|
19469
19480
|
try {
|
|
19470
|
-
const { exportInteractiveHtml } = await import("./chunk-
|
|
19481
|
+
const { exportInteractiveHtml } = await import("./chunk-PF4RFKX2.js");
|
|
19471
19482
|
const { html } = await exportInteractiveHtml(def, { params: opt.params, reportId: opt.reportId, lang: opt.lang, model });
|
|
19472
19483
|
return new Blob([html], { type: "text/html;charset=utf-8" });
|
|
19473
19484
|
} catch (e) {
|
|
@@ -19477,19 +19488,19 @@ async function exportBlob(fmt, model, def, opt = {}) {
|
|
|
19477
19488
|
}
|
|
19478
19489
|
if (fmt === "html") {
|
|
19479
19490
|
const store = await loadedFonts(model);
|
|
19480
|
-
const { exportHtml } = await import("./chunk-
|
|
19491
|
+
const { exportHtml } = await import("./chunk-WOBRKNIA.js");
|
|
19481
19492
|
return new Blob([await exportHtml(model, { fonts: store, title: def.name, subset: subsetter, drillBase: origin(), static: o.html === "static", locale: def.locale, currency: def.currency, lang: opt.lang, strings: opt.strings })], { type: "text/html;charset=utf-8" });
|
|
19482
19493
|
}
|
|
19483
19494
|
if (fmt === "docx") {
|
|
19484
|
-
const { exportDocx } = await import("./chunk-
|
|
19495
|
+
const { exportDocx } = await import("./chunk-JD6EJ3LI.js");
|
|
19485
19496
|
return new Blob([await exportDocx(model, { title: def.name, lang, fontStore: await loadedFonts(model), fetchImage })], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
|
|
19486
19497
|
}
|
|
19487
19498
|
if (fmt === "pptx") {
|
|
19488
|
-
const { exportPptx } = await import("./chunk-
|
|
19499
|
+
const { exportPptx } = await import("./chunk-GRYITZPG.js");
|
|
19489
19500
|
return new Blob([await exportPptx(model, { title: def.name, lang, fontStore: await loadedFonts(model), fetchImage })], { type: "application/vnd.openxmlformats-officedocument.presentationml.presentation" });
|
|
19490
19501
|
}
|
|
19491
19502
|
if (fmt === "xlsx") {
|
|
19492
|
-
const { exportXlsx } = await import("./chunk-
|
|
19503
|
+
const { exportXlsx } = await import("./chunk-H422SRD3.js");
|
|
19493
19504
|
const bytes = await exportXlsx(model, { currency: def.currency, title: def.name, formulas: o.formulas, fontStore: await loadedFonts(model), fetchImage });
|
|
19494
19505
|
return new Blob([bytes], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
|
|
19495
19506
|
}
|
|
@@ -19735,9 +19746,10 @@ var Thumb = ({ page, w, h, n, current, near, onGo, T }) => {
|
|
|
19735
19746
|
(0, import_react.useEffect)(() => {
|
|
19736
19747
|
if (current) ref.current?.scrollIntoView?.({ block: "nearest" });
|
|
19737
19748
|
}, [current]);
|
|
19738
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { ref, type: "button", className: "vthumb", "aria-current": current ? "page" : void 0,
|
|
19749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { ref, type: "button", className: "vthumb", "aria-current": current ? "page" : void 0, onClick: () => onGo(n), children: [
|
|
19739
19750
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vthumb-sheet", style: { aspectRatio: `${w} / ${h}` }, children: near && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SvgHtml, { as: "span", html, "aria-hidden": "true" }) }),
|
|
19740
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "
|
|
19751
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "sr-only", children: T("b2_pageN", { n }) }),
|
|
19752
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "vthumb-n", "aria-hidden": "true", children: n })
|
|
19741
19753
|
] });
|
|
19742
19754
|
};
|
|
19743
19755
|
var Skeleton = ({ def, scale, T }) => {
|
|
@@ -19861,7 +19873,7 @@ function ReportViewer({ definition: rootDef, reportId: rootReportId, params: roo
|
|
|
19861
19873
|
const onRetry = (r) => {
|
|
19862
19874
|
if (id === runId.current) setStatus({ state: "running", retry: r });
|
|
19863
19875
|
};
|
|
19864
|
-
const [m, defaultFailed] = await Promise.all([renderReport(renderDef, p, { ...st, target: "screen" }, reportId, { onPartial, onRetry }), loadReportFonts(
|
|
19876
|
+
const [m, defaultFailed] = await Promise.all([renderReport(renderDef, p, { ...st, target: "screen" }, reportId, { onPartial, onRetry }), loadReportFonts([CORE_FONT_KEY])]);
|
|
19865
19877
|
const failed = [...defaultFailed, ...await loadModelFonts(m)];
|
|
19866
19878
|
if (id !== runId.current) return;
|
|
19867
19879
|
setModel(m);
|
|
@@ -19977,11 +19989,20 @@ function ReportViewer({ definition: rootDef, reportId: rootReportId, params: roo
|
|
|
19977
19989
|
const optKey = JSON.stringify(params);
|
|
19978
19990
|
(0, import_react.useEffect)(() => {
|
|
19979
19991
|
if (!(definition.parameters || []).some((p) => p.options || p.optionsFrom)) return;
|
|
19992
|
+
let stale = false;
|
|
19980
19993
|
const t2 = setTimeout(() => {
|
|
19981
|
-
parameterOptions(definition, params, { baseUrl: origin(), reportId, fetch: reportFetch(origin()) }).then((o) =>
|
|
19994
|
+
parameterOptions(definition, params, { baseUrl: origin(), reportId, fetch: reportFetch(origin()) }).then((o) => {
|
|
19995
|
+
if (stale) return;
|
|
19996
|
+
const choices = paramChoices(definition, o);
|
|
19997
|
+
setOptions(choices);
|
|
19998
|
+
setParams((s) => clearStaleParams(definition, s, choices));
|
|
19999
|
+
}).catch(() => {
|
|
19982
20000
|
});
|
|
19983
20001
|
}, 250);
|
|
19984
|
-
return () =>
|
|
20002
|
+
return () => {
|
|
20003
|
+
stale = true;
|
|
20004
|
+
clearTimeout(t2);
|
|
20005
|
+
};
|
|
19985
20006
|
}, [definition, optKey]);
|
|
19986
20007
|
(0, import_react.useEffect)(() => {
|
|
19987
20008
|
const el = scroller.current, rt = root.current;
|
|
@@ -20687,4 +20708,4 @@ export {
|
|
|
20687
20708
|
ReportViewer,
|
|
20688
20709
|
uiFontCss
|
|
20689
20710
|
};
|
|
20690
|
-
//# sourceMappingURL=chunk-
|
|
20711
|
+
//# sourceMappingURL=chunk-B5ZCT3UK.js.map
|