@hueest/xray 0.6.0 → 0.7.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stefan Maric
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Auto-captured skeleton loading screens for [Vite](https://vite.dev). Capture the structure, ship the plate.
4
4
 
5
- xray captures the **real rendered DOM** of your components as you browse your own dev server, then renders pixel-faithful skeleton loading states from those captures no hand-drawn placeholders, no separate headless browser, no fixed-height/absolute hacks.
5
+ xray captures the **real rendered DOM** of your components as you browse your dev server, then renders faithful skeleton loading states from those captures. Placeholders are captured rather than hand-drawn, with no separate headless browser and no fixed-height hacks.
6
6
 
7
- > Beta APIs may still move before 1.0. Docs, guides, and the API reference live at
7
+ > Beta: APIs may move before 1.0. Docs, guides, and the API reference live at
8
8
  > **[xray-js.dev](https://xray-js.dev)**; source and issues at
9
9
  > [github.com/hueest/xray](https://github.com/hueest/xray).
10
10
 
@@ -35,22 +35,24 @@ import plate from 'virtual:xray/plates/my-banner'
35
35
  </Skeleton>
36
36
  ```
37
37
 
38
- To eyeball skeletons without waiting on loading states, tick **Light Box**
39
- in the HUD (or open the page with `?xray-lightbox`) every
40
- mounted `<Skeleton>` flips to its skeleton until you untick it.
38
+ To inspect skeletons without waiting on loading states, tick **Light Box**
39
+ in the HUD (or open the page with `?xray-lightbox`); every mounted
40
+ `<Skeleton>` flips to its skeleton until unticked.
41
41
 
42
- Capture starts off: tick **Capture** in the HUD (or pass `capture: true` to
43
- `xrayVitePlugin`) to start writing Plates as you browse. With Capture on, browse
44
- your dev server and captures land in `plates/` (commit them). Resize to
45
- capture other views JS-driven layout differences merge into the one plate
46
- as `display:none` projections. Add `"@hueest/xray/virtual"` to your tsconfig `types`
47
- for the `virtual:xray/plates/*` imports.
42
+ Capture starts off. Tick **Capture** in the HUD (or pass `capture: true` to
43
+ `xrayVitePlugin`) to start writing Plates as you browse. With Capture on,
44
+ captures land in `plates/` (commit them). Resize to capture other views: each
45
+ width lands as its own View, carried whole in the one plate and gated by
46
+ `@media display:none` (JS-driven structure differences become Projections).
47
+ Add `"@hueest/xray/virtual"` to the tsconfig `types` for the
48
+ `virtual:xray/plates/*` imports.
48
49
 
49
50
  ## Learn more
50
51
 
51
52
  - **[xray-js.dev](https://xray-js.dev)** — the docs site: how it works, the
52
53
  radiographic mental model (Plate / Capture / Stitch / View / Projection / Light
53
- Box), and guides for responsive Views, the HUD & Light Box, and capture-all-views.
54
+ Box), and guides for responsive Views, the HUD & Light Box, capture-all-views,
55
+ and theming.
54
56
  - **[xray-js.dev/reference/api/xray](https://xray-js.dev/reference/api/xray)** —
55
57
  full API reference, generated from source.
56
58
  - **[GitHub](https://github.com/hueest/xray)** — source, issues, and the
package/dist/client.d.ts CHANGED
@@ -1,25 +1,22 @@
1
- import { b as CaptureDiagnostic, g as StoredPlate, o as CollectLimits } from "./serialize-BqbQVxYl.js";
2
-
1
+ import { b as CaptureDiagnostic, g as StoredPlate, o as CollectLimits } from "./measure-CUQxB-Ic.js";
3
2
  //#region src/client.d.ts
4
3
  /**
5
- * The dev capture client (M2). Runs in the browser during dev only: installs
6
- * the `__XRAY__` hook `<Skeleton>` calls when content becomes ready, settles,
7
- * measures the subtree into a per-Plate `PlateIR`, projects it to the structured
8
- * `StoredPlate` in the browser (the ADR 0022 in-browser Serialize), and hands the
9
- * envelope to the sink (the plugin's POST endpoint). Re-captures when the viewport
10
- * crosses into another view while a site is still mounted.
4
+ * The dev capture client. Runs in the browser during dev only: installs the `__XRAY__` hook
5
+ * `<Skeleton>` calls when content becomes ready, settles, measures the subtree into a per-Plate
6
+ * `PlateIR`, projects it to the structured `StoredPlate` in the browser (the ADR 0022 in-browser
7
+ * Serialize), and hands the envelope to the sink (the plugin's POST endpoint). Re-captures when the
8
+ * viewport crosses into another view while a site is still mounted.
11
9
  *
12
- * Two paths produce a Plate. BROWSE-TIME is a RECORDING SESSION (the Capture toggle):
13
- * while on, each capture accumulates a View into a name-keyed `PlateIR` buffer
14
- * (deduped per breakpoint band) and live-previews it in-memory; toggling off writes
15
- * each accumulated Plate to the sink ONCE. The capture-all SWEEP threads ONE `PlateIR`
16
- * through every emulated width (one View each) and posts the projected StoredPlate once.
10
+ * Two paths produce a Plate. BROWSE-TIME is a CAPTURE SESSION (the Capture toggle): while on, each
11
+ * capture accumulates a View into a name-keyed `PlateIR` buffer (deduped per breakpoint band) and
12
+ * live-previews it in-memory; toggling off writes each accumulated Plate to the sink ONCE. The
13
+ * capture-all SWEEP threads ONE `PlateIR` through every emulated width (one View each) and posts
14
+ * the projected StoredPlate once.
17
15
  */
18
16
  /**
19
- * The `/__xray` POST envelope (ADR 0022 cutover). `plate` is the finished,
20
- * in-browser-projected `StoredPlate` written to disk as-is; `diagnostics` is a
21
- * SIBLING dev-only field the server logs and drops — it NEVER reaches the stored
22
- * artifact (ADR 0008).
17
+ * The `/__xray` POST envelope (ADR 0022). `plate` is the finished, in-browser-projected
18
+ * `StoredPlate` written to disk as-is; `diagnostics` is a SIBLING dev-only field the server logs
19
+ * and drops — it NEVER reaches the stored artifact (ADR 0008).
23
20
  */
24
21
  interface CaptureEnvelope {
25
22
  plate: StoredPlate;
@@ -29,59 +26,53 @@ interface ClientOptions {
29
26
  /** Settle delay (ms) once the subtree goes quiet. Default 200. */
30
27
  delay?: number;
31
28
  /**
32
- * Upper bound (ms) on waiting for quiet before capturing anyway. Raise it
33
- * for pages that stream content for a long time. Default 5000.
29
+ * Upper bound (ms) on waiting for quiet before capturing anyway. Raise it for pages that stream
30
+ * content for a long time. Default 5000.
34
31
  */
35
32
  settleCap?: number;
36
33
  /**
37
- * Collect limits (ADR 0022): refuse a capture whose measured tree exceeds any
38
- * axis — that big means the Skeleton sits too high in the component tree.
39
- * `maxNodes` caps total surviving nodes (default 4096), `maxBreadth` the widest
40
- * level (default 512), `maxDepth` the nesting depth (default 32). When `maxNodes`
41
- * is omitted it derives as `round(maxBreadth × maxDepth / 4)`.
34
+ * Collect limits (ADR 0022): refuse a capture whose measured tree exceeds any axis — that big
35
+ * means the Skeleton sits too high in the component tree. `maxNodes` caps total surviving nodes
36
+ * (default 4096), `maxBreadth` the widest level (default 512), `maxDepth` the nesting depth
37
+ * (default 32). When `maxNodes` is omitted it derives as `round(maxBreadth × maxDepth / 4)`.
42
38
  */
43
39
  collect?: CollectLimits;
44
40
  /**
45
- * Initial state of the capture toggle: whether the recording session is active
46
- * at boot. A per-tab override (sessionStorage / `?xray-capture`) wins over it.
47
- * Defaults to `false` — recording is explicit opt-in (turn it on, browse/resize to
48
- * accumulate Views, turn it off to write), so normal browsing never accumulates and
49
- * an HMR/close can't drop an unsaved recording. The plugin passes the same
50
- * off-by-default policy; a direct caller can pass `true` to capture on boot.
41
+ * Initial state of the capture toggle: whether the capture session is active at boot. A per-tab
42
+ * override (sessionStorage / `?xray-capture`) wins over it. Defaults to `false` — capturing is
43
+ * explicit opt-in (turn it on, browse/resize to accumulate Views, turn it off to write), so
44
+ * normal browsing never accumulates and an HMR/close can't drop an unsaved session. The plugin
45
+ * passes the same off-by-default policy; a direct caller can pass `true` to capture on boot.
51
46
  */
52
47
  capture?: boolean;
53
48
  /**
54
- * Where finished captures go. May be synchronous (fire-and-forget) or return
55
- * a promise that resolves once the write is server-confirmed. Browse-time
56
- * capture ignores the return value; the capture-all sweep awaits it so it
57
- * does not advance to the next emulated width until the current writes have
58
- * been accepted by the dev server (backpressure — capture-all-backpressure plan).
49
+ * Where finished captures go. May be synchronous (fire-and-forget) or return a promise that
50
+ * resolves once the write is server-confirmed. Browse-time capture ignores the return value; the
51
+ * capture-all sweep awaits it so it does not advance to the next emulated width until the current
52
+ * writes have been accepted by the dev server (backpressure).
59
53
  */
60
54
  sink: (envelope: CaptureEnvelope) => void | Promise<void>;
61
55
  /**
62
- * Re-pull the on-disk per-plate coverage and feed it into the coverage store.
63
- * The capture-all sweep calls this after each pass so the next `sweepWidths()`
64
- * sees the breakpoints just written by that pass, rather than racing the
65
- * async `xray:plate` HMR event (coverage freshness capture-all-backpressure
66
- * plan). Optional: browse-time capture never needs it, and the unit tests
67
- * drive coverage directly through the store.
56
+ * Re-pull the on-disk per-plate coverage and feed it into the coverage store. The capture-all
57
+ * sweep calls this after each pass so the next `sweepWidths()` sees the breakpoints just written
58
+ * by that pass, rather than racing the async `xray:plate` HMR event. Optional: browse-time
59
+ * capture never needs it, and the unit tests drive coverage directly through the store.
68
60
  */
69
61
  refreshCoverage?: () => void | Promise<void>;
70
62
  /**
71
- * Fixtures boot state (ADR 0015). `record` is when to write the live `data` to a
72
- * sidecar (`'manual'` — HUD button only, the default; `'first-ready'`; or
73
- * `'always'`); `replay` is whether to substitute a recorded Fixture for live
74
- * `data` (`false`, `'prefer'`, or `'missing-only'`). The HUD overrides the
75
- * replay toggle per tab. Absent ≡ defaults (`'manual'` / `false`).
63
+ * Fixtures boot state (ADR 0015). `record` is when to write the live `data` to a sidecar
64
+ * (`'manual'` — HUD button only, the default; `'first-ready'`; or `'always'`); `replay` is
65
+ * whether to substitute a recorded Fixture for live `data` (`false`, `'prefer'`, or
66
+ * `'missing-only'`). The HUD overrides the replay toggle per tab. Absent ≡ defaults (`'manual'` /
67
+ * `false`).
76
68
  */
77
69
  record?: 'manual' | 'first-ready' | 'always';
78
70
  replay?: false | 'prefer' | 'missing-only';
79
71
  /**
80
- * Where a recorded Fixture's OPAQUE devalue string is POSTed (the sidecar write
81
- * endpoint). The client owns the devalue stringify; this only ships the bytes.
82
- * Resolves once the write is server-confirmed, rejects on a non-2xx so the HUD
83
- * Record button can surface a failed write. Absent ≡ Record is a no-op (the
84
- * unit tests inject their own).
72
+ * Where a recorded Fixture's OPAQUE devalue string is POSTed (the sidecar write endpoint). The
73
+ * client owns the devalue stringify; this only ships the bytes. Resolves once the write is
74
+ * server-confirmed, rejects on a non-2xx so the HUD Record button can surface a failed write.
75
+ * Absent ≡ Record is a no-op (the unit tests inject their own).
85
76
  */
86
77
  recordFixtureSink?: (payload: {
87
78
  name: string;