@quario/viewer 0.7.0 → 0.8.0

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 CHANGED
@@ -1,15 +1,52 @@
1
- # Changelog
2
-
3
- All notable changes to @quario/viewer are documented in this file.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [Unreleased]
9
-
10
- ## [0.7.0] - 2026-09-07
11
-
12
- ### Added
1
+ # @quario/viewer
2
+
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **An image's box is now as wide as the container it sits in.** A
8
+ `background` or `border*` on an image item hugged the picture and now spans
9
+ the content width, or the slot's share inside a split; the picture itself
10
+ does not move. See the `@quario/layout` changelog for the rule and for what
11
+ it costs a report that relied on a border hugging a logo.
12
+ - **Only the pages you can see are on the sheet.** A page outside the reach
13
+ used to be an empty canvas holding its place; now it has no element at all,
14
+ and the sheet carries the document's extent itself — its height and width are
15
+ written from the layout, and it paints the page silhouettes. The stretch a
16
+ reader scrolls through is exactly what it was, and a scale change no longer
17
+ costs the browser a relayout of every page: that was around 10 microseconds a
18
+ page, so a five-thousand-page report paid roughly 50 ms of it each time.
19
+
20
+ This changes the sheet's markup, which matters if you style it. `.qv-page` is
21
+ now absolutely positioned inside `.qv-sheet`, and is present only for the pages
22
+ on screen and one viewport height either side. A rule that gave a page a
23
+ margin, or that relied on the pages being a flow of siblings, no longer
24
+ applies — the sheet places its own pages, and does it with inline styles a
25
+ stylesheet rule cannot override. `--qv-sheet-shadow` is unchanged.
26
+
27
+ One cost, stated: a page outside the reach has no `role="img"` node, so
28
+ assistive technology sees the few images of the reach renumbering as the
29
+ reader scrolls rather than a document of named pages.
30
+
31
+ ### Patch Changes
32
+
33
+ - **Every published README says where the documentation is.** Each package now
34
+ carries a Documentation section pointing at the reference, at the report schema
35
+ that normatively specifies what a report may declare, and at the package's own
36
+ API. The paragraphs that used to end on an unstated contract — the event
37
+ stream's field semantics, the style vocabulary, page columns, the Content
38
+ Security Policy a fragment with images needs, the formula mangling, and each
39
+ target's own contract — link the page that states it. Every link is an absolute
40
+ URL, so it resolves from the npm package page as readily as from an installed
41
+ copy.
42
+ - Updated dependencies
43
+ - @quario/layout@0.5.0
44
+ - @quario/landing@0.2.0
45
+ - quario@0.8.0
46
+
47
+ ## 0.7.0
48
+
49
+ ### Minor Changes
13
50
 
14
51
  - **`fonts` is validated as a host property.** It was the one the viewer never
15
52
  checked, so a malformed record reached the target inside the render and came
@@ -18,9 +55,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
18
55
  on the target's `options.fonts`. A face that will not parse, or a missing
19
56
  parser, is still found while the report is measured and remains a render
20
57
  failure there.
21
-
22
- ### Changed
23
-
24
58
  - **A rejected host property reports as `host-option`.** `ViewerErrorKind`
25
59
  gains a fourth member, so a host switching exhaustively over the kind needs
26
60
  a case for it. A `page`, `zoom`, `filename`, `colorScheme` or `fonts` the
@@ -33,9 +67,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
33
67
  are refused where the render begins rather than when the property is written,
34
68
  so nothing yet tells them apart from a render that failed.
35
69
 
36
- ## [0.6.0] - 2026-09-07
70
+ ## 0.6.0
37
71
 
38
- ### Changed
72
+ ### Minor Changes
39
73
 
40
74
  - **Numbers presented through `format` now show a fixed two fraction digits**,
41
75
  the same as every other target: `1,000.00` where the preview showed `1,000`,
@@ -43,9 +77,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
77
  a universal two. The digits come from the engine, so a page on screen and
44
78
  the PDF of it agree. A formatted cell is also up to three characters wider,
45
79
  so a line that just fitted can wrap and move a page break.
46
-
47
- ### Fixed
48
-
49
80
  - **A page the browser cannot fully paint no longer fails the render.** An
50
81
  image whose pixel data is corrupt past the size in its header left that page
51
82
  blank _and_ rejected `renderComplete`, so a host awaiting it saw an unhandled
@@ -55,29 +86,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55
86
  fires, and no `error` event is raised. It never rejects for this reason
56
87
  again: a page that cannot be drawn is blank, not a failed render.
57
88
 
58
- ## [0.5.0] - 2026-09-05
89
+ ## 0.5.0
59
90
 
60
- ### Changed
91
+ ### Minor Changes
61
92
 
62
93
  - **Previewing with `fonts` now needs `fontkit`, not `@pdf-lib/fontkit`.**
63
94
  Install `fontkit` instead. The viewer measures host TrueType faces through
64
95
  `@quario/layout`, whose optional parser this is; the old package crashed on
65
96
  any OpenType face needing a shaping state machine, so those faces now
66
97
  preview where they used to throw.
67
-
68
98
  - **The bar's controls are drawn icons.** The zoom trigger, the menu's check
69
99
  and the error panel's dismiss are drawn from Lucide's set rather than by
70
100
  hand, at one weight and one grid, and the dismiss no longer relies on the
71
101
  host's font to draw a multiplication sign. They paint in `currentColor`, so
72
102
  `--qv-icon` and `--qv-icon-active` still recolour them.
73
-
74
103
  - **An export button names its format in words.** Each one is a download icon
75
104
  with `PDF`, `XLSX` or `CSV` beside it, in place of the sheet drawing that
76
105
  lettered the format inside itself. The buttons are wider; the accessible
77
106
  name is unchanged.
78
-
79
- ### Fixed
80
-
81
107
  - **A zoom no longer leaves a page part-drawn.** Changing the zoom while a
82
108
  page was still painting could leave that page carrying content at the old
83
109
  scale on a canvas sized for the new one — the rest of it blank — and nothing
@@ -85,27 +111,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
85
111
  whose paint is still in flight is now replaced rather than reused, so the
86
112
  superseded paint has nowhere to land.
87
113
 
88
- ## [0.4.0] - 2026-09-03
114
+ ## 0.4.0
89
115
 
90
- ### Added
116
+ ### Minor Changes
91
117
 
92
118
  - **`fonts`.** The font mapping a host passes to `pdf({ fonts })`, so the
93
119
  preview measures and draws in the same TrueType faces the document embeds.
94
-
95
- ### Changed
96
-
97
120
  - **`renderComplete` and `rendered` settle once the pages on screen are
98
121
  painted.** Both already answered for the newest render reaching the sheet;
99
122
  what that means is now stated: the pages the reader can see carry their
100
123
  pixels, and the pages further down the report do not hold the promise up.
101
124
  A screenshot or a pixel-reading test taken at that moment sees what the
102
125
  reader sees.
103
-
104
126
  - **A split slot's box now fills the split's height.** A slot's background and
105
127
  border stopped at that slot's own content and now take the split's height,
106
128
  the way a table cell's take their row's. See the `@quario/layout` changelog
107
129
  for the rule and for what it costs a report that relied on the short box.
108
-
109
130
  - **The sheet has pages, and they break where the PDF's do.** The viewer
110
131
  depends on `@quario/layout` and paints the same display list the pdf target
111
132
  writes, one canvas per page, in the faces the document itself uses.
@@ -115,9 +136,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
115
136
  `page` change re-lays the report out rather than resizing a sheet. The
116
137
  unlicensed marking is painted per page from the list; the `--qv-mark`
117
138
  token is gone with the DOM stamps.
118
-
119
- ### Fixed
120
-
121
139
  - **A long report no longer asks for a backing store per page.** The viewer
122
140
  paints the pages near the viewport — the ones on screen and one screenful
123
141
  either side — and keeps every other page sized but blank. A report of a
@@ -128,23 +146,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
128
146
  the first frame, and a zoom step now repaints a handful of pages instead of
129
147
  walking the document.
130
148
 
131
- ## [0.3.0] - 2026-09-02
149
+ ## 0.3.0
132
150
 
133
- ### Changed
151
+ ### Minor Changes
134
152
 
135
153
  - **Report and group containers are flex columns.** Adjacent authored
136
154
  `spaceBefore` / `spaceAfter` margins add rather than collapse, matching
137
155
  the html reference stylesheet.
138
-
139
- ### Fixed
140
-
141
156
  - **The adopted sheet occupies a line and preserves authored newlines.**
142
157
  Same `min-height: 1lh` and `white-space: pre-line` the html reference
143
158
  stylesheet now carries on `.q-item`, and `pre-line` on table cells.
144
159
 
145
- ## [0.2.0] - 2026-09-01
160
+ ## 0.2.0
146
161
 
147
- ### Changed
162
+ ### Minor Changes
148
163
 
149
164
  - **The sheet is now page-shaped, so short reports reserve a full page.**
150
165
  `page` sized the sheet's width and padding and ignored its height, so a
@@ -163,9 +178,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
163
178
  - **The adopted sheet's baseline face moved onto `.q-report`.** It was on
164
179
  `.q-item` and `.q-table`, where a direct rule would have beaten a report's
165
180
  own declared family. Same look; the fragment's new root is what carries it.
166
-
167
- ### Fixed
168
-
169
181
  - **The sheet no longer draws report text in the platform's own face.** It
170
182
  hard-coded `system-ui`, which is SF Pro on macOS, Segoe UI on Windows and
171
183
  Roboto on Android — so the same report showed a different typeface to every
@@ -174,9 +186,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
174
186
  resolves to Helvetica. The viewer's own chrome keeps `system-ui`, which is
175
187
  what a toolbar should do.
176
188
 
177
- ## [0.1.0] - 2026-08-27
189
+ ## 0.1.0
178
190
 
179
- ### Added
191
+ ### Minor Changes
180
192
 
181
193
  - **An embeddable `<quario-viewer>`.** Assign a compiled report, the targets
182
194
  to render with, and data; it shows the HTML report on a continuous sheet,
package/README.md CHANGED
@@ -314,6 +314,13 @@ reference seam, not a frozen vocabulary: backdrop and bar (`--qv-backdrop`, `--q
314
314
  The report itself is paint, not markup: there is no report stylesheet to restyle, because what
315
315
  you see is the layout the PDF target writes.
316
316
 
317
+ ## Documentation
318
+
319
+ [The quario documentation](https://getquario.com/docs/) is the reference.
320
+ The [report schema](https://getquario.com/docs/reference/report-schema/) is the normative
321
+ specification of what a report may declare, and
322
+ [`@quario/viewer`](https://getquario.com/docs/reference/viewer/) is this element's own API.
323
+
317
324
  ## License
318
325
 
319
326
  Commercial software with readable source. Free, unlimited, watermarked evaluation; per-developer
package/lib/icons.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * default, 14px in the gutter and the menu's tick slot — because `x` appears
5
5
  * in two contexts at once (ADR 0044).
6
6
  *
7
- * Generated by `scripts/icons.mjs` from lucide 1.40.0. Do not edit:
7
+ * Generated by `scripts/icons.mjs` from lucide 1.42.0. Do not edit:
8
8
  * `npm run icons` rewrites it, and `npm run check` regenerates it into a
9
9
  * temp directory and compares.
10
10
  *
package/lib/stage.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * The stage: the surface the pages are painted on. It owns the scroll
3
3
  * container the reader looks through, the wrapper that carries the gutter,
4
- * and the sheet — one canvas per page of the layout list, painted by
5
- * `@quario/layout`'s `paint` — their elements, their CSS, and every number
6
- * relating them.
4
+ * and the sheet — the layout list's whole extent, with a canvas for each page
5
+ * of the reach painted by `@quario/layout`'s `paint` — their elements, their
6
+ * CSS, and every number relating them.
7
7
  *
8
8
  * Zoom is a repaint, not a transform: each page canvas is sized to the
9
9
  * percentage in CSS pixels and painted at that scale times the device pixel
@@ -11,15 +11,17 @@
11
11
  * reader saw. The list never changes under a zoom — the preview scales and
12
12
  * never reflows (zoom.js says why).
13
13
  *
14
- * Every page keeps its CSS size, but only the
15
- * [reach](../../../CONTEXT.md#reach) carries pixels — the pages on screen and
16
- * one viewport height either side. The extent the reader scrolls through is
17
- * whole and synchronous whatever is painted; what comes and goes is the
18
- * backing store, released by sizing a canvas to 0 × 0. A scroll or a resize
19
- * runs the same arithmetic over the list's own geometry, coalesced to one
20
- * pass a frame. ADR 0043 says what that is worth: painting the whole sheet
21
- * asked a thousand-page report for gigabytes of backing store, and past what
22
- * the browser would grant the pages simply came up blank.
14
+ * The sheet carries the whole list's extent, but only the
15
+ * [reach](../../../CONTEXT.md#reach) carries elements and pixels — the pages
16
+ * on screen and one viewport height either side. The extent the reader scrolls
17
+ * through is whole and synchronous whatever is standing, because the sheet is
18
+ * given its height and width inline and paints the page silhouettes itself; a
19
+ * page leaving the reach is removed, which takes its backing store with it
20
+ * (ADR 0065). A scroll or a resize runs the same arithmetic over the list's own
21
+ * geometry, coalesced to one pass a frame. ADR 0043 says what the reach is
22
+ * worth: painting the whole sheet asked a thousand-page report for gigabytes of
23
+ * backing store, and past what the browser would grant the pages simply came up
24
+ * blank.
23
25
  *
24
26
  * **A page the browser will not paint is blank, not a failure.** `start`
25
27
  * swallows and nothing here rejects: the report laid out and the list reached
@@ -39,13 +41,14 @@
39
41
  * *retired* rather than painted over or emptied: it comes off the sheet, its
40
42
  * pixels go back, and a fresh one stands in its place, so the superseded
41
43
  * paint draws into an element nobody is looking at. A canvas whose paint has
42
- * settled has nothing that could land late and is re-sized or emptied in
43
- * place as before. Without this a zoom landing mid-paint could leave a page
44
+ * settled has nothing that could land late and is re-sized in place as before;
45
+ * a page leaving the reach is removed either way, which takes its pixels with
46
+ * it whether that paint has landed or not. Without this a zoom landing mid-paint could leave a page
44
47
  * carrying old-scale content on a new-scale canvas, with the memo below
45
48
  * calling it painted so that nothing repainted it again (ADR 0046).
46
49
  *
47
- * Retirement is lazy, and only the paint is guarded. A scale change sizes
48
- * every page's CSS box at once but retires a page only when the repaint loop
50
+ * Retirement is lazy, and only the paint is guarded. A scale change sizes the
51
+ * reach's CSS boxes at once but retires a page only when the repaint loop
49
52
  * reaches it, so a page further down the reach shows its old pixels stretched
50
53
  * into the new box until its turn comes — the ordinary look of a zoom in
51
54
  * progress, not the artefact above. The cost is that a retired page is a
@@ -70,12 +73,14 @@
70
73
  */
71
74
 
72
75
  import { css } from "lit";
73
- import { GAP, GUTTER, sheet } from "@quario/landing";
76
+ import { GUTTER, sheet } from "@quario/landing";
74
77
  import { PX_PER_POINT } from "@quario/layout";
75
78
 
76
- // `GUTTER` and `GAP` come from `@quario/landing`, which walks the reach over
77
- // them: the CSS below and the sheet's own arithmetic have to agree about where
78
- // a page sits, and two copies of that is a reach that paints the wrong pages.
79
+ // `GUTTER` comes from `@quario/landing`, which walks the reach over it: the CSS
80
+ // below and the sheet's own arithmetic have to agree about where a page sits,
81
+ // and two copies of that is a reach that paints the wrong pages. The gap
82
+ // between pages is that package's too, and is not named here at all — the sheet
83
+ // positions its own pages now, so this file has nothing to space.
79
84
 
80
85
  export let SURFACE = css`
81
86
  /* Where scrollbars take width, the gutter is held whether one is showing or
@@ -101,16 +106,17 @@ export let SURFACE = css`
101
106
  margin: ${GUTTER}px auto;
102
107
  }
103
108
 
104
- /* The sheet is the stack of pages. */
105
- .qv-sheet {
106
- display: flex;
107
- flex-direction: column;
108
- gap: ${GAP}px;
109
- }
109
+ /* The sheet is the whole document's extent, and the pages of the reach are
110
+ positioned inside it. It has no rule here because it has no look: its
111
+ position, its height, its width and its page silhouettes are all written
112
+ inline by \`@quario/landing\` from the list's own geometry, which is the one
113
+ place any of them is decided (ADR 0065). A page outside the reach has no
114
+ element, so what shows there is the sheet's own paint.
110
115
 
111
- /* One page. The painter fills it white; the background here is what a page
112
- outside the reach shows, and what one inside it shows between being sized
113
- and being painted. */
116
+ One page of the reach, at the size and offset the sheet gives it. The
117
+ painter fills it white; the background here is what it shows between being
118
+ placed and being painted, and the shadow is what lifts it off the sheet —
119
+ the two this file does decide. */
114
120
  .qv-page {
115
121
  display: block;
116
122
  background: #fff;
@@ -191,14 +197,17 @@ export let stage = () => {
191
197
  * offset; horizontally the wrapper is centred by auto margins while it
192
198
  * fits — which is exactly when `scrollLeft` is 0 anyway — and its margins
193
199
  * are 0 once it overflows, so the plain ratio holds wherever it can be
194
- * seen. The browser clamps whatever it cannot honour. An empty sheet has
195
- * no view to hold, which is what mounting at an authored zoom takes.
200
+ * seen. The browser clamps whatever it cannot honour. A sheet with no list
201
+ * on it has no view to hold, which is what mounting at an authored zoom
202
+ * takes. Asked of the list rather than of the sheet's children, which
203
+ * since ADR 0065 are the reach's and can be none of them while a list is
204
+ * standing — and it saves a DOM read besides.
196
205
  *
197
206
  * Only the reach is repainted, and only where the scale actually changed,
198
207
  * so a zoom step costs a handful of pages however long the report is.
199
208
  */
200
209
  scale: (percent) => {
201
- let held = sheetEl.firstChild && {
210
+ let held = paged.count() > 0 && {
202
211
  top: scroll.scrollTop,
203
212
  left: scroll.scrollLeft,
204
213
  height: scroll.clientHeight,
@@ -228,12 +237,12 @@ export let stage = () => {
228
237
 
229
238
  /**
230
239
  * Put a laid-out report on the sheet, keeping the reader where they
231
- * were: one canvas per page, the reach among them painted at the applied
232
- * scale. The order is the point of the method: the pages come off
233
- * `pageOf` already at their size, so the browser clamps the offsets going
234
- * back against the extent the sheet will have rather than the one it had
235
- * — and the reach is read from those offsets, so it is chosen after they
236
- * are in. What the
240
+ * were: the extent whole at once, with the reach's pages painted at the
241
+ * applied scale. The order is the point of the method: the sheet takes its
242
+ * height from the list before anything else, so the browser clamps the
243
+ * offsets going back against the extent the sheet will have rather than
244
+ * the one it had — and the reach is read from those offsets, so it is
245
+ * chosen after they are in. What the
237
246
  * returned promise settles behind is the reach, which is what the caller's
238
247
  * `renderComplete` means by "the pages on screen have finished trying to
239
248
  * paint" — and **it never rejects**, because `start` swallows a page the
@@ -241,8 +250,8 @@ export let stage = () => {
241
250
  */
242
251
  swap: async (next, faces) => {
243
252
  // Reading the offsets flushes layout, so only an actual reswap pays for
244
- // it: on an empty sheet there is nothing scrolled to preserve.
245
- let held = sheetEl.firstChild && {
253
+ // it: with no list standing there is nothing scrolled to preserve.
254
+ let held = paged.count() > 0 && {
246
255
  top: scroll.scrollTop,
247
256
  left: scroll.scrollLeft,
248
257
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quario/viewer",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "The embeddable report viewer shell for quario — in the makings, not yet released",
5
5
  "homepage": "https://getquario.com",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -44,8 +44,8 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@lit/task": "^1.0.3",
47
- "@quario/landing": "^0.1.0",
48
- "@quario/layout": "^0.4.0",
47
+ "@quario/landing": "^0.2.0",
48
+ "@quario/layout": "^0.5.0",
49
49
  "lit": "^3.3.3"
50
50
  },
51
51
  "devDependencies": {
@@ -54,12 +54,12 @@
54
54
  "@size-limit/preset-small-lib": "^13.0.3",
55
55
  "esbuild": "^0.28.2",
56
56
  "exceljs": "^4.4.0",
57
- "quario": "^0.7.0",
57
+ "quario": "^0.8.0",
58
58
  "size-limit": "^13.0.3",
59
59
  "typescript": "^7.0.2"
60
60
  },
61
61
  "peerDependencies": {
62
- "quario": "^0.7.0"
62
+ "quario": "^0.8.0"
63
63
  },
64
64
  "size-limit": [
65
65
  {