@hueest/xray 0.1.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/dist/breakpoints-CBNlh7lQ.js +47 -0
- package/dist/client.d.ts +42 -0
- package/dist/client.js +354 -0
- package/dist/core.d.ts +55 -0
- package/dist/core.js +230 -0
- package/dist/hud.d.ts +18 -0
- package/dist/hud.js +165 -0
- package/dist/index.d.ts +317 -0
- package/dist/index.js +726 -0
- package/dist/plate-BuzRMPx4.js +94 -0
- package/dist/plate-DboxMKg-.d.ts +196 -0
- package/dist/react.core-CqnDjfAJ.js +59 -0
- package/dist/react.core-fgWG_svU.d.ts +21 -0
- package/dist/react.d.ts +29 -0
- package/dist/react.dev.d.ts +19 -0
- package/dist/react.dev.js +101 -0
- package/dist/react.js +58 -0
- package/dist/serialize-Bq6yJnNV.js +1071 -0
- package/dist/serialize.d.ts +88 -0
- package/dist/serialize.js +2 -0
- package/package.json +95 -0
- package/virtual.d.ts +53 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { n as MergedPlate, s as ViewCapture, t as LeafKind } from "./plate-DboxMKg-.js";
|
|
2
|
+
|
|
3
|
+
//#region src/serialize.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Browser-side capture: walk a live rendered subtree into a Plate — one node
|
|
6
|
+
* tree plus one self-contained, scoped CSS string (ADR 0003). The CSS is
|
|
7
|
+
* lifted from the author rules that matched each node, rewritten to
|
|
8
|
+
* plate-local selectors — it carries `@media` for free and keeps layout live
|
|
9
|
+
* (the M1 bake-off winner; ADR 0005).
|
|
10
|
+
*/
|
|
11
|
+
interface CaptureOptions {
|
|
12
|
+
/** Plate name; comes from the virtual-module specifier. */
|
|
13
|
+
name: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Capture the rendered subtree(s) under a Skeleton into a Plate. `roots` are
|
|
17
|
+
* the component's top-level elements (the children of the layout-neutral
|
|
18
|
+
* wrapper); the synthetic root node (id 0) stands in for the wrapper itself.
|
|
19
|
+
*/
|
|
20
|
+
declare function capture(roots: readonly Element[], options: CaptureOptions): MergedPlate;
|
|
21
|
+
/**
|
|
22
|
+
* Thrown when a subtree has more nodes than the capture limit — almost always
|
|
23
|
+
* a `<Skeleton>` sitting too high in the tree. Raised after the cheap walk and
|
|
24
|
+
* before the O(rules × nodes) CSS extraction, so an oversized capture is
|
|
25
|
+
* refused without freezing the main thread on it.
|
|
26
|
+
*/
|
|
27
|
+
declare class CaptureTooLargeError extends Error {
|
|
28
|
+
readonly nodeCount: number;
|
|
29
|
+
constructor(nodeCount: number);
|
|
30
|
+
}
|
|
31
|
+
interface CaptureRegimeOptions {
|
|
32
|
+
/** Refuse (throw `CaptureTooLargeError`) before CSS extraction if the walk exceeds this. */
|
|
33
|
+
maxNodes?: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Capture one view's worth of a component: the tree plus id-form rules,
|
|
37
|
+
* with the viewport width it was taken at. The caller (the dev client)
|
|
38
|
+
* derives the view interval and ships it off; `capture` is the
|
|
39
|
+
* single-view convenience on top.
|
|
40
|
+
*/
|
|
41
|
+
declare function captureRegime(roots: readonly Element[], options?: CaptureRegimeOptions): ViewCapture;
|
|
42
|
+
/** One measurement per walked node, ids matching what `capture` assigns. */
|
|
43
|
+
interface AuditEntry {
|
|
44
|
+
id: number;
|
|
45
|
+
tag: string;
|
|
46
|
+
leaf?: LeafKind;
|
|
47
|
+
w: number;
|
|
48
|
+
h: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Walk a live subtree exactly like `capture` does, but return per-node
|
|
52
|
+
* geometry instead of a plate. Rendering the captured plate and auditing both
|
|
53
|
+
* sides gives an id-aligned fidelity diff (used by the M1 bake-off).
|
|
54
|
+
*/
|
|
55
|
+
declare function audit(roots: readonly Element[]): AuditEntry[];
|
|
56
|
+
/**
|
|
57
|
+
* Shrink a text run's measured box to what's actually painted. A `Range`'s
|
|
58
|
+
* rect is the text's full geometry and ignores ancestor clipping, so a
|
|
59
|
+
* `-webkit-line-clamp` box (fewer lines than the text fills) or a single-line
|
|
60
|
+
* `text-overflow: ellipsis` (`white-space: nowrap; overflow: hidden`) makes the
|
|
61
|
+
* bar over-measure — a 2-line title bone rendered at its unclamped 5-line
|
|
62
|
+
* height. Painted text can't exceed any clipping ancestor's content box, so we
|
|
63
|
+
* intersect with each: per axis the ancestor clips (`overflow !== visible`),
|
|
64
|
+
* clamp to its content box. A non-clipping or larger ancestor leaves it be, so
|
|
65
|
+
* unclamped text is untouched. Walks to the root since the clamp may sit a few
|
|
66
|
+
* inline wrappers up from the text node.
|
|
67
|
+
*/
|
|
68
|
+
interface ClippingStyle {
|
|
69
|
+
overflowX: string;
|
|
70
|
+
overflowY: string;
|
|
71
|
+
paddingTop: string;
|
|
72
|
+
paddingBottom: string;
|
|
73
|
+
paddingLeft: string;
|
|
74
|
+
paddingRight: string;
|
|
75
|
+
borderTopWidth: string;
|
|
76
|
+
borderBottomWidth: string;
|
|
77
|
+
borderLeftWidth: string;
|
|
78
|
+
borderRightWidth: string;
|
|
79
|
+
}
|
|
80
|
+
interface ClippingWindow {
|
|
81
|
+
getComputedStyle(element: Element): ClippingStyle;
|
|
82
|
+
}
|
|
83
|
+
declare function clampToClipping(width: number, height: number, fromParent: Element | null, win: ClippingWindow): {
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
export { AuditEntry, CaptureOptions, CaptureRegimeOptions, CaptureTooLargeError, audit, capture, captureRegime, clampToClipping };
|
package/package.json
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hueest/xray",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Auto-captured skeleton loading screens for Vite — capture the structure, ship the plate.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"loading",
|
|
7
|
+
"placeholder",
|
|
8
|
+
"skeleton",
|
|
9
|
+
"skeleton-screen",
|
|
10
|
+
"vite",
|
|
11
|
+
"vite-plugin"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://xray-js.dev",
|
|
14
|
+
"bugs": "https://github.com/hueest/xray/issues",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "Stefan Maric",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/hueest/xray.git"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"virtual.d.ts"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./core": {
|
|
34
|
+
"types": "./dist/core.d.ts",
|
|
35
|
+
"import": "./dist/core.js"
|
|
36
|
+
},
|
|
37
|
+
"./react": {
|
|
38
|
+
"types": "./dist/react.d.ts",
|
|
39
|
+
"import": "./dist/react.js"
|
|
40
|
+
},
|
|
41
|
+
"./react/dev": {
|
|
42
|
+
"types": "./dist/react.dev.d.ts",
|
|
43
|
+
"import": "./dist/react.dev.js"
|
|
44
|
+
},
|
|
45
|
+
"./serialize": {
|
|
46
|
+
"types": "./dist/serialize.d.ts",
|
|
47
|
+
"import": "./dist/serialize.js"
|
|
48
|
+
},
|
|
49
|
+
"./client": {
|
|
50
|
+
"types": "./dist/client.d.ts",
|
|
51
|
+
"import": "./dist/client.js"
|
|
52
|
+
},
|
|
53
|
+
"./hud": {
|
|
54
|
+
"types": "./dist/hud.d.ts",
|
|
55
|
+
"import": "./dist/hud.js"
|
|
56
|
+
},
|
|
57
|
+
"./virtual": {
|
|
58
|
+
"types": "./virtual.d.ts"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "25.9.3",
|
|
66
|
+
"@types/react": "19.2.17",
|
|
67
|
+
"@types/react-dom": "19.2.3",
|
|
68
|
+
"@typescript/native-preview": "7.0.0-dev.20260619.1",
|
|
69
|
+
"happy-dom": "20.10.6",
|
|
70
|
+
"react": "19.2.7",
|
|
71
|
+
"react-dom": "19.2.7",
|
|
72
|
+
"tsdown": "0.22.3",
|
|
73
|
+
"typescript": "6.0.3",
|
|
74
|
+
"vite": "8.0.16",
|
|
75
|
+
"vitest": "4.1.9"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
79
|
+
"vite": ">=7"
|
|
80
|
+
},
|
|
81
|
+
"peerDependenciesMeta": {
|
|
82
|
+
"react": {
|
|
83
|
+
"optional": true
|
|
84
|
+
},
|
|
85
|
+
"vite": {
|
|
86
|
+
"optional": true
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"scripts": {
|
|
90
|
+
"build": "tsdown",
|
|
91
|
+
"dev": "tsdown --watch",
|
|
92
|
+
"test": "vitest run",
|
|
93
|
+
"test:watch": "vitest"
|
|
94
|
+
}
|
|
95
|
+
}
|
package/virtual.d.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type declarations for xray virtual modules.
|
|
3
|
+
*
|
|
4
|
+
* Reference from the consuming app, e.g. in tsconfig:
|
|
5
|
+
* `"types": ["@hueest/xray/virtual"]`, or per file:
|
|
6
|
+
* `/// <reference types="@hueest/xray/virtual" />`.
|
|
7
|
+
*
|
|
8
|
+
* @module @hueest/xray/virtual
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Import a committed or not-yet-captured Plate by name.
|
|
13
|
+
*
|
|
14
|
+
* The import specifier is the Plate identity: `virtual:xray/plates/my-banner`
|
|
15
|
+
* reads and writes `plates/my-banner.json`, and that name travels with the
|
|
16
|
+
* imported Plate. Pass the imported Plate to `<Skeleton>`; do not repeat the
|
|
17
|
+
* name in props.
|
|
18
|
+
*
|
|
19
|
+
* If the file does not exist yet, the Vite plugin resolves an empty Plate with
|
|
20
|
+
* the same name so `<Skeleton fallback={...}>` can render until the first
|
|
21
|
+
* Capture writes the file. Nested `<Skeleton>` boundaries become Stitches; the
|
|
22
|
+
* generated virtual module wires child Plates into `Plate.refs`, so production
|
|
23
|
+
* rendering follows the static import graph with no global registry.
|
|
24
|
+
*
|
|
25
|
+
* Captured Plate files are source artifacts. Commit files under `plates/` with
|
|
26
|
+
* the component change they describe.
|
|
27
|
+
*/
|
|
28
|
+
declare module 'virtual:xray/plates/*' {
|
|
29
|
+
import type { Plate } from '@hueest/xray'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The captured Plate named by the `virtual:xray/plates/<name>` import specifier.
|
|
33
|
+
*
|
|
34
|
+
* Enable this import in a consuming app with
|
|
35
|
+
* `"types": ["@hueest/xray/virtual"]` in tsconfig, or with a per-file
|
|
36
|
+
* `/// <reference types="@hueest/xray/virtual" />` directive.
|
|
37
|
+
*
|
|
38
|
+
* The specifier maps to a file under `plates/`; for example,
|
|
39
|
+
* `virtual:xray/plates/my-banner` maps to `plates/my-banner.json`. If that
|
|
40
|
+
* file does not exist yet, the plugin returns an empty Plate with the same
|
|
41
|
+
* name so a `<Skeleton fallback={...}>` can render until the first Capture.
|
|
42
|
+
* Pass the imported Plate to `<Skeleton>`; do not repeat the name in props.
|
|
43
|
+
*
|
|
44
|
+
* Child Plates referenced by Stitches are wired into `Plate.refs` by the
|
|
45
|
+
* generated virtual module. Production rendering follows that static import
|
|
46
|
+
* graph with no global Plate registry or runtime name lookup.
|
|
47
|
+
*
|
|
48
|
+
* Captured Plate files are source artifacts. Commit them with the component
|
|
49
|
+
* change they describe.
|
|
50
|
+
*/
|
|
51
|
+
const plate: Plate
|
|
52
|
+
export default plate
|
|
53
|
+
}
|